feat(control-ui): upload files into terminals (#107364)

* feat(control-ui): add terminal file uploads

* fix(control-ui): protect Windows terminal uploads

* fix(control-ui): satisfy terminal upload gates

* chore(ui): translate terminal upload labels

* fix(control-ui): reject unknown Windows upload shells

* fix(control-ui): harden Windows upload paths

* fix(control-ui): retry terminal upload cleanup

* chore(ui): reconcile locale translation memory

* fix(control-ui): validate terminal upload inputs

* fix(control-ui): retry failed upload cleanup

* chore(ui): refresh terminal upload locale metadata

* fix(terminal): integrate uploads with session recovery

* refactor(control-ui): isolate terminal upload transport

* fix(control-ui): keep upload helper types private
This commit is contained in:
Peter Steinberger 2026-07-14 09:33:39 -07:00 committed by GitHub
parent 4ea573edd2
commit 084d1d9637
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
98 changed files with 1946 additions and 275 deletions

View file

@ -365,6 +365,7 @@ enum class GatewayMethod(
EnvironmentsDestroy("environments.destroy"),
SessionsCatalogList("sessions.catalog.list"),
SessionsCatalogRead("sessions.catalog.read"),
TerminalUpload("terminal.upload"),
SessionsCatalogContinue("sessions.catalog.continue"),
SessionsCatalogArchive("sessions.catalog.archive"),
ApprovalGet("approval.get"),

View file

@ -11075,6 +11075,46 @@ public struct TerminalTextResult: Codable, Sendable {
}
}
public struct TerminalUploadParams: Codable, Sendable {
public let sessionid: String
public let name: String
public let contentbase64: String
public init(
sessionid: String,
name: String,
contentbase64: String)
{
self.sessionid = sessionid
self.name = name
self.contentbase64 = contentbase64
}
private enum CodingKeys: String, CodingKey {
case sessionid = "sessionId"
case name
case contentbase64 = "contentBase64"
}
}
public struct TerminalUploadResult: Codable, Sendable {
public let path: String
public let size: Int
public init(
path: String,
size: Int)
{
self.path = path
self.size = size
}
private enum CodingKeys: String, CodingKey {
case path
case size
}
}
public struct TerminalAckResult: Codable, Sendable {
public let ok: Bool

View file

@ -4887,6 +4887,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
- H3: Codex sessions and transcripts
- H3: Claude sessions and transcripts
- H3: OpenCode and Pi sessions
- H3: Terminal file uploads
- H2: Invoking commands
- H2: Command policy
- H2: Config (openclaw.json)

View file

@ -456,6 +456,7 @@ methods. Treat this as feature discovery, not a full enumeration of
<Accordion title="Operator terminal">
- `terminal.open` starts a host PTY for an explicit `agentId` or the default agent and returns the resolved agent, working directory, shell, and confinement state.
- `terminal.input`, `terminal.resize`, and `terminal.close` operate only on sessions owned by the calling connection.
- `terminal.upload` accepts one base64 file up to 16 MiB, stages it in a private 24-hour temporary directory on the session's Gateway or paired-node host, and returns the absolute path. The caller must still paste or otherwise use that path; the RPC never writes terminal input or executes a command.
- `terminal.data` and `terminal.exit` events stream only to the connection that owns the session.
- Sessions whose connection drops are detached, not killed: they stay reattachable for `gateway.terminal.detachedSessionTimeoutSeconds` (default 300; `0` restores kill-on-disconnect) while recent output accumulates in a bounded server-side buffer.
- `terminal.list` returns attachable sessions; `terminal.attach` rebinds a live-or-detached session to the calling connection and returns the replay buffer (tmux-style take-over — a previous live owner receives `terminal.exit` with reason `detached`); `terminal.text` reads the buffer as plain text without attaching.

View file

@ -403,6 +403,12 @@ Terminal resume uses the stored session working directory and the same
allowlisted duplex PTY relay as Codex and Claude. It does not expose arbitrary
node command execution.
### Terminal file uploads
The Control UI can drag files into an open paired-node terminal. The native node host advertises the admin-only `terminal.upload` command; approve the pairing upgrade when it first appears. Each file is limited to 16 MiB, staged in a private temporary directory on that node, and returned to the terminal as a shell-quoted path without executing it.
Path insertion supports PowerShell, `cmd.exe`, and recognized POSIX shells (`sh`, Bash, Dash, Ash, Ksh, Zsh, and Fish), including Git Bash on Windows. Other shell overrides are refused because their quoting rules cannot be inferred safely; run the node host inside WSL for native WSL paths. `cmd.exe` paths containing `%` or `!` are also refused because that shell expands those characters even inside double quotes.
## Invoking commands
Low-level (raw RPC):

View file

@ -319,9 +319,13 @@ The terminal is an unconfined host shell and inherits the Gateway process enviro
Use **Ctrl + backtick** to toggle the dock. The layout supports bottom and right docking, resizes with the browser viewport, and keeps multiple shell tabs. See [Gateway configuration](/gateway/configuration-reference#gateway) for `gateway.terminal.enabled` and the optional `gateway.terminal.shell` override.
Drag one or more files onto the active terminal, or use the paperclip button to choose files. OpenClaw stages each file on the machine that owns the PTY and pastes shell-quoted absolute paths at the cursor; it never presses Enter or executes the input. Images, PDFs, archives, and other file types are accepted up to 16 MiB per file. Staged files use a private system-temporary directory on POSIX hosts (directory mode `0700`, file mode `0600`) or a directory under the user-profile ACL boundary on Windows, plus a 24-hour cleanup timer, so move or copy anything you need to keep.
Path insertion supports PowerShell, `cmd.exe`, and recognized POSIX shells (`sh`, Bash, Dash, Ash, Ksh, Zsh, and Fish), including Git Bash on Windows. Other shell overrides are refused because their quoting rules cannot be inferred safely; run the Gateway inside WSL for a native WSL terminal and Linux upload paths. `cmd.exe` paths containing `%` or `!` are also refused because that shell expands those characters even inside double quotes.
Codex and Claude Code sessions discovered in the sessions sidebar can open in their native CLI inside the same terminal panel. In **Settings Chat**, set **Open Codex/Claude sessions in** to **Terminal** to make a normal row click open `codex resume` or `claude --resume`; the default remains the read-only OpenClaw viewer. A row's right-click or kebab menu always offers both choices, and the viewer header includes **Open in terminal** when that session is eligible.
Eligibility is per session and per host. Gateway-local sessions start the provider-owned resume command on the Gateway host. Paired-node sessions start an allowlisted provider command on the owning node and relay only that PTY's output, input, and resize events; this does not expose a general node shell or accept browser-supplied commands. Nodes that do not advertise the matching terminal-resume command, including embedded worker bridges without duplex streaming, keep the viewer available and show terminal opening as unavailable.
Eligibility is per session and per host. Gateway-local sessions start the provider-owned resume command on the Gateway host. Paired-node sessions start an allowlisted provider command on the owning node and relay only that PTY's output, input, and resize events; this does not expose a general node shell or accept browser-supplied commands. File uploads use the separate, size-bounded `terminal.upload` node command and remain bound to the already-open terminal session. Approve the node pairing upgrade when that command first appears. Nodes that do not advertise the matching terminal-resume command, including embedded worker bridges without duplex streaming, keep the viewer available and show terminal opening as unavailable; older nodes can still run a terminal but cannot receive dragged files.
Sessions survive disconnects: a page reload, laptop sleep, or network blip detaches the session on the Gateway instead of killing it, and the same browser tab reattaches on reconnect with recent output replayed. Detached sessions are killed after `gateway.terminal.detachedSessionTimeoutSeconds` (default 300 seconds; `0` restores kill-on-disconnect). `terminal.list` shows attachable sessions, `terminal.attach` adopts one (tmux-style take-over), and `terminal.text` reads a session's recent output as plain text without attaching - an agent/tooling affordance.

View file

@ -1,4 +1,5 @@
export * from "./clawhub-trust-error-details.js";
export * from "./terminal-validators.js";
export { validateApprovalGetResult } from "./approval-result-validators.js";
export { validateApprovalResolveResult } from "./approval-result-validators.js";
import type { ValidationError } from "./validation-errors.js";
@ -266,6 +267,8 @@ import {
TerminalSessionInfoSchema,
TerminalTextParamsSchema,
TerminalTextResultSchema,
TerminalUploadParamsSchema,
TerminalUploadResultSchema,
ModelsListParamsSchema,
AuthProbeStatusSchema,
ModelsProbeParamsSchema,
@ -814,13 +817,6 @@ export const validateExecApprovalsNodeGetParams = lazyCompile(ExecApprovalsNodeG
export const validateExecApprovalsNodeSetParams = lazyCompile(ExecApprovalsNodeSetParamsSchema);
export const validateExecApprovalsNodeSnapshot = lazyCompile(ExecApprovalsNodeSnapshotSchema);
export const validateLogsTailParams = lazyCompile(LogsTailParamsSchema);
export const validateTerminalOpenParams = lazyCompile(TerminalOpenParamsSchema);
export const validateTerminalInputParams = lazyCompile(TerminalInputParamsSchema);
export const validateTerminalResizeParams = lazyCompile(TerminalResizeParamsSchema);
export const validateTerminalCloseParams = lazyCompile(TerminalCloseParamsSchema);
export const validateTerminalAttachParams = lazyCompile(TerminalAttachParamsSchema);
export const validateTerminalTextParams = lazyCompile(TerminalTextParamsSchema);
export const validateTerminalEvent = lazyCompile(TerminalEventSchema);
export const validateModelsProbeParams = lazyCompile(ModelsProbeParamsSchema);
export const validateChatHistoryParams = lazyCompile(ChatHistoryParamsSchema);
export const validateChatMetadataParams = lazyCompile(ChatMetadataParamsSchema);
@ -1211,6 +1207,8 @@ export {
TerminalListResultSchema,
TerminalTextParamsSchema,
TerminalTextResultSchema,
TerminalUploadParamsSchema,
TerminalUploadResultSchema,
TerminalAckResultSchema,
TerminalDataEventSchema,
TerminalExitEventSchema,
@ -1629,6 +1627,8 @@ export type {
TerminalOpenParams,
TerminalOpenResult,
TerminalInputParams,
TerminalUploadParams,
TerminalUploadResult,
TerminalResizeParams,
TerminalCloseParams,
TerminalAttachParams,

View file

@ -459,23 +459,7 @@ import {
TasksListResultSchema,
TaskSummarySchema,
} from "./tasks.js";
import {
TerminalAckResultSchema,
TerminalAttachParamsSchema,
TerminalAttachResultSchema,
TerminalCloseParamsSchema,
TerminalDataEventSchema,
TerminalEventSchema,
TerminalExitEventSchema,
TerminalInputParamsSchema,
TerminalListResultSchema,
TerminalOpenParamsSchema,
TerminalOpenResultSchema,
TerminalResizeParamsSchema,
TerminalSessionInfoSchema,
TerminalTextParamsSchema,
TerminalTextResultSchema,
} from "./terminal.js";
import { TerminalProtocolSchemas } from "./terminal-protocol-schemas.js";
import {
WizardCancelParamsSchema,
WizardNextParamsSchema,
@ -866,21 +850,7 @@ export const ProtocolSchemas = {
CronRunsParams: CronRunsParamsSchema,
CronRunLogEntry: CronRunLogEntrySchema,
...LogMigrationProtocolSchemas,
TerminalOpenParams: TerminalOpenParamsSchema,
TerminalOpenResult: TerminalOpenResultSchema,
TerminalInputParams: TerminalInputParamsSchema,
TerminalResizeParams: TerminalResizeParamsSchema,
TerminalCloseParams: TerminalCloseParamsSchema,
TerminalAttachParams: TerminalAttachParamsSchema,
TerminalAttachResult: TerminalAttachResultSchema,
TerminalSessionInfo: TerminalSessionInfoSchema,
TerminalListResult: TerminalListResultSchema,
TerminalTextParams: TerminalTextParamsSchema,
TerminalTextResult: TerminalTextResultSchema,
TerminalAckResult: TerminalAckResultSchema,
TerminalDataEvent: TerminalDataEventSchema,
TerminalExitEvent: TerminalExitEventSchema,
TerminalEvent: TerminalEventSchema,
...TerminalProtocolSchemas,
ApprovalKind: ApprovalKindSchema,
ApprovalDecision: ApprovalDecisionSchema,
ApprovalAllowDecision: ApprovalAllowDecisionSchema,

View file

@ -0,0 +1,39 @@
import {
TerminalAckResultSchema,
TerminalAttachParamsSchema,
TerminalAttachResultSchema,
TerminalCloseParamsSchema,
TerminalDataEventSchema,
TerminalEventSchema,
TerminalExitEventSchema,
TerminalInputParamsSchema,
TerminalListResultSchema,
TerminalOpenParamsSchema,
TerminalOpenResultSchema,
TerminalResizeParamsSchema,
TerminalSessionInfoSchema,
TerminalTextParamsSchema,
TerminalTextResultSchema,
TerminalUploadParamsSchema,
TerminalUploadResultSchema,
} from "./terminal.js";
export const TerminalProtocolSchemas = {
TerminalOpenParams: TerminalOpenParamsSchema,
TerminalOpenResult: TerminalOpenResultSchema,
TerminalInputParams: TerminalInputParamsSchema,
TerminalResizeParams: TerminalResizeParamsSchema,
TerminalCloseParams: TerminalCloseParamsSchema,
TerminalAttachParams: TerminalAttachParamsSchema,
TerminalAttachResult: TerminalAttachResultSchema,
TerminalSessionInfo: TerminalSessionInfoSchema,
TerminalListResult: TerminalListResultSchema,
TerminalTextParams: TerminalTextParamsSchema,
TerminalTextResult: TerminalTextResultSchema,
TerminalUploadParams: TerminalUploadParamsSchema,
TerminalUploadResult: TerminalUploadResultSchema,
TerminalAckResult: TerminalAckResultSchema,
TerminalDataEvent: TerminalDataEventSchema,
TerminalExitEvent: TerminalExitEventSchema,
TerminalEvent: TerminalEventSchema,
} as const;

View file

@ -1,5 +1,6 @@
import { describe, expect, it } from "vitest";
import { validateTerminalOpenParams } from "../index.js";
import { validateTerminalOpenParams, validateTerminalUploadParams } from "../index.js";
import { MAX_TERMINAL_UPLOAD_BASE64_LENGTH } from "../terminal-upload-constants.js";
describe("terminal protocol", () => {
it("accepts a typed catalog reference and rejects client command fields", () => {
@ -30,4 +31,29 @@ describe("terminal protocol", () => {
}),
).toBe(false);
});
it("bounds terminal uploads inside one gateway frame", () => {
expect(
validateTerminalUploadParams({
sessionId: "terminal-1",
name: "scan.pdf",
contentBase64: "AA==",
}),
).toBe(true);
expect(
validateTerminalUploadParams({
sessionId: "terminal-1",
name: "scan.pdf",
contentBase64: "A".repeat(MAX_TERMINAL_UPLOAD_BASE64_LENGTH + 1),
}),
).toBe(false);
expect(
validateTerminalUploadParams({
sessionId: "terminal-1",
name: "scan.pdf",
contentBase64: "AA==",
destination: "/etc",
}),
).toBe(false);
});
});

View file

@ -3,6 +3,11 @@
// operator connection and stream its bytes back over the existing WebSocket.
import type { Static } from "typebox";
import { Type } from "typebox";
import {
MAX_TERMINAL_UPLOAD_BASE64_LENGTH,
MAX_TERMINAL_UPLOAD_BYTES,
MAX_TERMINAL_UPLOAD_NAME_LENGTH,
} from "../terminal-upload-constants.js";
import { closedObject } from "./closed-object.js";
import { NonEmptyString } from "./primitives.js";
@ -48,6 +53,21 @@ export const TerminalInputParamsSchema = closedObject({
});
export type TerminalInputParams = Static<typeof TerminalInputParamsSchema>;
/** Stages one file on the host bound to an existing terminal session. */
export const TerminalUploadParamsSchema = closedObject({
sessionId: NonEmptyString,
name: Type.String({ minLength: 1, maxLength: MAX_TERMINAL_UPLOAD_NAME_LENGTH }),
contentBase64: Type.String({ maxLength: MAX_TERMINAL_UPLOAD_BASE64_LENGTH }),
});
export type TerminalUploadParams = Static<typeof TerminalUploadParamsSchema>;
/** Absolute temporary path pasted into the active terminal after upload. */
export const TerminalUploadResultSchema = closedObject({
path: NonEmptyString,
size: Type.Integer({ minimum: 0, maximum: MAX_TERMINAL_UPLOAD_BYTES }),
});
export type TerminalUploadResult = Static<typeof TerminalUploadResultSchema>;
/** Resizes the PTY grid after the client viewport changes. */
export const TerminalResizeParamsSchema = closedObject({
sessionId: NonEmptyString,

View file

@ -0,0 +1,60 @@
/** Maximum size of one file staged through the operator terminal. */
export const MAX_TERMINAL_UPLOAD_BYTES = 16 * 1024 * 1024;
/** Base64 expansion of MAX_TERMINAL_UPLOAD_BYTES. */
export const MAX_TERMINAL_UPLOAD_BASE64_LENGTH = Math.ceil(MAX_TERMINAL_UPLOAD_BYTES / 3) * 4;
/** Browser-provided file name bound before filesystem sanitization. */
export const MAX_TERMINAL_UPLOAD_NAME_LENGTH = 255;
function base64Value(code: number): number {
if (code >= 65 && code <= 90) {
return code - 65;
}
if (code >= 97 && code <= 122) {
return code - 71;
}
if (code >= 48 && code <= 57) {
return code + 4;
}
return code === 43 ? 62 : code === 47 ? 63 : -1;
}
export function terminalUploadDecodedSize(contentBase64: string): number {
if (contentBase64.length === 0) {
return 0;
}
const padding = contentBase64.endsWith("==") ? 2 : contentBase64.endsWith("=") ? 1 : 0;
return Math.floor(contentBase64.length / 4) * 3 - padding;
}
/** Validates canonical padded base64, including zero-valued unused bits. */
export function isCanonicalTerminalUploadBase64(contentBase64: string): boolean {
if (
contentBase64.length > MAX_TERMINAL_UPLOAD_BASE64_LENGTH ||
contentBase64.length % 4 !== 0 ||
terminalUploadDecodedSize(contentBase64) > MAX_TERMINAL_UPLOAD_BYTES
) {
return false;
}
const padding = contentBase64.endsWith("==") ? 2 : contentBase64.endsWith("=") ? 1 : 0;
const dataEnd = contentBase64.length - padding;
for (let index = 0; index < dataEnd; index += 1) {
if (base64Value(contentBase64.charCodeAt(index)) < 0) {
return false;
}
}
for (let index = dataEnd; index < contentBase64.length; index += 1) {
if (contentBase64.charCodeAt(index) !== 61) {
return false;
}
}
if (padding > 0) {
const finalValue = base64Value(contentBase64.charCodeAt(dataEnd - 1));
const unusedBitsMask = padding === 2 ? 0b1111 : 0b11;
if (finalValue < 0 || (finalValue & unusedBitsMask) !== 0) {
return false;
}
}
return true;
}

View file

@ -0,0 +1,22 @@
import { lazyCompile } from "./protocol-validator.js";
import {
TerminalAttachParamsSchema,
TerminalCloseParamsSchema,
TerminalEventSchema,
TerminalInputParamsSchema,
TerminalOpenParamsSchema,
TerminalResizeParamsSchema,
TerminalTextParamsSchema,
TerminalUploadParamsSchema,
TerminalUploadResultSchema,
} from "./schema/terminal.js";
export const validateTerminalOpenParams = lazyCompile(TerminalOpenParamsSchema);
export const validateTerminalInputParams = lazyCompile(TerminalInputParamsSchema);
export const validateTerminalResizeParams = lazyCompile(TerminalResizeParamsSchema);
export const validateTerminalCloseParams = lazyCompile(TerminalCloseParamsSchema);
export const validateTerminalAttachParams = lazyCompile(TerminalAttachParamsSchema);
export const validateTerminalTextParams = lazyCompile(TerminalTextParamsSchema);
export const validateTerminalUploadParams = lazyCompile(TerminalUploadParamsSchema);
export const validateTerminalUploadResult = lazyCompile(TerminalUploadResultSchema);
export const validateTerminalEvent = lazyCompile(TerminalEventSchema);

View file

@ -342,6 +342,7 @@ const CORE_GATEWAY_METHOD_SPECS: readonly CoreGatewayMethodSpec[] = [
},
{ name: "sessions.catalog.list", scope: "operator.read" },
{ name: "sessions.catalog.read", scope: "operator.read" },
{ name: "terminal.upload", scope: "operator.admin" },
{ name: "sessions.catalog.continue", scope: "operator.write" },
{ name: "sessions.catalog.archive", scope: "operator.write" },
{ name: "approval.get", scope: "operator.approvals" },

View file

@ -8,7 +8,7 @@ import {
NODE_AGENT_CLI_CLAUDE_RUN_COMMAND,
NODE_BROWSER_PROXY_COMMAND,
NODE_EXEC_APPROVALS_COMMANDS,
NODE_FS_LIST_DIR_COMMAND,
NODE_FILE_COMMANDS,
NODE_MCP_TOOLS_CALL_COMMAND,
NODE_SYSTEM_NOTIFY_COMMAND,
NODE_SYSTEM_RUN_COMMANDS,
@ -72,7 +72,7 @@ const IOS_SYSTEM_COMMANDS = [NODE_SYSTEM_NOTIFY_COMMAND];
const SYSTEM_COMMANDS = [
...NODE_SYSTEM_RUN_COMMANDS,
...NODE_EXEC_APPROVALS_COMMANDS,
NODE_FS_LIST_DIR_COMMAND,
...NODE_FILE_COMMANDS,
NODE_SYSTEM_NOTIFY_COMMAND,
NODE_BROWSER_PROXY_COMMAND,
NODE_MCP_TOOLS_CALL_COMMAND,
@ -81,7 +81,7 @@ const SYSTEM_COMMANDS = [
const DESKTOP_HOST_COMMANDS = new Set<string>([
...NODE_SYSTEM_RUN_COMMANDS,
...NODE_EXEC_APPROVALS_COMMANDS,
NODE_FS_LIST_DIR_COMMAND,
...NODE_FILE_COMMANDS,
NODE_BROWSER_PROXY_COMMAND,
NODE_MCP_TOOLS_CALL_COMMAND,
NODE_AGENT_CLI_CLAUDE_RUN_COMMAND,

View file

@ -1,4 +1,3 @@
// Gateway registry wires RPC descriptors to handlers, scopes, and budgets.
import { ErrorCodes, errorShape } from "../../packages/gateway-protocol/src/index.js";
import {
gatewayStartupUnavailableDetails,
@ -341,6 +340,7 @@ export const coreGatewayHandlers: GatewayRequestHandlers = {
"terminal.attach",
"terminal.list",
"terminal.text",
"terminal.upload",
],
loadHandlers: loadTerminalHandlers,
}),

View file

@ -11,34 +11,42 @@ import type { GatewayRequestHandlerOptions } from "./types.js";
type NodeCatalogTerminalPlan = Extract<SessionCatalogTerminalPlan, { kind: "node" }>;
export function authorizeCatalogTerminalNode(
export function authorizeTerminalNodeCommand(
context: GatewayRequestHandlerOptions["context"],
plan: NodeCatalogTerminalPlan,
nodeId: string,
command: string,
):
| { ok: true; node: NonNullable<ReturnType<typeof context.nodeRegistry.get>> }
| {
ok: false;
message: string;
} {
const node = context.nodeRegistry.get(plan.nodeId);
const node = context.nodeRegistry.get(nodeId);
if (!node) {
return { ok: false, message: "catalog terminal node is not connected" };
return { ok: false, message: "terminal node is not connected" };
}
if (!node.commands.includes(plan.command)) {
return { ok: false, message: "catalog terminal command is not available" };
if (!node.commands.includes(command)) {
return { ok: false, message: "terminal node command is not available" };
}
const allowlist = resolveNodeCommandAllowlist(context.getRuntimeConfig(), {
...node,
approvedCommands: node.commands,
});
const allowed = isNodeCommandAllowed({
command: plan.command,
command,
declaredCommands: node.commands,
allowlist,
});
return allowed.ok ? { ok: true, node } : { ok: false, message: allowed.reason };
}
export function authorizeCatalogTerminalNode(
context: GatewayRequestHandlerOptions["context"],
plan: NodeCatalogTerminalPlan,
) {
return authorizeTerminalNodeCommand(context, plan.nodeId, plan.command);
}
export function resolveTerminalOpenSpawnPlan(
launchPlan: TerminalLaunchPlan,
catalogPlan?: SessionCatalogTerminalPlan,

View file

@ -0,0 +1,64 @@
import {
ErrorCodes,
errorShape,
formatValidationErrors,
type TerminalUploadParams,
validateTerminalUploadParams,
} from "../../../packages/gateway-protocol/src/index.js";
import { isCanonicalTerminalUploadBase64 } from "../../../packages/gateway-protocol/src/terminal-upload-constants.js";
import type { GatewayRequestHandlerOptions, GatewayRequestHandlers } from "./types.js";
function invalid(respond: GatewayRequestHandlerOptions["respond"], detail: string): void {
respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, detail));
}
export const terminalUploadHandlers: GatewayRequestHandlers = {
"terminal.upload": async (opts) => {
const { params, respond, context } = opts;
if (!validateTerminalUploadParams(params)) {
invalid(
respond,
`invalid terminal.upload params: ${formatValidationErrors(validateTerminalUploadParams.errors)}`,
);
return;
}
const connId = opts.client?.connId;
if (!connId) {
invalid(respond, "terminal requires an authenticated connection");
return;
}
const p = params as TerminalUploadParams;
if (!isCanonicalTerminalUploadBase64(p.contentBase64)) {
invalid(respond, "invalid terminal.upload base64 content");
return;
}
if (!context.terminalSessions || !context.isTerminalEnabled()) {
respond(false, undefined, errorShape(ErrorCodes.UNAVAILABLE, "terminal is not available"));
return;
}
try {
const result = await context.terminalSessions.upload(connId, p.sessionId, {
name: p.name,
contentBase64: p.contentBase64,
});
if (!result) {
respond(
false,
undefined,
errorShape(ErrorCodes.INVALID_REQUEST, `unknown terminal session "${p.sessionId}"`),
);
return;
}
respond(true, result);
} catch (error) {
respond(
false,
undefined,
errorShape(
ErrorCodes.UNAVAILABLE,
error instanceof Error ? error.message : "terminal upload failed",
),
);
}
},
};

View file

@ -1,6 +1,7 @@
import { expectDefined } from "@openclaw/normalization-core";
import { afterEach, describe, expect, it, vi } from "vitest";
import { GATEWAY_CLIENT_CAPS } from "../../../packages/gateway-protocol/src/client-info.js";
import { ErrorCodes } from "../../../packages/gateway-protocol/src/index.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { createEmptyPluginRegistry } from "../../plugins/registry-empty.js";
import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../../plugins/runtime.js";
@ -39,10 +40,13 @@ function makeOpts(
params: unknown,
terminalConfig: { enabled?: boolean } | undefined,
terminalPolicyConfig?: OpenClawConfig,
nodeRegistry: { get: (nodeId: string) => unknown } = { get: () => undefined },
nodeRegistry: {
get: (nodeId: string) => unknown;
invoke?: (params: unknown) => Promise<unknown>;
} = { get: () => undefined },
) {
const sessions = {
open: vi.fn(async () => ({
open: vi.fn(async (_request: unknown) => ({
ok: true as const,
sessionId: "terminal-1",
agentId: "main",
@ -61,6 +65,7 @@ function makeOpts(
seq: 6,
})),
snapshot: vi.fn(() => "10%\r100%"),
upload: vi.fn(async () => ({ path: "/tmp/upload/report.pdf", size: 4 })),
};
const runtimeConfig = { gateway: { terminal: terminalConfig } } as OpenClawConfig;
const policy = createTerminalLaunchPolicy(runtimeConfig);
@ -76,7 +81,7 @@ function makeOpts(
resolveTerminalLaunchPolicy,
isTerminalEnabled,
terminalSessions: sessions,
nodeRegistry,
nodeRegistry: { invoke: vi.fn(), ...nodeRegistry },
isConnectionActive,
logGateway: { info: vi.fn() },
} as unknown as Parameters<(typeof terminalHandlers)["terminal.input"]>[0]["context"];
@ -376,7 +381,8 @@ describe("terminal gateway policy", () => {
}),
});
const node = { nodeId: "node-1", connId: "conn-node", commands: [command] };
const invoke = vi.fn((params: { onInvokeId?: (id: string) => void }) => {
const invoke = vi.fn((rawParams: unknown) => {
const params = rawParams as { onInvokeId?: (id: string) => void };
params.onInvokeId?.("invoke-1");
return Promise.resolve({ ok: true });
});
@ -455,7 +461,7 @@ describe("terminal gateway policy", () => {
expect(respond).toHaveBeenCalledWith(
false,
undefined,
expect.objectContaining({ message: "catalog terminal command is not available" }),
expect.objectContaining({ message: "terminal node command is not available" }),
);
});
@ -549,6 +555,91 @@ describe("terminal gateway policy", () => {
expect(respond).toHaveBeenCalledWith(true, { ok: false });
});
it("uploads a file through the owned terminal session", async () => {
const { opts, sessions, respond } = makeOpts(
{ sessionId: "s1", name: "report.pdf", contentBase64: "dGVzdA==" },
{ enabled: true },
);
await expectDefined(terminalHandlers["terminal.upload"], "terminal.upload")(opts);
expect(sessions.upload).toHaveBeenCalledWith("conn-1", "s1", {
name: "report.pdf",
contentBase64: "dGVzdA==",
});
expect(respond).toHaveBeenCalledWith(true, { path: "/tmp/upload/report.pdf", size: 4 });
});
it("rejects non-canonical base64 before staging", async () => {
const { opts, sessions, respond } = makeOpts(
{ sessionId: "s1", name: "report.pdf", contentBase64: "AB==" },
{ enabled: true },
);
await expectDefined(terminalHandlers["terminal.upload"], "terminal.upload")(opts);
expect(sessions.upload).not.toHaveBeenCalled();
expect(respond).toHaveBeenCalledWith(
false,
undefined,
expect.objectContaining({ code: ErrorCodes.INVALID_REQUEST }),
);
});
it("binds paired-node uploads to the catalog terminal host", async () => {
const command = "codex.terminal.resume.v1";
const uploadCommand = "terminal.upload";
installCatalog({
id: "codex",
label: "Codex",
list: async () => [],
read: async (request) => ({ ...request, items: [] }),
openTerminal: async () => ({
kind: "node",
nodeId: "node-1",
command,
paramsJSON: JSON.stringify({ threadId: "thread" }),
}),
});
const node = {
nodeId: "node-1",
connId: "conn-node",
commands: [command, uploadCommand],
};
const invoke = vi.fn(async () => ({
ok: true,
payloadJSON: JSON.stringify({ path: "/tmp/node/report.pdf", size: 4 }),
}));
const { opts, sessions } = makeOpts(
{
cols: 80,
rows: 24,
catalog: { catalogId: "codex", hostId: "node:node-1", threadId: "thread" },
},
{ enabled: true },
undefined,
{ get: () => node, invoke },
);
await expectDefined(terminalHandlers["terminal.open"], "terminal.open")(opts);
const openRequest = sessions.open.mock.calls[0]?.[0] as
| { stageUpload?: (file: { name: string; contentBase64: string }) => Promise<unknown> }
| undefined;
const result = await openRequest?.stageUpload?.({
name: "report.pdf",
contentBase64: "dGVzdA==",
});
expect(invoke).toHaveBeenCalledWith({
nodeId: "node-1",
expectedConnId: "conn-node",
command: uploadCommand,
params: { name: "report.pdf", contentBase64: "dGVzdA==" },
timeoutMs: 120_000,
});
expect(result).toEqual({ path: "/tmp/node/report.pdf", size: 4 });
});
it("sanitizes terminal snapshots before returning plain text", async () => {
const { opts, sessions, respond } = makeOpts({ sessionId: "s1" }, { enabled: true });
const finals = Array.from({ length: 0x7e - 0x40 + 1 }, (_, offset) =>

View file

@ -11,13 +11,17 @@ import {
errorShape,
formatValidationErrors,
type TerminalOpenParams,
type TerminalUploadResult,
validateTerminalAttachParams,
validateTerminalCloseParams,
validateTerminalInputParams,
validateTerminalOpenParams,
validateTerminalResizeParams,
validateTerminalTextParams,
validateTerminalUploadResult,
} from "../../../packages/gateway-protocol/src/index.js";
import { NODE_TERMINAL_UPLOAD_COMMAND } from "../../infra/node-commands.js";
import type { TerminalUploadFile } from "../../infra/terminal-file-upload.js";
import type { SessionCatalogTerminalPlan } from "../../plugins/session-catalog.js";
import { applyPluginNodeInvokePolicy } from "../node-invoke-plugin-policy.js";
import { renderTerminalBufferText } from "../terminal/buffer-text.js";
@ -26,8 +30,10 @@ import { createNodeRelayBackend } from "../terminal/node-relay.js";
import { resolveSessionCatalogProvider } from "./session-catalog.js";
import {
authorizeCatalogTerminalNode,
authorizeTerminalNodeCommand,
resolveTerminalOpenSpawnPlan,
} from "./terminal-open-plan.js";
import { terminalUploadHandlers } from "./terminal-upload.js";
import type { GatewayRequestHandlerOptions, GatewayRequestHandlers } from "./types.js";
function invalid(respond: GatewayRequestHandlerOptions["respond"], detail: string): void {
@ -47,6 +53,43 @@ function terminalEnabled(context: GatewayRequestHandlerOptions["context"]): bool
return context.isTerminalEnabled();
}
function parseNodePayload(payload: unknown, payloadJSON?: string | null): unknown {
if (!payloadJSON) {
return payload;
}
try {
return JSON.parse(payloadJSON) as unknown;
} catch {
return undefined;
}
}
async function stageNodeTerminalUpload(
context: GatewayRequestHandlerOptions["context"],
nodeId: string,
file: TerminalUploadFile,
): Promise<TerminalUploadResult> {
const access = authorizeTerminalNodeCommand(context, nodeId, NODE_TERMINAL_UPLOAD_COMMAND);
if (!access.ok) {
throw new Error(access.message);
}
const result = await context.nodeRegistry.invoke({
nodeId,
expectedConnId: access.node.connId,
command: NODE_TERMINAL_UPLOAD_COMMAND,
params: file,
timeoutMs: 120_000,
});
if (!result.ok) {
throw new Error(result.error?.message ?? "terminal node upload failed");
}
const payload = parseNodePayload(result.payload, result.payloadJSON);
if (!validateTerminalUploadResult(payload)) {
throw new Error("terminal node returned an invalid upload result");
}
return payload as TerminalUploadResult;
}
function respondLaunchBlocked(
respond: GatewayRequestHandlerOptions["respond"],
block: Extract<TerminalLaunchResolution, { ok: false }>["block"],
@ -76,6 +119,7 @@ function respondLaunchBlocked(
/** Handlers for the operator terminal method family. */
export const terminalHandlers: GatewayRequestHandlers = {
...terminalUploadHandlers,
"terminal.open": async (opts) => {
const { params, respond, context } = opts;
if (!validateTerminalOpenParams(params)) {
@ -110,6 +154,7 @@ export const terminalHandlers: GatewayRequestHandlers = {
params: Record<string, unknown>;
}
| undefined;
let stageUpload: ((file: TerminalUploadFile) => Promise<TerminalUploadResult>) | undefined;
if (p.catalog) {
const provider = resolveSessionCatalogProvider(p.catalog.catalogId);
if (!provider) {
@ -180,6 +225,8 @@ export const terminalHandlers: GatewayRequestHandlers = {
return;
}
nodeRelay = { plan: nodeCatalogPlan, params: nodeParams };
stageUpload = async (file) =>
await stageNodeTerminalUpload(context, nodeCatalogPlan.nodeId, file);
}
}
@ -223,6 +270,7 @@ export const terminalHandlers: GatewayRequestHandlers = {
rows: p.rows,
env: buildTerminalEnv(process.env),
...(createBackend ? { createBackend } : {}),
...(stageUpload ? { stageUpload } : {}),
});
if (!outcome.ok) {
const code = outcome.code === "limit" ? ErrorCodes.INVALID_REQUEST : ErrorCodes.UNAVAILABLE;

View file

@ -338,6 +338,25 @@ describe("TerminalSessionManager", () => {
expect(fake.writes).toEqual([]);
});
it("stages uploads only through the owning session host", async () => {
const fake = makeFakePty();
const stageUpload = vi.fn(async () => ({ path: "/tmp/node/report.pdf", size: 4 }));
const manager = new TerminalSessionManager({ emit: vi.fn(), spawn: async () => fake });
const outcome = await manager.open(baseRequest({ stageUpload }));
if (!outcome.ok) {
throw new Error("expected open");
}
const file = { name: "report.pdf", contentBase64: "dGVzdA==" };
await expect(manager.upload("conn-2", outcome.sessionId, file)).resolves.toBeUndefined();
expect(stageUpload).not.toHaveBeenCalled();
await expect(manager.upload("conn-1", outcome.sessionId, file)).resolves.toEqual({
path: "/tmp/node/report.pdf",
size: 4,
});
expect(stageUpload).toHaveBeenCalledWith(file);
});
it("emits an exit event and drops the session when the process exits", async () => {
const emit = vi.fn();
const fake = makeFakePty();

View file

@ -1,5 +1,11 @@
// Owns one PTY per operator connection and its gateway event lifecycle.
import { randomUUID } from "node:crypto";
import {
ensureTerminalUploadCleanup,
stageTerminalUpload,
type TerminalUploadFile,
type TerminalUploadResult,
} from "../../infra/terminal-file-upload.js";
import {
createLocalTerminalBackend,
type LocalTerminalBackendSpawner,
@ -15,59 +21,15 @@ import {
} from "./session-limits.js";
import type { TerminalAttachSummary, TerminalSessionSummary } from "./session-types.js";
export { DEFAULT_TERMINAL_DETACH_SECONDS } from "./session-limits.js";
/** Emits one terminal event frame to the single owning connection. */
type TerminalEventSink = (connId: string, event: string, payload: unknown) => void;
type TerminalExitReason = "process_exit" | "closed" | "disconnected" | "detached" | "error";
type TerminalSession = {
id: string;
/** Owning connection; null while the session is detached. */
connId: string | null;
agentId: string;
cwd: string;
shell: string;
backend: TerminalBackend;
closed: boolean;
createdAtMs: number;
buffer: TerminalOutputRing;
output: TerminalOutputController;
/** Kills the session when a detach outlives the grace period. */
reaper: ReturnType<typeof setTimeout> | null;
detachedAtMs: number | null;
};
type TerminalSessionManagerOptions = {
emit: TerminalEventSink;
getBufferedAmount?: (connId: string) => number | undefined;
spawn?: LocalTerminalBackendSpawner;
maxSessions?: number;
env?: NodeJS.ProcessEnv;
/** Detach grace; 0 preserves kill-on-disconnect. Gateway wiring owns its default. */
detachGraceMs?: number;
maxDetachedSessions?: number;
scrollbackChars?: number;
};
/** Parameters for a resolved host terminal launch (isolation already checked). */
type TerminalOpenRequest = {
connId: string;
agentId: string;
cwd: string;
shell: string;
args: string[];
cols: number;
rows: number;
env: Record<string, string>;
createBackend?: () => Promise<TerminalBackend>;
};
type TerminalOpenOutcome =
| { ok: true; sessionId: string; agentId: string; cwd: string; shell: string }
| { ok: false; code: "limit" | "spawn_failed" | "closed"; message: string };
/** Abort state shared between a pending open and lifecycle/policy teardown. */
type OpenToken = { agentId: string; abortMessage?: string };
import type {
TerminalEventSink,
TerminalExitReason,
TerminalOpenOutcome,
TerminalOpenRequest,
TerminalPendingOpen,
TerminalSession,
TerminalSessionManagerOptions,
} from "./session-manager.types.js";
/**
* Tracks live PTY sessions keyed by session id, with a reverse index by
@ -79,7 +41,7 @@ export class TerminalSessionManager {
// Opens still awaiting spawn, keyed by connection. A disconnect flips their
// abort flag so the resumed open kills the PTY instead of registering an
// orphan for a dead connection.
private readonly pendingOpens = new Map<string, Set<OpenToken>>();
private readonly pendingOpens = new Map<string, Set<TerminalPendingOpen>>();
private readonly emit: TerminalEventSink;
private readonly getBufferedAmount: (connId: string) => number | undefined;
private readonly spawn?: LocalTerminalBackendSpawner;
@ -92,6 +54,7 @@ export class TerminalSessionManager {
private opening = 0;
constructor(options: TerminalSessionManagerOptions) {
void ensureTerminalUploadCleanup();
this.emit = options.emit;
this.getBufferedAmount = options.getBufferedAmount ?? (() => undefined);
this.spawn = options.spawn;
@ -117,8 +80,8 @@ export class TerminalSessionManager {
}
// Reserve the slot before the async spawn so it is visible to concurrent opens.
this.opening += 1;
const token: OpenToken = { agentId: request.agentId };
this.trackPendingOpen(request.connId, token);
const pending: TerminalPendingOpen = { agentId: request.agentId };
this.trackPendingOpen(request.connId, pending);
let backend: TerminalBackend;
try {
backend = request.createBackend
@ -136,15 +99,15 @@ export class TerminalSessionManager {
);
} catch (err) {
this.opening -= 1;
this.untrackPendingOpen(request.connId, token);
this.untrackPendingOpen(request.connId, pending);
const message = err instanceof Error ? err.message : String(err);
return { ok: false, code: "spawn_failed", message };
}
// Hand the reservation over to the live session (synchronous from here — no
// await — so the counts never both drop).
this.opening -= 1;
this.untrackPendingOpen(request.connId, token);
if (token.abortMessage) {
this.untrackPendingOpen(request.connId, pending);
if (pending.abortMessage) {
// The owning connection disconnected while the shell was spawning; kill it
// now rather than register an orphan no one can reach or close.
try {
@ -152,7 +115,7 @@ export class TerminalSessionManager {
} catch {
// Best-effort; the process may already be gone.
}
return { ok: false, code: "closed", message: token.abortMessage };
return { ok: false, code: "closed", message: pending.abortMessage };
}
const sessionId = randomUUID();
@ -183,6 +146,7 @@ export class TerminalSessionManager {
cwd: request.cwd,
shell: request.shell,
backend,
stageUpload: request.stageUpload ?? stageTerminalUpload,
closed: false,
createdAtMs: Date.now(),
buffer,
@ -247,6 +211,22 @@ export class TerminalSessionManager {
}
}
/** Stages a file on the same host as an owned terminal session. */
async upload(
connId: string,
sessionId: string,
file: TerminalUploadFile,
): Promise<TerminalUploadResult | undefined> {
const session = this.ownedSession(connId, sessionId);
if (!session) {
return undefined;
}
const result = await session.stageUpload(file);
// Upload can outlive a socket or take-over. Do not return a usable path to
// a connection that no longer owns the terminal after the await.
return this.ownedSession(connId, sessionId) === session ? result : undefined;
}
/** Closes one session on operator request. */
close(connId: string, sessionId: string): boolean {
const session = this.ownedSession(connId, sessionId);
@ -321,19 +301,19 @@ export class TerminalSessionManager {
return session.buffer.snapshot();
}
private trackPendingOpen(connId: string, token: OpenToken): void {
private trackPendingOpen(connId: string, pending: TerminalPendingOpen): void {
let set = this.pendingOpens.get(connId);
if (!set) {
set = new Set();
this.pendingOpens.set(connId, set);
}
set.add(token);
set.add(pending);
}
private untrackPendingOpen(connId: string, token: OpenToken): void {
private untrackPendingOpen(connId: string, pending: TerminalPendingOpen): void {
const set = this.pendingOpens.get(connId);
if (set) {
set.delete(token);
set.delete(pending);
if (set.size === 0) {
this.pendingOpens.delete(connId);
}
@ -351,8 +331,8 @@ export class TerminalSessionManager {
// never answered, so the client has no session id to reattach.
const opens = this.pendingOpens.get(connId);
if (opens) {
for (const token of opens) {
token.abortMessage = "connection closed during open";
for (const pending of opens) {
pending.abortMessage = "connection closed during open";
}
}
const ids = this.byConn.get(connId);
@ -379,9 +359,9 @@ export class TerminalSessionManager {
// Config can change while spawn is awaiting the native PTY import. Mark the
// pending open so it kills the process instead of registering stale access.
for (const opens of this.pendingOpens.values()) {
for (const token of opens) {
if (!isAllowed(token.agentId)) {
token.abortMessage = "terminal closed because the agent policy changed";
for (const pending of opens) {
if (!isAllowed(pending.agentId)) {
pending.abortMessage = "terminal closed because the agent policy changed";
}
}
}
@ -432,8 +412,8 @@ export class TerminalSessionManager {
disposeAll(): void {
// Abort any opens still spawning so they don't register after shutdown.
for (const opens of this.pendingOpens.values()) {
for (const token of opens) {
token.abortMessage = "gateway closed during terminal open";
for (const pending of opens) {
pending.abortMessage = "gateway closed during terminal open";
}
}
// Snapshot first: finalize() deletes from this.sessions during iteration.

View file

@ -0,0 +1,58 @@
import type { TerminalUploadFile, TerminalUploadResult } from "../../infra/terminal-file-upload.js";
import type { LocalTerminalBackendSpawner, TerminalBackend } from "./backend.js";
import type { TerminalOutputController } from "./output-flow-control.js";
import type { TerminalOutputRing } from "./output-ring.js";
export type TerminalEventSink = (connId: string, event: string, payload: unknown) => void;
export type TerminalExitReason = "process_exit" | "closed" | "disconnected" | "detached" | "error";
export type TerminalSession = {
id: string;
/** Owning connection; null while the session is detached. */
connId: string | null;
agentId: string;
cwd: string;
shell: string;
backend: TerminalBackend;
stageUpload: (file: TerminalUploadFile) => Promise<TerminalUploadResult>;
closed: boolean;
createdAtMs: number;
buffer: TerminalOutputRing;
output: TerminalOutputController;
/** Kills the session when a detach outlives the grace period. */
reaper: ReturnType<typeof setTimeout> | null;
detachedAtMs: number | null;
};
export type TerminalSessionManagerOptions = {
emit: TerminalEventSink;
getBufferedAmount?: (connId: string) => number | undefined;
spawn?: LocalTerminalBackendSpawner;
maxSessions?: number;
env?: NodeJS.ProcessEnv;
/** Detach grace; 0 preserves kill-on-disconnect. Gateway wiring owns its default. */
detachGraceMs?: number;
maxDetachedSessions?: number;
scrollbackChars?: number;
};
export type TerminalOpenRequest = {
connId: string;
agentId: string;
cwd: string;
shell: string;
args: string[];
cols: number;
rows: number;
env: Record<string, string>;
createBackend?: () => Promise<TerminalBackend>;
stageUpload?: (file: TerminalUploadFile) => Promise<TerminalUploadResult>;
};
export type TerminalOpenOutcome =
| { ok: true; sessionId: string; agentId: string; cwd: string; shell: string }
| { ok: false; code: "limit" | "spawn_failed" | "closed"; message: string };
/** Abort state shared between a pending open and lifecycle/policy teardown. */
export type TerminalPendingOpen = { agentId: string; abortMessage?: string };

View file

@ -7,6 +7,8 @@ export const NODE_SYSTEM_RUN_COMMANDS = [
export const NODE_SYSTEM_NOTIFY_COMMAND = "system.notify";
export const NODE_FS_LIST_DIR_COMMAND = "fs.listDir";
export const NODE_TERMINAL_UPLOAD_COMMAND = "terminal.upload";
export const NODE_FILE_COMMANDS = [NODE_FS_LIST_DIR_COMMAND, NODE_TERMINAL_UPLOAD_COMMAND];
export const NODE_BROWSER_PROXY_COMMAND = "browser.proxy";
export const NODE_MCP_TOOLS_CALL_COMMAND = "mcp.tools.call.v1";
export const NODE_AGENT_CLI_CLAUDE_RUN_COMMAND = "agent.cli.claude.run.v1";
@ -24,6 +26,7 @@ export const NODE_EXEC_APPROVALS_COMMANDS = [
export const NODE_ADMIN_ONLY_INVOKE_COMMANDS = [
NODE_BROWSER_PROXY_COMMAND,
NODE_FS_LIST_DIR_COMMAND,
NODE_TERMINAL_UPLOAD_COMMAND,
] as const;
// Pairing also protects commands whose execution uses a separate gated path.

View file

@ -0,0 +1,151 @@
import { mkdir, readFile, rm, stat, utimes, writeFile } from "node:fs/promises";
import path from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";
import { MAX_TERMINAL_UPLOAD_BYTES } from "../../packages/gateway-protocol/src/terminal-upload-constants.js";
import { isCanonicalTerminalUploadBase64 } from "../../packages/gateway-protocol/src/terminal-upload-constants.js";
import { useAutoCleanupTempDirTracker } from "../../test/helpers/temp-dir.js";
import { ensureTerminalUploadCleanup, stageTerminalUpload } from "./terminal-file-upload.js";
vi.mock("node:fs/promises", async () => {
const actual = await vi.importActual<typeof import("node:fs/promises")>("node:fs/promises");
return {
...actual,
rm: vi.fn(actual.rm),
writeFile: vi.fn(actual.writeFile),
};
});
const tempDirs = useAutoCleanupTempDirTracker(afterEach);
describe("terminal file upload", () => {
it("stages arbitrary bytes under a private temporary directory", async () => {
const root = tempDirs.make("openclaw-terminal-upload-test-");
const content = Buffer.from([0, 1, 2, 255]);
const result = await stageTerminalUpload(
{ name: "../report final.pdf", contentBase64: content.toString("base64") },
{ tempRoot: root, cleanupAfterMs: 60_000 },
);
expect(path.basename(result.path)).toBe("report final.pdf");
expect(result.path.startsWith(`${root}${path.sep}`)).toBe(true);
expect(result.size).toBe(content.length);
expect(await readFile(result.path)).toEqual(content);
if (process.platform !== "win32") {
expect((await stat(result.path)).mode & 0o777).toBe(0o600);
expect((await stat(path.dirname(result.path))).mode & 0o777).toBe(0o700);
}
});
it("uses the user-profile ACL boundary instead of a configurable Windows temp directory", async () => {
const homeDir = tempDirs.make("openclaw-terminal-upload-windows-home-");
const sharedTemp = tempDirs.make("openclaw-terminal-upload-windows-shared-");
const result = await stageTerminalUpload(
{ name: "report.pdf", contentBase64: "" },
{ platform: "win32", homeDir, tempDir: sharedTemp },
);
expect(result.path.startsWith(path.join(homeDir, ".openclaw", "tmp"))).toBe(true);
expect(result.path.startsWith(sharedTemp)).toBe(false);
});
it("normalizes hostile and oversized names", async () => {
const root = tempDirs.make("openclaw-terminal-upload-name-test-");
const stagedName = async (name: string) =>
path.basename(
(
await stageTerminalUpload(
{ name, contentBase64: "" },
{ tempRoot: root, cleanupAfterMs: 60_000 },
)
).path,
);
expect(await stagedName("..\\..\\secret\u0000.txt")).toBe("secret_.txt");
expect(await stagedName("report:<final>?!-%PATH%.pdf. ")).toBe("report__final___-_PATH_.pdf");
expect(await stagedName("CON.txt")).toBe("_CON.txt");
expect(await stagedName("COM¹.txt")).toBe("_COM¹.txt");
expect(await stagedName("LPT³.log")).toBe("_LPT³.log");
expect(Buffer.byteLength(await stagedName("🦞".repeat(100)), "utf8")).toBeLessThanOrEqual(180);
expect(await stagedName("..")).toBe("upload");
});
it("recovers expired upload directories after restart", async () => {
const root = tempDirs.make("openclaw-terminal-upload-recovery-test-");
const directory = path.join(root, "openclaw-terminal-upload-stale");
await mkdir(directory, { mode: 0o700 });
await writeFile(path.join(directory, "report.pdf"), "stale");
await utimes(directory, new Date(0), new Date(0));
await ensureTerminalUploadCleanup({ tempRoot: root, retentionMs: 1, nowMs: Date.now() });
await expect(stat(directory)).rejects.toMatchObject({ code: "ENOENT" });
});
it("retries a recovery scan after a transient root failure", async () => {
vi.useFakeTimers();
const parent = tempDirs.make("openclaw-terminal-upload-retry-test-");
const root = path.join(parent, "root");
const directory = path.join(root, "openclaw-terminal-upload-stale");
try {
await writeFile(root, "temporarily not a directory");
await ensureTerminalUploadCleanup({ tempRoot: root, retentionMs: 1 });
await rm(root);
await mkdir(directory, { recursive: true, mode: 0o700 });
await writeFile(path.join(directory, "report.pdf"), "stale");
await utimes(directory, new Date(0), new Date(0));
await vi.advanceTimersByTimeAsync(60 * 60 * 1000);
await vi.waitFor(async () => {
await expect(stat(directory)).rejects.toMatchObject({ code: "ENOENT" });
});
} finally {
vi.useRealTimers();
}
});
it("retries partial upload cleanup without replacing the write error", async () => {
vi.useFakeTimers();
const root = tempDirs.make("openclaw-terminal-upload-write-failure-test-");
const writeError = new Error("write failed");
const writeMock = vi.mocked(writeFile);
const rmMock = vi.mocked(rm);
writeMock.mockClear();
rmMock.mockClear();
writeMock.mockRejectedValueOnce(writeError);
rmMock.mockRejectedValueOnce(new Error("cleanup busy")).mockResolvedValueOnce(undefined);
try {
await expect(
stageTerminalUpload({ name: "partial.bin", contentBase64: "AA==" }, { tempRoot: root }),
).rejects.toBe(writeError);
expect(rmMock).toHaveBeenCalledTimes(1);
await vi.advanceTimersByTimeAsync(60 * 60 * 1000);
expect(rmMock).toHaveBeenCalledTimes(2);
} finally {
vi.useRealTimers();
}
});
it("rejects malformed and oversized payloads", async () => {
const root = tempDirs.make("openclaw-terminal-upload-test-");
expect(isCanonicalTerminalUploadBase64("AB==")).toBe(false);
expect(isCanonicalTerminalUploadBase64("AAB=")).toBe(false);
expect(isCanonicalTerminalUploadBase64("AA==")).toBe(true);
await expect(
stageTerminalUpload({ name: "bad.bin", contentBase64: "not base64" }, { tempRoot: root }),
).rejects.toThrow("invalid terminal upload encoding");
await expect(
stageTerminalUpload(
{
name: "large.bin",
contentBase64: Buffer.alloc(MAX_TERMINAL_UPLOAD_BYTES + 1).toString("base64"),
},
{ tempRoot: root },
),
).rejects.toThrow("exceeds");
});
});

View file

@ -0,0 +1,257 @@
import { lstat, mkdir, mkdtemp, readdir, rm, writeFile } from "node:fs/promises";
import { homedir, tmpdir } from "node:os";
import path from "node:path";
import {
isCanonicalTerminalUploadBase64,
MAX_TERMINAL_UPLOAD_BASE64_LENGTH,
MAX_TERMINAL_UPLOAD_BYTES,
terminalUploadDecodedSize,
} from "../../packages/gateway-protocol/src/terminal-upload-constants.js";
import { logWarn } from "../logger.js";
const TERMINAL_UPLOAD_PREFIX = "openclaw-terminal-upload-";
const TERMINAL_UPLOAD_RETENTION_MS = 24 * 60 * 60 * 1000;
const TERMINAL_UPLOAD_CLEANUP_RETRY_MS = 60 * 60 * 1000;
const MAX_STAGED_NAME_BYTES = 180;
const PORTABLE_NAME_FORBIDDEN = new Set(["<", ">", ":", '"', "/", "\\", "|", "?", "*", "%", "!"]);
const WINDOWS_RESERVED_NAME = /^(?:con|prn|aux|nul|com[1-9¹²³]|lpt[1-9¹²³])(?:\.|$)/iu;
const cleanupTimers = new Map<string, ReturnType<typeof setTimeout>>();
const cleanupRecoveryTimers = new Map<string, ReturnType<typeof setTimeout>>();
let defaultCleanupPromise: Promise<void> | undefined;
type TerminalUploadRootOptions = {
platform?: NodeJS.Platform;
homeDir?: string;
tempDir?: string;
};
/** Windows temp variables can point at a shared directory; inherit the user's profile ACL instead. */
function resolveTerminalUploadRoot(options?: TerminalUploadRootOptions): string {
return (options?.platform ?? process.platform) === "win32"
? path.join(options?.homeDir ?? homedir(), ".openclaw", "tmp")
: (options?.tempDir ?? tmpdir());
}
export type TerminalUploadFile = {
name: string;
contentBase64: string;
};
export type TerminalUploadResult = {
path: string;
size: number;
};
function truncateUtf8(value: string, maxBytes: number): string {
let result = "";
let bytes = 0;
for (const character of value) {
const nextBytes = Buffer.byteLength(character, "utf8");
if (bytes + nextBytes > maxBytes) {
break;
}
result += character;
bytes += nextBytes;
}
return result;
}
function sanitizeTerminalUploadName(name: string): string {
const basename = path.posix.basename(name.replaceAll("\\", "/"));
const cleaned = Array.from(basename, (char) => {
const codePoint = char.codePointAt(0) ?? 0;
return codePoint <= 0x1f || codePoint === 0x7f || PORTABLE_NAME_FORBIDDEN.has(char)
? "_"
: char;
})
.join("")
.trim()
.replace(/[. ]+$/u, "");
const portable = WINDOWS_RESERVED_NAME.test(cleaned) ? `_${cleaned}` : cleaned;
const safe = portable && portable !== "." && portable !== ".." ? portable : "upload";
return truncateUtf8(safe, MAX_STAGED_NAME_BYTES) || "upload";
}
function decodeTerminalUpload(contentBase64: string): Buffer {
if (
contentBase64.length > MAX_TERMINAL_UPLOAD_BASE64_LENGTH ||
terminalUploadDecodedSize(contentBase64) > MAX_TERMINAL_UPLOAD_BYTES
) {
throw new Error(`terminal upload exceeds ${MAX_TERMINAL_UPLOAD_BYTES} bytes`);
}
if (!isCanonicalTerminalUploadBase64(contentBase64)) {
throw new Error("invalid terminal upload encoding");
}
const bytes = Buffer.from(contentBase64, "base64");
if (bytes.length > MAX_TERMINAL_UPLOAD_BYTES) {
throw new Error(`terminal upload exceeds ${MAX_TERMINAL_UPLOAD_BYTES} bytes`);
}
if (bytes.toString("base64") !== contentBase64) {
throw new Error("invalid terminal upload encoding");
}
return bytes;
}
async function removeTerminalUploadDirectory(directory: string): Promise<void> {
try {
await rm(directory, { recursive: true, force: true });
} catch (error) {
logWarn(`terminal-upload: cleanup failed; retrying: ${String(error)}`);
scheduleTerminalUploadCleanup(directory, TERMINAL_UPLOAD_CLEANUP_RETRY_MS);
}
}
function scheduleTerminalUploadCleanup(directory: string, afterMs: number): void {
if (cleanupTimers.has(directory)) {
return;
}
const timer = setTimeout(
() => {
cleanupTimers.delete(directory);
void removeTerminalUploadDirectory(directory);
},
Math.max(0, afterMs),
);
cleanupTimers.set(directory, timer);
timer.unref?.();
}
/** Restores cleanup timers for staged uploads left by a previous process. */
async function recoverTerminalUploadCleanup(options?: {
tempRoot?: string;
retentionMs?: number;
nowMs?: number;
}): Promise<void> {
const tempRoot = options?.tempRoot ?? resolveTerminalUploadRoot();
const retentionMs = options?.retentionMs ?? TERMINAL_UPLOAD_RETENTION_MS;
const nowMs = options?.nowMs ?? Date.now();
let entries;
try {
entries = await readdir(tempRoot, { withFileTypes: true });
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
logWarn(`terminal-upload: recovery scan failed: ${String(error)}`);
throw error;
}
return;
}
await Promise.all(
entries
.filter((entry) => entry.isDirectory() && entry.name.startsWith(TERMINAL_UPLOAD_PREFIX))
.map(async (entry) => {
const directory = path.join(tempRoot, entry.name);
try {
const stats = await lstat(directory);
if (!stats.isDirectory()) {
return;
}
if (typeof process.getuid === "function" && stats.uid !== process.getuid()) {
return;
}
const remainingMs = retentionMs - Math.max(0, nowMs - stats.mtimeMs);
if (remainingMs <= 0) {
await removeTerminalUploadDirectory(directory);
} else {
scheduleTerminalUploadCleanup(directory, remainingMs);
}
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
logWarn(`terminal-upload: recovery failed: ${String(error)}`);
throw error;
}
}
}),
);
}
function cleanupRecoveryRoot(options?: { tempRoot?: string }): string {
return options?.tempRoot ?? resolveTerminalUploadRoot();
}
function clearTerminalUploadCleanupRetry(tempRoot: string): void {
const timer = cleanupRecoveryTimers.get(tempRoot);
if (!timer) {
return;
}
clearTimeout(timer);
cleanupRecoveryTimers.delete(tempRoot);
}
function scheduleTerminalUploadCleanupRetry(options?: {
tempRoot?: string;
retentionMs?: number;
}): void {
const tempRoot = cleanupRecoveryRoot(options);
if (cleanupRecoveryTimers.has(tempRoot)) {
return;
}
const timer = setTimeout(() => {
cleanupRecoveryTimers.delete(tempRoot);
void ensureTerminalUploadCleanup(
options ? { tempRoot, retentionMs: options.retentionMs } : undefined,
);
}, TERMINAL_UPLOAD_CLEANUP_RETRY_MS);
cleanupRecoveryTimers.set(tempRoot, timer);
timer.unref?.();
}
async function runTerminalUploadCleanupRecovery(options?: {
tempRoot?: string;
retentionMs?: number;
nowMs?: number;
}): Promise<void> {
const tempRoot = cleanupRecoveryRoot(options);
try {
await recoverTerminalUploadCleanup(options);
clearTerminalUploadCleanupRetry(tempRoot);
} catch {
scheduleTerminalUploadCleanupRetry(options);
}
}
/** Starts one process-wide recovery scan and retries transient scan failures. */
export function ensureTerminalUploadCleanup(options?: {
tempRoot?: string;
retentionMs?: number;
nowMs?: number;
}): Promise<void> {
if (options) {
return runTerminalUploadCleanupRecovery(options);
}
if (defaultCleanupPromise) {
return defaultCleanupPromise;
}
defaultCleanupPromise = runTerminalUploadCleanupRecovery().finally(() => {
if (cleanupRecoveryTimers.has(cleanupRecoveryRoot())) {
defaultCleanupPromise = undefined;
}
});
return defaultCleanupPromise;
}
/** Stages one browser-selected file in a private, expiring temporary directory. */
export async function stageTerminalUpload(
file: TerminalUploadFile,
options?: TerminalUploadRootOptions & { tempRoot?: string; cleanupAfterMs?: number },
): Promise<TerminalUploadResult> {
if (!options?.tempRoot) {
void ensureTerminalUploadCleanup();
}
const bytes = decodeTerminalUpload(file.contentBase64);
const platform = options?.platform ?? process.platform;
const tempRoot = options?.tempRoot ?? resolveTerminalUploadRoot(options);
if (platform === "win32" && !options?.tempRoot) {
// The user profile supplies the restrictive DACL; this mode protects POSIX-compatible hosts.
await mkdir(tempRoot, { recursive: true, mode: 0o700 });
}
const directory = await mkdtemp(path.join(tempRoot, TERMINAL_UPLOAD_PREFIX));
const targetPath = path.join(directory, sanitizeTerminalUploadName(file.name));
try {
await writeFile(targetPath, bytes, { flag: "wx", mode: 0o600 });
} catch (error) {
await removeTerminalUploadDirectory(directory);
throw error;
}
scheduleTerminalUploadCleanup(directory, options?.cleanupAfterMs ?? TERMINAL_UPLOAD_RETENTION_MS);
return { path: targetPath, size: bytes.length };
}

View file

@ -0,0 +1,46 @@
import { listHostDirectories } from "../infra/host-directory-listing.js";
import { NODE_FS_LIST_DIR_COMMAND, NODE_TERMINAL_UPLOAD_COMMAND } from "../infra/node-commands.js";
import { stageTerminalUpload } from "../infra/terminal-file-upload.js";
type NodeFileCommandResult = { payload: unknown } | { error: unknown };
function decodeParams(raw?: string | null): Record<string, unknown> {
if (!raw) {
throw new Error("INVALID_REQUEST: paramsJSON required");
}
try {
return JSON.parse(raw) as Record<string, unknown>;
} catch {
throw new Error("INVALID_REQUEST: paramsJSON malformed JSON");
}
}
/** Handles bounded node-host filesystem commands before plugin dispatch. */
export async function invokeNodeFileCommand(
command: string,
paramsJSON?: string | null,
): Promise<NodeFileCommandResult | null> {
if (command !== NODE_FS_LIST_DIR_COMMAND && command !== NODE_TERMINAL_UPLOAD_COMMAND) {
return null;
}
try {
const params = decodeParams(paramsJSON);
if (command === NODE_FS_LIST_DIR_COMMAND) {
if (params.path !== undefined && typeof params.path !== "string") {
throw new Error("INVALID_REQUEST: path must be a string");
}
return { payload: await listHostDirectories(params.path) };
}
if (typeof params.name !== "string" || typeof params.contentBase64 !== "string") {
throw new Error("INVALID_REQUEST: terminal upload name and content are required");
}
return {
payload: await stageTerminalUpload({
name: params.name,
contentBase64: params.contentBase64,
}),
};
} catch (error) {
return { error };
}
}

View file

@ -176,6 +176,29 @@ describe("node host invoke", () => {
});
});
it("stages terminal uploads on the node host", async () => {
const request = vi.fn<GatewayClient["request"]>().mockResolvedValue(null);
await handleInvoke(
{
id: "invoke-terminal-upload",
nodeId: "node-1",
command: "terminal.upload",
paramsJSON: JSON.stringify({
name: "node report.pdf",
contentBase64: Buffer.from("node bytes").toString("base64"),
}),
},
{ request } as unknown as GatewayClient,
{ current: async () => [] },
);
const result = request.mock.calls[0]?.[1] as InvokeResult | undefined;
const payload = JSON.parse(result?.payloadJSON ?? "{}") as { path: string; size: number };
expect(payload.size).toBe(10);
expect(fs.readFileSync(payload.path, "utf8")).toBe("node bytes");
fs.rmSync(path.dirname(payload.path), { recursive: true, force: true });
});
it("returns a redacted exec approvals snapshot", async () => {
execApprovalsStoreMock.hasEnsureResult = true;
execApprovalsStoreMock.ensureResult = createExecApprovalsSnapshot();

View file

@ -30,7 +30,6 @@ import {
extractShellWrapperCommand,
isShellWrapperInvocation,
} from "../infra/exec-wrapper-resolution.js";
import { listHostDirectories } from "../infra/host-directory-listing.js";
import {
inspectHostExecEnvOverrides,
sanitizeHostExecEnv,
@ -38,7 +37,6 @@ import {
} from "../infra/host-env-security.js";
import {
NODE_AGENT_CLI_CLAUDE_RUN_COMMAND,
NODE_FS_LIST_DIR_COMMAND,
NODE_MCP_TOOLS_CALL_COMMAND,
} from "../infra/node-commands.js";
import { logWarn } from "../logger.js";
@ -49,6 +47,7 @@ import {
handleClaudeCliNodeInvoke,
type NodeHostInvokeRuntime,
} from "./invoke-agent-cli-claude-handler.js";
import { invokeNodeFileCommand } from "./invoke-file-commands.js";
import {
buildSystemRunApprovalPlan,
handleSystemRunInvoke,
@ -659,15 +658,12 @@ async function dispatchInvoke(
return;
}
if (command === NODE_FS_LIST_DIR_COMMAND) {
try {
const params = decodeParams<{ path?: unknown }>(frame.paramsJSON);
if (params.path !== undefined && typeof params.path !== "string") {
throw new Error("INVALID_REQUEST: path must be a string");
}
await sendJsonPayloadResult(client, frame, await listHostDirectories(params.path));
} catch (err) {
await sendInvalidRequestResult(client, frame, err);
const fileCommand = await invokeNodeFileCommand(command, frame.paramsJSON);
if (fileCommand) {
if ("error" in fileCommand) {
await sendInvalidRequestResult(client, frame, fileCommand.error);
} else {
await sendJsonPayloadResult(client, frame, fileCommand.payload);
}
return;
}

View file

@ -11,8 +11,10 @@ import {
NODE_FS_LIST_DIR_COMMAND,
NODE_MCP_TOOLS_CALL_COMMAND,
NODE_SYSTEM_RUN_COMMANDS,
NODE_TERMINAL_UPLOAD_COMMAND,
} from "../infra/node-commands.js";
import { ensureOpenClawCliOnPath } from "../infra/path-env.js";
import { ensureTerminalUploadCleanup } from "../infra/terminal-file-upload.js";
import { logDebug } from "../logger.js";
import type { OpenClawPluginNodeHostCommandIo } from "../plugins/types.js";
import { BoundedBuffer } from "../shared/bounded-buffer.js";
@ -215,6 +217,7 @@ export async function prepareNodeHostRuntime(params?: {
/** Embedded workers may still host long-lived plugin commands over the app-owned socket. */
enableDuplexPluginCommands?: boolean;
}): Promise<PreparedNodeHostRuntime> {
void ensureTerminalUploadCleanup();
const config = params?.config ?? getRuntimeConfig();
const env = params?.env ?? process.env;
await ensureNodeHostPluginRegistry({ config, env });
@ -240,6 +243,7 @@ export async function prepareNodeHostRuntime(params?: {
...NODE_SYSTEM_RUN_COMMANDS,
...NODE_EXEC_APPROVALS_COMMANDS,
NODE_FS_LIST_DIR_COMMAND,
NODE_TERMINAL_UPLOAD_COMMAND,
NODE_MCP_TOOLS_CALL_COMMAND,
...(claudePath ? [NODE_AGENT_CLI_CLAUDE_RUN_COMMAND] : []),
...pluginNodeHost.commands,

View file

@ -0,0 +1,87 @@
/* @vitest-environment jsdom */
import { describe, expect, it } from "vitest";
import {
encodeTerminalUpload,
quoteTerminalUploadPath,
uploadTerminalFile,
} from "./terminal-file-upload.ts";
const MAX_TERMINAL_UPLOAD_BYTES = 16 * 1024 * 1024;
describe("terminal file upload", () => {
it("requests terminal.upload with the session-bound payload", async () => {
const requests: Array<{ method: string; params: unknown }> = [];
const client = {
request: async <T>(method: string, params?: unknown) => {
requests.push({ method, params });
return { path: "/tmp/scan.pdf", size: 1 } as T;
},
};
await expect(
uploadTerminalFile(client, "s1", { name: "scan.pdf", contentBase64: "AA==" }),
).resolves.toEqual({ path: "/tmp/scan.pdf", size: 1 });
expect(requests).toEqual([
{
method: "terminal.upload",
params: { sessionId: "s1", name: "scan.pdf", contentBase64: "AA==" },
},
]);
});
it("base64-encodes arbitrary browser files", async () => {
const file = new File([new Uint8Array([0, 1, 2, 255])], "scan.pdf");
await expect(encodeTerminalUpload(file)).resolves.toBe("AAEC/w==");
});
it("rejects oversized files before reading them", async () => {
const file = {
name: "archive.zip",
size: MAX_TERMINAL_UPLOAD_BYTES + 1,
arrayBuffer: () => Promise.reject(new Error("should not read")),
} as File;
await expect(encodeTerminalUpload(file)).rejects.toThrow("16 MiB");
});
it("quotes paths for POSIX, PowerShell, and cmd terminals", () => {
expect(quoteTerminalUploadPath("/tmp/report.pdf", "/bin/zsh")).toBe("/tmp/report.pdf");
expect(quoteTerminalUploadPath("/tmp/report final.pdf", "/bin/zsh")).toBe(
"'/tmp/report final.pdf'",
);
expect(quoteTerminalUploadPath("/tmp/it's.pdf", "/bin/zsh")).toBe("'/tmp/it'\\''s.pdf'");
expect(quoteTerminalUploadPath("C:\\Temp\\report final.pdf", "pwsh.exe")).toBe(
"'C:\\Temp\\report final.pdf'",
);
expect(quoteTerminalUploadPath("C:\\Temp\\report.pdf", "cmd.exe")).toBe(
'"C:\\Temp\\report.pdf"',
);
expect(quoteTerminalUploadPath("C:\\Temp\\x$(touch pwned).txt", "C:\\Git\\bin\\bash.exe")).toBe(
"'C:\\Temp\\x$(touch pwned).txt'",
);
});
it("refuses Windows paths for shells with unknown quoting and path semantics", () => {
expect(() => quoteTerminalUploadPath("C:\\Temp\\x$(touch pwned).txt", "wsl.exe")).toThrow(
"unsupported shell: wsl.exe",
);
expect(() =>
quoteTerminalUploadPath("\\\\server\\profiles\\x$(touch pwned).txt", "wsl.exe"),
).toThrow("unsupported shell: wsl.exe");
});
it("refuses POSIX paths for shells with unknown quoting", () => {
expect(() => quoteTerminalUploadPath("/tmp/it's.pdf", "/usr/bin/nu")).toThrow(
"unsupported shell: nu",
);
});
it.each(["C:\\Users\\%USERNAME%\\report.pdf", "C:\\Users\\bang!\\report.pdf"])(
"refuses cmd.exe expansion in the complete staged path: %s",
(filePath) => {
expect(() => quoteTerminalUploadPath(filePath, "cmd.exe")).toThrow(
"path containing % or ! into cmd.exe",
);
},
);
});

View file

@ -0,0 +1,55 @@
// Keep this client guard aligned with the gateway protocol's 16 MiB limit so
// oversized files never expand into a WebSocket base64 payload.
const MAX_TERMINAL_UPLOAD_BYTES = 16 * 1024 * 1024;
type TerminalUploadFile = { name: string; contentBase64: string };
type TerminalUploadResult = { path: string; size: number };
type TerminalUploadClient = {
request<T = unknown>(method: string, params?: unknown): Promise<T>;
};
export async function uploadTerminalFile(
client: TerminalUploadClient,
sessionId: string,
file: TerminalUploadFile,
): Promise<TerminalUploadResult> {
return await client.request<TerminalUploadResult>("terminal.upload", { sessionId, ...file });
}
export async function encodeTerminalUpload(file: File): Promise<string> {
if (file.size > MAX_TERMINAL_UPLOAD_BYTES) {
throw new Error(`File exceeds the 16 MiB terminal upload limit: ${file.name}`);
}
const bytes = new Uint8Array(await file.arrayBuffer());
const chunks: string[] = [];
const chunkSize = 32 * 1024;
for (let offset = 0; offset < bytes.length; offset += chunkSize) {
chunks.push(String.fromCharCode(...bytes.subarray(offset, offset + chunkSize)));
}
return btoa(chunks.join(""));
}
/** Quotes one staged path for the shell that owns the active terminal. */
export function quoteTerminalUploadPath(filePath: string, shell: string): string {
const shellName = shell.split(/[\\/]/u).pop()?.toLowerCase() ?? "";
if (/^(?:pwsh|powershell)(?:\.exe)?$/u.test(shellName)) {
return `'${filePath.replaceAll("'", "''")}'`;
}
if (/^cmd(?:\.exe)?$/u.test(shellName)) {
if (/[%!]/u.test(filePath)) {
throw new Error("Cannot safely insert an uploaded path containing % or ! into cmd.exe");
}
return `"${filePath.replaceAll('"', '""')}"`;
}
const posixShell = /^(?:(?:ba|da|a|k|z)?sh|fish)(?:\.exe)?$/u.test(shellName);
if (!posixShell) {
throw new Error(
`Cannot safely insert an uploaded path into unsupported shell: ${shellName || shell}`,
);
}
if (/^[A-Za-z0-9_@%+=:,./-]+$/u.test(filePath)) {
return filePath;
}
return `'${filePath.replaceAll("'", "'\\''")}'`;
}

View file

@ -0,0 +1,254 @@
import type { GhosttyTerminalController } from "@openclaw/libterminal/browser";
import { css, html, nothing, svg } from "lit";
import { t } from "../../i18n/index.ts";
import type { TerminalGatewayClient } from "./terminal-connection.ts";
import {
encodeTerminalUpload,
quoteTerminalUploadPath,
uploadTerminalFile,
} from "./terminal-file-upload.ts";
const CLOSE_GLYPH = svg`<svg viewBox="0 0 16 16" width="12" height="12" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M4 4l8 8M12 4l-8 8" /></svg>`;
const DOCK_BOTTOM_GLYPH = svg`<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="1.3"><rect x="2" y="2.5" width="12" height="11" rx="1.5" /><path d="M2 10h12" /></svg>`;
const DOCK_RIGHT_GLYPH = svg`<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="1.3"><rect x="2" y="2.5" width="12" height="11" rx="1.5" /><path d="M10 2.5v11" /></svg>`;
const UPLOAD_GLYPH = svg`<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><path d="M5.2 8.1 9.8 3.5a2.5 2.5 0 0 1 3.5 3.5l-6 6a3.5 3.5 0 0 1-5-5l5.8-5.8" /><path d="m4.4 9 5.2-5.2a1.4 1.4 0 0 1 2 2l-5.3 5.3a2.3 2.3 0 0 1-3.2-3.2l4.6-4.6" /></svg>`;
type TerminalUploadTab = {
gatewaySessionId: string;
shell: string;
status: string;
controller: GhosttyTerminalController;
};
type TerminalPanelUploadHost = {
activeTab: () => TerminalUploadTab | undefined;
client: () => TerminalGatewayClient | null;
isCurrent: (tab: TerminalUploadTab) => boolean;
fileInput: () => HTMLInputElement | null;
setError: (message: string | null) => void;
requestUpdate: () => void;
};
export class TerminalPanelUploadController {
uploading = false;
dragActive = false;
private generation = 0;
private dragDepth = 0;
constructor(private readonly host: TerminalPanelUploadHost) {}
hasActiveTab(): boolean {
return Boolean(this.host.activeTab());
}
chooseFiles = (): void => {
this.host.fileInput()?.click();
};
handleFileSelection = (event: Event): void => {
const input = event.currentTarget as HTMLInputElement;
const files = Array.from(input.files ?? []);
input.value = "";
void this.uploadFiles(files);
};
private hasDraggedFiles(event: DragEvent): boolean {
return Array.from(event.dataTransfer?.types ?? []).includes("Files");
}
handleDragEnter = (event: DragEvent): void => {
if (!this.hasDraggedFiles(event) || !this.hasActiveTab() || this.uploading) {
return;
}
event.preventDefault();
this.dragDepth += 1;
this.dragActive = true;
this.host.requestUpdate();
};
handleDragOver = (event: DragEvent): void => {
if (!this.hasDraggedFiles(event) || !this.hasActiveTab() || this.uploading) {
return;
}
event.preventDefault();
if (event.dataTransfer) {
event.dataTransfer.dropEffect = "copy";
}
};
handleDragLeave = (event: DragEvent): void => {
if (!this.hasDraggedFiles(event)) {
return;
}
this.dragDepth = Math.max(0, this.dragDepth - 1);
if (this.dragDepth === 0) {
this.dragActive = false;
this.host.requestUpdate();
}
};
handleDrop = (event: DragEvent): void => {
if (!this.hasDraggedFiles(event)) {
return;
}
event.preventDefault();
this.dragDepth = 0;
this.dragActive = false;
this.host.requestUpdate();
void this.uploadFiles(Array.from(event.dataTransfer?.files ?? []));
};
private async uploadFiles(files: File[]): Promise<void> {
const tab = this.host.activeTab();
const client = this.host.client();
if (files.length === 0 || !tab || !client || this.uploading) {
return;
}
const generation = ++this.generation;
this.uploading = true;
this.host.setError(null);
this.host.requestUpdate();
const paths: string[] = [];
try {
for (const file of files) {
try {
const contentBase64 = await encodeTerminalUpload(file);
const result = await uploadTerminalFile(client, tab.gatewaySessionId, {
name: file.name,
contentBase64,
});
paths.push(quoteTerminalUploadPath(result.path, tab.shell));
} catch (error) {
this.host.setError(error instanceof Error ? error.message : String(error));
break;
}
}
if (paths.length > 0 && generation === this.generation && this.host.isCurrent(tab)) {
// Ghostty preserves bracketed-paste mode. This produces editable input,
// never Enter, so adding a file cannot execute a shell command.
tab.controller.terminal.paste(paths.join(" "));
tab.controller.terminal.focus();
}
} finally {
if (generation === this.generation) {
this.uploading = false;
this.host.requestUpdate();
}
}
}
dispose(): void {
this.generation += 1;
this.uploading = false;
this.dragActive = false;
this.dragDepth = 0;
}
}
export function renderTerminalPanelActions(params: {
fullscreen: boolean;
dock: "bottom" | "right";
upload: TerminalPanelUploadController;
sessionPicker: unknown;
onDock: (dock: "bottom" | "right") => void;
onHide: () => void;
}) {
return html`<div class="tp-actions">
<input
class="tp-file-input"
type="file"
multiple
aria-hidden="true"
tabindex="-1"
@change=${params.upload.handleFileSelection}
/>
<button
class="tp-icon tp-upload"
type="button"
title=${t("terminal.addFiles")}
aria-label=${t("terminal.addFiles")}
?disabled=${params.upload.uploading || !params.upload.hasActiveTab()}
@click=${params.upload.chooseFiles}
>
${UPLOAD_GLYPH}
</button>
${params.fullscreen
? nothing
: html`${params.sessionPicker}<button
class="tp-icon ${params.dock === "bottom" ? "is-active" : ""}"
type="button"
title=${t("terminal.dockBottom")}
aria-label=${t("terminal.dockBottom")}
@click=${() => params.onDock("bottom")}
>
${DOCK_BOTTOM_GLYPH}
</button>
<button
class="tp-icon ${params.dock === "right" ? "is-active" : ""}"
type="button"
title=${t("terminal.dockRight")}
aria-label=${t("terminal.dockRight")}
@click=${() => params.onDock("right")}
>
${DOCK_RIGHT_GLYPH}
</button>
<button
class="tp-icon"
type="button"
title=${t("terminal.hide")}
aria-label=${t("terminal.hide")}
@click=${params.onHide}
>
${CLOSE_GLYPH}
</button>`}
</div>`;
}
export function renderTerminalUploadLayer(upload: TerminalPanelUploadController) {
return html`${upload.dragActive
? html`<div class="tp-drop-overlay">${t("terminal.dropFiles")}</div>`
: nothing}
${upload.uploading
? html`<div class="tp-upload-status" role="status">${t("terminal.uploading")}</div>`
: nothing}`;
}
export const terminalPanelUploadStyles = css`
.tp-icon:disabled {
opacity: 0.35;
pointer-events: none;
}
.tp-file-input {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.tp-drop-overlay {
position: absolute;
z-index: 4;
inset: 8px;
display: grid;
place-items: center;
border: 1px dashed var(--accent, #ff5c5c);
background: color-mix(in srgb, var(--bg, #0e1015) 88%, var(--accent, #ff5c5c));
color: var(--text, #d7dae0);
font-size: 13px;
pointer-events: none;
}
.tp-upload-status {
position: absolute;
z-index: 3;
right: 10px;
bottom: 8px;
padding: 4px 7px;
border: 1px solid var(--border, #262b34);
border-radius: 4px;
background: var(--bg, #0e1015);
color: var(--muted, #8a919e);
font-size: 11px;
pointer-events: none;
}
`;

View file

@ -29,6 +29,7 @@ function createTerminalController(dispose: () => void = vi.fn()) {
write: vi.fn(),
focus: vi.fn(),
reset: vi.fn(),
paste: vi.fn(),
},
write: vi.fn(),
fit: vi.fn(),
@ -166,7 +167,10 @@ describe("OpenClawTerminalPanel", () => {
});
expect(createOptions?.terminalOptions?.fontFamily).toContain("MesloLGLDZ Nerd Font Mono");
expect(getComputedStyle(createOptions!.parent).caretColor).toBe("rgba(0, 0, 0, 0)");
const styles = (OpenClawTerminalPanel.styles as { cssText: string }).cssText;
const styleResults = Array.isArray(OpenClawTerminalPanel.styles)
? OpenClawTerminalPanel.styles
: [OpenClawTerminalPanel.styles];
const styles = styleResults.map((style) => style.cssText).join("\n");
expect(styles).toMatch(/\.tp-new\s*\{[^}]*align-self:\s*center/u);
await vi.waitFor(() => {
expect(requests).toContainEqual({
@ -613,7 +617,8 @@ describe("OpenClawTerminalPanel", () => {
const section = panel.renderRoot.querySelector(".tp");
expect(section?.classList.contains("tp--fullscreen")).toBe(true);
expect(panel.renderRoot.querySelector(".tp-resizer")).toBeNull();
expect(panel.renderRoot.querySelector(".tp-actions")).toBeNull();
expect(panel.renderRoot.querySelector(".tp-upload")).not.toBeNull();
expect(panel.renderRoot.querySelectorAll(".tp-actions button")).toHaveLength(1);
// Closing the last tab must keep the panel (with its "+" button) rendered —
// a fullscreen document has no toggle to bring a closed panel back.
@ -834,6 +839,57 @@ describe("OpenClawTerminalPanel", () => {
expect(host.isConnected).toBe(false);
});
it("uploads dropped files and pastes shell-safe paths without executing", async () => {
const controller = createTerminalController();
createGhosttyTerminalMock.mockResolvedValue(controller);
const requests: Array<{ method: string; params: unknown }> = [];
const client: TerminalGatewayClient = {
request: async <T>(method: string, params?: unknown) => {
requests.push({ method, params });
if (method === "terminal.open") {
return terminalOpenResult("session-1") as T;
}
if (method === "terminal.upload") {
return { path: "/tmp/openclaw upload/scan final.pdf", size: 3 } as T;
}
return {} as T;
},
addEventListener: () => () => {},
};
const panel = document.createElement(TERMINAL_PANEL_ELEMENT_NAME) as OpenClawTerminalPanel;
panel.client = client;
panel.available = true;
document.body.append(panel);
panel.toggle();
await vi.waitFor(() => {
expect(panel.renderRoot.querySelector<HTMLButtonElement>(".tp-upload")?.disabled).toBe(false);
});
expect(panel.renderRoot.querySelector<HTMLInputElement>(".tp-file-input")?.multiple).toBe(true);
const file = new File(["pdf"], "scan final.pdf", { type: "application/pdf" });
Object.defineProperty(file, "arrayBuffer", {
value: async () => new TextEncoder().encode("pdf").buffer,
});
const drop = new Event("drop", { bubbles: true, cancelable: true });
Object.defineProperty(drop, "dataTransfer", {
value: { types: ["Files"], files: [file], dropEffect: "none" },
});
panel.renderRoot.querySelector(".tp-viewport")?.dispatchEvent(drop);
await vi.waitFor(() => {
expect(requests).toContainEqual({
method: "terminal.upload",
params: {
sessionId: "session-1",
name: "scan final.pdf",
contentBase64: "cGRm",
},
});
});
expect(controller.terminal.paste).toHaveBeenCalledWith("'/tmp/openclaw upload/scan final.pdf'");
expect(controller.terminal.paste).not.toHaveBeenCalledWith(expect.stringContaining("\n"));
});
it("retranslates cached exit state when the locale changes", async () => {
createGhosttyTerminalMock.mockResolvedValue(createTerminalController());
let listener: ((event: { event: string; payload: unknown }) => void) | undefined;

View file

@ -5,7 +5,7 @@ import type { GhosttyTerminalController } from "@openclaw/libterminal/browser";
// tabs. Each tab hosts one libterminal Ghostty controller wired to a gateway PTY
// session. The browser runtime is dynamically imported on first open so it
// never weighs down the initial Control UI bundle.
import { html, nothing, svg } from "lit";
import { html, nothing } from "lit";
import { property, state } from "lit/decorators.js";
import { t } from "../../i18n/index.ts";
import { OpenClawLitElement } from "../../lit/openclaw-element.ts";
@ -22,6 +22,12 @@ import {
} from "./terminal-connection.ts";
import { terminalPanelStyles } from "./terminal-panel-styles.ts";
import { renderTerminalPanelTabs, type TerminalPanelTab } from "./terminal-panel-tabs.ts";
import {
renderTerminalPanelActions,
renderTerminalUploadLayer,
TerminalPanelUploadController,
terminalPanelUploadStyles,
} from "./terminal-panel-upload.ts";
import { createIsolatedGhosttyTerminal } from "./terminal-runtime.ts";
import { renderTerminalSessionPicker } from "./terminal-session-picker.ts";
import {
@ -32,16 +38,12 @@ import { createTerminalStartupInput, type StartupInputBuffer } from "./terminal-
import { TerminalTaskQueue } from "./terminal-task-queue.ts";
import { terminalTheme } from "./terminal-theme.ts";
// Inline icon set (self-contained; the Control UI blocks external asset loads).
const CLOSE_GLYPH = svg`<svg viewBox="0 0 16 16" width="12" height="12" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M4 4l8 8M12 4l-8 8" /></svg>`;
const DOCK_BOTTOM_GLYPH = svg`<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="1.3"><rect x="2" y="2.5" width="12" height="11" rx="1.5" /><path d="M2 10h12" /></svg>`;
const DOCK_RIGHT_GLYPH = svg`<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="1.3"><rect x="2" y="2.5" width="12" height="11" rx="1.5" /><path d="M10 2.5v11" /></svg>`;
type TerminalDock = DockPanelSide;
type TerminalTabState = TerminalPanelTab & {
gatewaySessionId: string;
pendingInput: StartupInputBuffer;
controller: GhosttyTerminalController;
shell: string;
host: HTMLDivElement;
/** Why an in-flight open/attach must not adopt this disposed terminal. */
cancelled?: "close" | "lifecycle";
@ -108,6 +110,17 @@ export class OpenClawTerminalPanel extends OpenClawLitElement {
private lifecycleSyncToken = 0;
private resizeCleanup: (() => void) | null = null;
private tabSeq = 0;
private readonly upload = new TerminalPanelUploadController({
activeTab: () =>
this.tabs.find(
(tab) => tab.id === this.activeId && tab.status === "live" && tab.gatewaySessionId,
),
client: () => this.client,
isCurrent: (tab) => this.tabs.includes(tab as TerminalTabState) && tab.status === "live",
fileInput: () => this.renderRoot.querySelector<HTMLInputElement>(".tp-file-input"),
setError: (message) => (this.errorText = message),
requestUpdate: () => this.requestUpdate(),
});
private readonly bootQueue = new TerminalTaskQueue();
protected createTerminal = createIsolatedGhosttyTerminal;
private readonly onGlobalKeyDown = (event: KeyboardEvent) => this.handleGlobalKey(event);
@ -510,6 +523,7 @@ export class OpenClawTerminalPanel extends OpenClawLitElement {
gatewaySessionId: "",
pendingInput: startupInput.buffer,
shellName: null,
shell: "",
agentId: null,
cwd: null,
controller,
@ -554,6 +568,7 @@ export class OpenClawTerminalPanel extends OpenClawLitElement {
): void {
tab.gatewaySessionId = result.sessionId;
tab.shellName = result.title ?? shellBasename(result.shell);
tab.shell = result.shell;
tab.agentId = result.agentId;
tab.cwd = result.cwd;
// Libterminal observes layout before the Gateway session exists. Resync the
@ -761,6 +776,7 @@ export class OpenClawTerminalPanel extends OpenClawLitElement {
this.lifecycleAbortController = new AbortController();
this.bootQueue.reset();
this.booting = false;
this.upload.dispose();
this.clearResizeListeners();
for (const tab of this.tabs) {
// No terminal.close here: this teardown runs for disconnects,
@ -895,53 +911,29 @@ export class OpenClawTerminalPanel extends OpenClawLitElement {
onClose: (id) => this.closeTab(id),
onNew: () => void this.openSession(),
})}
${this.fullscreen
? nothing
: html`<div class="tp-actions">
${renderTerminalSessionPicker({
open: this.sessionPickerOpen,
loading: this.sessionPickerLoading,
sessions: this.pickerSessions,
currentSessionIds: new Set(
this.tabs
.map((tab) => tab.gatewaySessionId)
.filter(
(sessionId): sessionId is string =>
typeof sessionId === "string" && sessionId.length > 0,
),
${renderTerminalPanelActions({
fullscreen: this.fullscreen,
dock: this.dock,
upload: this.upload,
sessionPicker: renderTerminalSessionPicker({
open: this.sessionPickerOpen,
loading: this.sessionPickerLoading,
sessions: this.pickerSessions,
currentSessionIds: new Set(
this.tabs
.map((tab) => tab.gatewaySessionId)
.filter(
(sessionId): sessionId is string =>
typeof sessionId === "string" && sessionId.length > 0,
),
onToggle: () => this.toggleSessionPicker(),
onRefresh: () => void this.refreshSessionPicker(),
onAttach: (sessionId) => void this.attachPickedSession(sessionId),
})}
<button
class="tp-icon ${this.dock === "bottom" ? "is-active" : ""}"
type="button"
title=${t("terminal.dockBottom")}
aria-label=${t("terminal.dockBottom")}
@click=${() => this.setDock("bottom")}
>
${DOCK_BOTTOM_GLYPH}
</button>
<button
class="tp-icon ${this.dock === "right" ? "is-active" : ""}"
type="button"
title=${t("terminal.dockRight")}
aria-label=${t("terminal.dockRight")}
@click=${() => this.setDock("right")}
>
${DOCK_RIGHT_GLYPH}
</button>
<button
class="tp-icon"
type="button"
title=${t("terminal.hide")}
aria-label=${t("terminal.hide")}
@click=${() => this.closePanel()}
>
${CLOSE_GLYPH}
</button>
</div>`}
),
onToggle: () => this.toggleSessionPicker(),
onRefresh: () => void this.refreshSessionPicker(),
onAttach: (sessionId) => void this.attachPickedSession(sessionId),
}),
onDock: (dock) => this.setDock(dock),
onHide: () => this.closePanel(),
})}
</header>
${this.errorText
? html`<div class="tp-error" role="alert">${this.errorText}</div>`
@ -952,10 +944,15 @@ export class OpenClawTerminalPanel extends OpenClawLitElement {
name=${this.activeId ?? "terminal"}
active
aria-labelledby=${this.activeId ? `terminal-tab-${this.activeId}` : nothing}
@dragenter=${this.upload.handleDragEnter}
@dragover=${this.upload.handleDragOver}
@dragleave=${this.upload.handleDragLeave}
@drop=${this.upload.handleDrop}
>
${this.booting && this.tabs.length === 0
? html`<div class="tp-empty">${t("terminal.starting")}</div>`
: nothing}
${renderTerminalUploadLayer(this.upload)}
</wa-tab-panel>
</section>
`;
@ -969,7 +966,7 @@ export class OpenClawTerminalPanel extends OpenClawLitElement {
}
}
static override styles = terminalPanelStyles;
static override styles = [terminalPanelStyles, terminalPanelUploadStyles];
}
declare global {

View file

@ -0,0 +1,160 @@
import { chromium, type Browser } from "playwright";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import {
canRunPlaywrightChromium,
installMockGateway,
resolvePlaywrightChromiumExecutablePath,
startControlUiE2eServer,
type ControlUiE2eServer,
} from "../test-helpers/control-ui-e2e.ts";
const chromiumExecutablePath = resolvePlaywrightChromiumExecutablePath(chromium.executablePath());
const chromiumAvailable = canRunPlaywrightChromium(chromiumExecutablePath);
const allowMissingChromium = process.env.OPENCLAW_UI_E2E_ALLOW_MISSING_CHROMIUM === "1";
const describeControlUiE2e = chromiumAvailable || !allowMissingChromium ? describe : describe.skip;
const expectUploadSurface = process.env.OPENCLAW_TERMINAL_UPLOAD_EXPECT_PRESENT !== "0";
const screenshotPath = process.env.OPENCLAW_TERMINAL_UPLOAD_SCREENSHOT?.trim();
let browser: Browser;
let server: ControlUiE2eServer;
describeControlUiE2e("Control UI terminal file upload", () => {
beforeAll(async () => {
if (!chromiumAvailable) {
throw new Error(
`Playwright Chromium is not installed or cannot start at ${chromiumExecutablePath}. Run \`pnpm --dir ui exec playwright install --with-deps chromium\`.`,
);
}
server = await startControlUiE2eServer();
browser = await chromium.launch({ executablePath: chromiumExecutablePath });
});
afterAll(async () => {
await browser?.close();
await server?.close();
});
it("uploads picked and dropped files, then pastes staged paths without Enter", async () => {
const context = await browser.newContext({
serviceWorkers: "block",
viewport: { width: 1280, height: 800 },
});
const page = await context.newPage();
await page.addInitScript(() => {
(
window as Window & {
["__OPENCLAW_NATIVE_CONTROL_AUTH__"]?: { gatewayUrl: string; token: string };
}
)["__OPENCLAW_NATIVE_CONTROL_AUTH__"] = {
gatewayUrl: "ws://gateway.example.test",
token: "test",
};
});
const stagedPath = "/tmp/openclaw-terminal-upload/sample file.pdf";
const gateway = await installMockGateway(page, {
deferredMethods: ["connect"],
featureMethods: ["terminal.open", "terminal.upload"],
methodResponses: {
"terminal.list": { sessions: [] },
"terminal.open": {
agentId: "main",
confined: false,
cwd: "/workspace",
sessionId: "terminal-upload-e2e",
shell: "/bin/bash",
},
"terminal.upload": { path: stagedPath, size: 4 },
},
terminalEnabled: true,
});
try {
await page.goto(`${server.baseUrl}?view=terminal`);
await gateway.waitForRequest("connect");
await gateway.resolveDeferred("connect");
await gateway.waitForRequest("terminal.open");
const addFiles = page.locator("button.tp-upload");
if (!expectUploadSurface) {
expect(await addFiles.count()).toBe(0);
if (screenshotPath) {
await page.screenshot({ path: screenshotPath });
}
return;
}
await addFiles.waitFor({ state: "visible" });
expect(await addFiles.isEnabled()).toBe(true);
if (screenshotPath) {
await page.screenshot({ path: screenshotPath });
}
await page.locator("input.tp-file-input").setInputFiles([
{ name: "sample file.pdf", mimeType: "application/pdf", buffer: Buffer.from("%PDF") },
{ name: "notes.txt", mimeType: "text/plain", buffer: Buffer.from("note") },
]);
await expect
.poll(async () => (await gateway.getRequests("terminal.upload")).length, {
timeout: 10_000,
})
.toBe(2);
const pickedUploads = await gateway.getRequests("terminal.upload");
expect(pickedUploads.map((request) => request.params)).toEqual([
{
sessionId: "terminal-upload-e2e",
name: "sample file.pdf",
contentBase64: "JVBERg==",
},
{
sessionId: "terminal-upload-e2e",
name: "notes.txt",
contentBase64: "bm90ZQ==",
},
]);
await expect
.poll(async () => (await gateway.getRequests("terminal.input")).length, {
timeout: 10_000,
})
.toBe(1);
const pickedInput = (await gateway.getRequests("terminal.input"))[0]?.params as {
data?: string;
};
expect(pickedInput.data).toContain("'/tmp/openclaw-terminal-upload/sample file.pdf'");
expect(pickedInput.data).not.toMatch(/[\r\n]/);
await page.locator("wa-tab-panel.tp-viewport").evaluate((target) => {
const transfer = new DataTransfer();
transfer.items.add(new File([new Uint8Array([1, 2, 3])], "dropped.png"));
target.dispatchEvent(
new DragEvent("dragenter", { bubbles: true, cancelable: true, dataTransfer: transfer }),
);
target.dispatchEvent(
new DragEvent("drop", { bubbles: true, cancelable: true, dataTransfer: transfer }),
);
});
await expect
.poll(async () => (await gateway.getRequests("terminal.upload")).length, {
timeout: 10_000,
})
.toBe(3);
const droppedUpload = (await gateway.getRequests("terminal.upload")).at(-1);
expect(droppedUpload?.params).toEqual({
sessionId: "terminal-upload-e2e",
name: "dropped.png",
contentBase64: "AQID",
});
await expect
.poll(async () => (await gateway.getRequests("terminal.input")).length, {
timeout: 10_000,
})
.toBe(2);
const droppedInput = (await gateway.getRequests("terminal.input")).at(-1)?.params as {
data?: string;
};
expect(droppedInput.data).toContain("'/tmp/openclaw-terminal-upload/sample file.pdf'");
expect(droppedInput.data).not.toMatch(/[\r\n]/);
} finally {
await context.close();
}
});
});

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:51.934Z",
"generatedAt": "2026-07-14T15:37:45.546Z",
"locale": "ar",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -535,6 +535,7 @@
{"cache_key":"4e8b7ee7bbcc3ee363c82ce19d80bf4fa44c695df555a9d42a07dc75454d8878","model":"gpt-5.6-sol","provider":"openai","segment_id":"skillWorkshop.queue.loadError","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Could not load proposals.","text_hash":"814058ea6e6bc7f50c19d52963dd8884be80bd7a23b9d00accd0e42022e512c4","tgt_lang":"ar","translated":"تعذر تحميل الاقتراحات.","updated_at":"2026-07-12T07:00:08.044Z"}
{"cache_key":"4ed7b64af9dcaf45e0965ccbad8aa18b20d6e7a139e4c26540259ff3d90d8080","model":"gpt-5.6-sol","provider":"openai","segment_id":"chat.commands.clearDescription","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Clear chat history","text_hash":"797a31a346b1a6256296ebe1b6d04dfdf22a2d9d67ad2d2c48370720c0c4bdae","tgt_lang":"ar","translated":"مسح سجل المحادثة","updated_at":"2026-07-12T07:00:45.634Z"}
{"cache_key":"4edc27e1a87e5b131758c269e103a39fa69e1150284f4ac02266a08697e554fb","model":"gpt-5.5","provider":"openai","segment_id":"cron.stats.scheduler","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Scheduler","text_hash":"d3a27d96cd0791a2b2161ed5cf5e3b5c0d360d05070e7bf6bf0e45d4e5a8f264","tgt_lang":"ar","translated":"المجدول","updated_at":"2026-07-09T21:53:23.244Z"}
{"cache_key":"4eeff42e7c8b43eec9cb2f278026d7c60efef74c250bd430e44238ff7b36e68a","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"ar","translated":"إضافة ملفات إلى الطرفية","updated_at":"2026-07-14T10:36:36.460Z"}
{"cache_key":"4f2841b2cce4d0b3f7b4bd1e52d77a2cf08f8f212172c8cf19a1646fdb4803d1","model":"gpt-5","provider":"openai","segment_id":"modelProviders.probe.status.ok","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Connected","text_hash":"22965568d22a14ee17af055d2870b50afcfe9fd94a83eec3196e266932297bb2","tgt_lang":"ar","translated":"متصل","updated_at":"2026-07-09T10:01:43.759Z"}
{"cache_key":"4f2c92d36346967c63f1179c6a7e8d9942385257ee61527be15404d1c09d50ef","model":"gpt-5.6-sol","provider":"openai","segment_id":"agents.toolCatalog.groups.nodes","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Nodes","text_hash":"7ac362063b9f204602f38f9f1ec9cf047f03e0d7b83896571c9df6d31ad41e9c","tgt_lang":"ar","translated":"العُقد","updated_at":"2026-07-12T06:57:34.656Z"}
{"cache_key":"4f35f1de814e48df3425d7ccb24ffa8bff62fcab0ee57ce60af3569c9456b4b7","model":"gpt-5.6-sol","provider":"openai","segment_id":"sessionsView.rowsPerPage","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"{count} per page","text_hash":"34671d4267b6d26e311454a2283688a2fa9da5f788b99f063068129e7cc09c1a","tgt_lang":"ar","translated":"{count} لكل صفحة","updated_at":"2026-07-12T06:57:30.154Z"}
@ -1403,6 +1404,7 @@
{"cache_key":"c56c5940ad05315204ae0393f41acce8223d1d014f3be6dbe4d20ee3cba96182","model":"gpt-5.6-sol","provider":"openai","segment_id":"skillsPage.clawHub","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"ClawHub","text_hash":"a2019fe71279ebb59b7876298299699524a6eb7885a04484409a1b556c8548f3","tgt_lang":"ar","translated":"ClawHub","updated_at":"2026-07-12T06:59:26.867Z"}
{"cache_key":"c581bed21a18848519a7481f58cdc056a9e4e417def0be84525553c36c928046","model":"gpt-5.6-sol","provider":"openai","segment_id":"dreaming.wiki.previewFallbackTitle","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Wiki page","text_hash":"3598a5a1e4cd6055bed67d7fca9076d0a4b0215eac44085e3d650eab5d17668c","tgt_lang":"ar","translated":"صفحة الويكي","updated_at":"2026-07-12T07:00:35.611Z"}
{"cache_key":"c5c2b11252739e2877ec6c8cf6b7cd934340cdcd2bcf7f1319571a7a32a5eedc","model":"gpt-5.5","provider":"openai","segment_id":"chat.sessionDiff.untracked","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"untracked","text_hash":"86ed2df8017823dff5b258f8082cf4be80ad80fed3388b6818d9a631a49e464e","tgt_lang":"ar","translated":"غير متعقب","updated_at":"2026-07-11T04:53:10.428Z"}
{"cache_key":"c620da8c5a8769452cda035da360c129e43ebef214e8de0e80466f1655ab0cf5","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"ar","translated":"جارٍ رفع الملفات…","updated_at":"2026-07-14T10:36:36.460Z"}
{"cache_key":"c647df64675118a6f95afb0d6c604eb34370ac9895f051fd541efb570fd772d9","model":"gpt-5.5","provider":"openai","segment_id":"chat.composer.noMicrophones","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"No additional microphones found","text_hash":"a6e4a20dda44dead8daa06da30fca7e7d90fa5aa4c15cbada30af1f52874d347","tgt_lang":"ar","translated":"لم يتم العثور على ميكروفونات إضافية","updated_at":"2026-07-06T17:33:50.709Z"}
{"cache_key":"c6570d69e46123db421265e90fce88cf9fd51b1f14535feb0371d71ad61e4524","model":"gpt-5.6-sol","provider":"openai","segment_id":"chat.toolCards.canvas","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Canvas","text_hash":"3824a9f4dafe92c6f1b80b40656a59784c03a824c27d58125d7d0ace753e2df2","tgt_lang":"ar","translated":"لوحة الرسم","updated_at":"2026-07-12T07:00:57.494Z"}
{"cache_key":"c65f7c23aabb213c289f6bbccf1056b3c20c7154fe2b3b58db1203d66693d3e9","model":"gpt-5.6-sol","provider":"openai","segment_id":"agents.skillsPanel.loadConfig","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Load the gateway config to set per-agent skills.","text_hash":"7d721609019cf7a5f56e1f289e45617b7d56926db11fbca2b19bf97e06600804","tgt_lang":"ar","translated":"حمّل إعدادات Gateway لتعيين Skills لكل وكيل.","updated_at":"2026-07-12T06:57:44.395Z"}
@ -1796,6 +1798,7 @@
{"cache_key":"fdc9e27b15c4316295b9bd8710c4b902393b4c7edb26f3abc22aafd000ca857c","model":"gpt-5.6-sol","provider":"openai","segment_id":"quickSettings.model.title","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Model & Thinking","text_hash":"e7fa5231806713c5a5d0a884c9706f24b330778c07f8390c116455a82abfba0d","tgt_lang":"ar","translated":"النموذج والتفكير","updated_at":"2026-07-12T06:58:23.581Z"}
{"cache_key":"fdd163f0b3dcf99f6994fff54757cf008ca139329050fc0c11ba7746dfb37277","model":"gpt-5.6-sol","provider":"openai","segment_id":"connection.access.connectHint","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Click Connect to apply connection changes.","text_hash":"473e1a24ad5a8bff00b2db667b8ff16a9b537a5b127dd2af42842620ea830b6d","tgt_lang":"ar","translated":"انقر على «اتصال» لتطبيق تغييرات الاتصال.","updated_at":"2026-07-12T00:09:09.397Z"}
{"cache_key":"fde68f6538750a4a1fa7fa9381c9cbb2334f7c63c124b17fe17500ddbf95b7d9","model":"gpt-5.5","provider":"openai","segment_id":"chat.backgroundTasks.finished","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Finished ({count})","text_hash":"075b0ee69a685d3a0fbf0b009794675b56ea66104ee5c931cd909140194f6be9","tgt_lang":"ar","translated":"مكتملة ({count})","updated_at":"2026-07-11T00:45:17.687Z"}
{"cache_key":"fdf42bf70cb42cb85a57865429ed42cdd8b78dff91e11d26113bf2492497d072","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"ar","translated":"أفلِت الملفات لإضافتها","updated_at":"2026-07-14T10:36:36.460Z"}
{"cache_key":"fdfae4037f1b921176091c183a97719273fd7b816e8b78e87bf309cbf1f5f1fc","model":"gpt-5.6-sol","provider":"openai","segment_id":"configView.sections.ui","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"UI","text_hash":"7c32699ff595e13b5c1315db137593163f4e28052592c776bea23471139b2422","tgt_lang":"ar","translated":"واجهة المستخدم","updated_at":"2026-07-12T06:58:48.215Z"}
{"cache_key":"fe12286b383bf01a6cf1daeb536d2e3c104f13a2694ab4f49de08e061131e766","model":"gpt-5.6-sol","provider":"openai","segment_id":"worktrees.cleanupMaxSize","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Max total size (GB)","text_hash":"cc527b42b91acf57e229f52b0f9e41797e56e48eb0962314f041586aeef223c9","tgt_lang":"ar","translated":"الحد الأقصى للحجم الإجمالي (GB)","updated_at":"2026-07-13T08:57:19.997Z"}
{"cache_key":"fe3108bf04a9a719ba1e3cec5751fb630c4f9d48edf50e53a06f77de0329f15e","model":"gpt-5.6-sol","provider":"openai","segment_id":"agents.skillsPanel.reason","source_path":"ui/src/i18n/locales/ar.ts","src_lang":"en","text":"Reason: {items}","text_hash":"81d7e0e0b82276324ba85e1f68d1a0a5c014658cfb3fbc01f9c24bd4c0bc5bd7","tgt_lang":"ar","translated":"السبب: {items}","updated_at":"2026-07-12T06:57:44.395Z"}

View file

@ -1,5 +1,5 @@
{
"fallbacks": {},
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"version": 1
}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:50.551Z",
"generatedAt": "2026-07-14T15:37:44.808Z",
"locale": "de",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -379,6 +379,7 @@
{"cache_key":"3370e1d00f22cfdaceffac5de196a27c9b29c7819554bd695abdf03e239885cc","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.dependenciesBlockedTitle","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Waiting on dependencies: {parents}.","text_hash":"50fb8f9b1326b69bd67d25583ddb4f70b9d75ae6e3ff8a9056a9361daa4b7d8b","tgt_lang":"de","translated":"Warten auf Abhängigkeiten: {parents}.","updated_at":"2026-06-16T14:12:59.821Z"}
{"cache_key":"339e013850a078472abfdc35510bae317847e1e0f5b2c245a73d8f613210d97b","model":"claude-opus-4-8","provider":"anthropic","segment_id":"filePreview.noMatches","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"No files match.","text_hash":"2ccf94bf0ca23256d6da7cde6b7f0da0906af09bd086292b1d3aefc2f3d6ab68","tgt_lang":"de","translated":"Keine passenden Dateien.","updated_at":"2026-07-12T06:24:53.539Z"}
{"cache_key":"33b35aa3f1ac602388332b476688766b1e9f6bc19af43244ff5c6f676031f2a8","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.detailPanel.noPreviewableMarkdown","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"No previewable markdown content.","text_hash":"a833f35167c66d5cb75593a749bd8b96395c929f46f3c7a7e71dff757d14dafc","tgt_lang":"de","translated":"Kein vorschaubarer Markdown-Inhalt.","updated_at":"2026-07-12T06:29:36.785Z"}
{"cache_key":"33c61b115ed91d6a5e1598d5b74cbadb111db55cb41a1ed3dde359ed254f2734","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"de","translated":"Dateien werden hochgeladen…","updated_at":"2026-07-14T10:36:18.325Z"}
{"cache_key":"33e8316ed3f105834e2d783ab819b39a6937433244142b909de5f196b173e223","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.workspaceFiles.browserCount","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"{count} shown","text_hash":"e57b4adfe868fd74a183650103d820176d4960bd0bdb677d9985db09f9752867","tgt_lang":"de","translated":"{count} angezeigt","updated_at":"2026-06-16T14:13:06.672Z"}
{"cache_key":"341a552c187d687046c80f1b4fa6f6d0e97692955aaba8a799f3fe868b1b991b","model":"claude-opus-4-8","provider":"anthropic","segment_id":"nodes.execApprovals.newPattern","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"New pattern","text_hash":"c6fbcde46fa9a9d2772cddd16675d11d0315ec6f505d859a2fd7a3cc65287e6e","tgt_lang":"de","translated":"Neues Muster","updated_at":"2026-07-12T06:25:37.276Z"}
{"cache_key":"3431cf560c7db005c0bc999391aceb93438f73b7593782a9e6a338bdc89d902b","model":"claude-opus-4-8","provider":"anthropic","segment_id":"nodes.execApprovals.allowlistHint","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Case-insensitive glob patterns.","text_hash":"db5c89db24461b936404c53fe2f7ddc83315691aec34f90bdafdf14d290c0601","tgt_lang":"de","translated":"Groß-/Kleinschreibung ignorierende Glob-Muster.","updated_at":"2026-07-12T06:25:37.276Z"}
@ -423,6 +424,7 @@
{"cache_key":"38e90629c5ab653eb98c51b46a96cd32b666c4df22f51e52491b54bf55937b4f","model":"gpt-5.5","provider":"openai","segment_id":"languages.hi","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"हिन्दी (Hindi)","text_hash":"fab2abfce45382f3031c59477017700a8cb5dfaf8d15379dc24304809b97c7d5","tgt_lang":"de","translated":"हिन्दी (Hindi)","updated_at":"2026-06-26T21:43:23.990Z"}
{"cache_key":"393e05f4f87ff8aeec1f5c0e35dc15c59806036ff7ce7e5f37b6c2719851ca74","model":"gpt-5","provider":"openai","segment_id":"codexSessions.scope.archived","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Archived","text_hash":"bdb86505f8062d15f152cef71dd4ca89609d5bf8e98771dcd2c9f70d247403da","tgt_lang":"de","translated":"Archiviert","updated_at":"2026-07-09T10:01:43.726Z"}
{"cache_key":"3945fedb6f0606aff28aba333b77d057d144d4b5767ff0abda9186c90cc019e6","model":"claude-opus-4-8","provider":"anthropic","segment_id":"nodes.execApprovals.enabled","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Enabled","text_hash":"92c1cdfdf4cb9cf6fcca962f206de36fd5d60db1178bc9461052f8de703a0e06","tgt_lang":"de","translated":"Aktiviert","updated_at":"2026-07-12T06:25:37.276Z"}
{"cache_key":"395c1e3e87a1e453def2dabf99ebbff3db1c46ca2bbc0cf5ba43291f9a3b8314","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"de","translated":"Dateien hier ablegen, um sie hinzuzufügen","updated_at":"2026-07-14T10:36:18.325Z"}
{"cache_key":"39943bee880812b78bde280b710a86b0b14e244881bfbbb3bb4cb0362fbc27ea","model":"gpt-5.5","provider":"openai","segment_id":"browser.start","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Start browser","text_hash":"4af2fc76dfa1bfc8b4b30cefd65fb5ca171d792bedc4cab90f082df7c9b961ff","tgt_lang":"de","translated":"Browser starten","updated_at":"2026-07-11T02:17:45.131Z"}
{"cache_key":"39e5b273989cca1e2b780b9e7d47117f7511f9b2701cc760a75762f442f0a5cf","model":"gpt-5.6-sol","provider":"openai","segment_id":"agentChip.working","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Working…","text_hash":"5474eef8d0f179c707cf418e2bbb468c77cc24edc5e9f5f4e137e85e06a8eea0","tgt_lang":"de","translated":"Arbeitet…","updated_at":"2026-07-12T23:39:03.678Z"}
{"cache_key":"39f21f129424f27f330f4f31c47b6b3b695ccfa2b53d75c83ee6097755752f17","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.session.description","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Session management and persistence","text_hash":"744f5b02b8639a6e3a4b00804534d2d0b6bc230a5c5f3403733c640d625f25ea","tgt_lang":"de","translated":"Sitzungsverwaltung und Persistenz","updated_at":"2026-07-12T06:26:23.146Z"}
@ -1052,6 +1054,7 @@
{"cache_key":"9553aa8b15a56ff003c14d11779500d79fd974f6e0274d107ab23a0e63d63636","model":"claude-opus-4-8","provider":"anthropic","segment_id":"dreaming.wiki.pageDetails","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Page details","text_hash":"86bbe3b1127c4076f48948f6a5a526db2d32efdef1f116d951b8f790dbb811b9","tgt_lang":"de","translated":"Seitendetails","updated_at":"2026-07-12T06:29:12.463Z"}
{"cache_key":"955ba0ca3d287e97bb5b48070236eb5ee6ed7ac30f0b243af50800b75efb5ee6","model":"gpt-5.5","provider":"openai","segment_id":"worktrees.empty","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"No managed worktrees.","text_hash":"67f97698da5ed0bb1cc4cadd157e403c0fcd22fc4735d8f39bcf27ea6dd612c8","tgt_lang":"de","translated":"Keine verwalteten Worktrees.","updated_at":"2026-07-05T21:00:37.724Z"}
{"cache_key":"957a360f8db70bfbe63b5912741b49d3714e2abb71c3885267f8b2eeee959e1f","model":"claude-opus-4-8","provider":"anthropic","segment_id":"cron.actions.runIfDue","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Run if due","text_hash":"1d9f1ae334e7591bf242d30542768eb1d4f91d01836b69642cfcea2eebd24663","tgt_lang":"de","translated":"Ausführen, wenn fällig","updated_at":"2026-07-12T06:29:49.618Z"}
{"cache_key":"9589137a60679edfbee3bb22229e9db952c23c4b5a99cc0812bcee6e1b8a50a5","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"de","translated":"Dateien zum Terminal hinzufügen","updated_at":"2026-07-14T10:36:18.325Z"}
{"cache_key":"9594c5c94f477d67e4dbb185c761d7183095416c4b1c7960302ca43d4f8058b5","model":"gpt-5.5","provider":"openai","segment_id":"chat.composer.realtimeTalkRequiresMicrophone","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Realtime Talk requires browser microphone access.","text_hash":"e082e85327dc5d2905a34ca4ca60e76836f9b4d7e3b1834b821c81a9c456b39d","tgt_lang":"de","translated":"Realtime Talk erfordert Mikrofonzugriff im Browser.","updated_at":"2026-07-06T17:56:14.727Z"}
{"cache_key":"959e833dc58f0912c0f2e318fb73b844dc83068ea2b1a84eea500ffcd57ab505","model":"gpt-5.5","provider":"openai","segment_id":"claudeSessions.searchLabel","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Search Claude sessions","text_hash":"538f7b50d5e731cf54a25b0714230f27a7da79f2830478993430f11701892470","tgt_lang":"de","translated":"Claude-Sitzungen suchen","updated_at":"2026-07-11T13:50:20.837Z"}
{"cache_key":"95a102d7744e0593e2656430e473fd61e141379d7111478df3a5530a4849e9b8","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agents.toolCatalog.descriptions.sessionsSpawn","source_path":"ui/src/i18n/locales/de.ts","src_lang":"en","text":"Spawn sub-agent","text_hash":"b022cd6d99d9c1096bac8dcae3ebc160c1ec428136e4437ed28922cfdea34950","tgt_lang":"de","translated":"Sub-Agent starten","updated_at":"2026-07-12T06:25:49.590Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:50.771Z",
"generatedAt": "2026-07-14T15:37:44.927Z",
"locale": "es",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -228,6 +228,7 @@
{"cache_key":"1bf6d6e495478e009f7dbb952d5bb0a3731651493e6ac77323a819b358b21b54","model":"claude-opus-4-8","provider":"anthropic","segment_id":"nodes.execApprovals.scope","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Scope","text_hash":"b073f6c68ef8721107fd9815b19b2c35ec111d526b75c2123d1111ba64424000","tgt_lang":"es","translated":"Ámbito","updated_at":"2026-07-12T06:31:44.630Z"}
{"cache_key":"1bfd871140f7c904944629f72952d209454be9d95bb120557ab8f71e5385f3b4","model":"gpt-5","provider":"openai","segment_id":"codexSessions.scopeLabel","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Session archive filter","text_hash":"9b7ab0c41b678c43f34c5e4d5b27428141588466c5d14b68bd19bcc93d7b6c38","tgt_lang":"es","translated":"Filtro de archivado de sesiones","updated_at":"2026-07-09T10:01:43.721Z"}
{"cache_key":"1c30ec67abaa19cbdb6d5fca80c4e6c513f8c4e28a0022ceed8436a20e689c29","model":"gpt-5.6-sol","provider":"openai","segment_id":"newSession.nodeCannotBrowse","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"This device doesn't support folder browsing","text_hash":"bb70bdb35a3e5252185e844f03ba04da79bcbe3a8fb2e4c82fe0377bb0dd7bb2","tgt_lang":"es","translated":"Este dispositivo no admite la exploración de carpetas","updated_at":"2026-07-12T18:40:02.321Z"}
{"cache_key":"1c8c785e5927f726f4d0397ee4f3f9b149f15dbb3d89fcc7ebe45b4c19968835","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"es","translated":"Subiendo archivos…","updated_at":"2026-07-14T10:36:20.719Z"}
{"cache_key":"1cac3cc6fec8d38ce69047c5ed38c050d5b0a53d9b9942de7c527552777ae664","model":"gpt-5.5","provider":"openai","segment_id":"browser.inspectName","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Name","text_hash":"dcd1d5223f73b3a965c07e3ff5dbee3eedcfedb806686a05b9b3868a2c3d6d50","tgt_lang":"es","translated":"Nombre","updated_at":"2026-07-05T21:00:41.074Z"}
{"cache_key":"1cb2c42ea023c5e5085afc88a8d602988bfb2570f9f05854b11ee2f0d29711b4","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.dependenciesBlocked","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"{count} blocked","text_hash":"fb39869b0fb3b8933126014e5c3739d7d67a620b8369781ca27e7395c595bde8","tgt_lang":"es","translated":"{count} bloqueadas","updated_at":"2026-06-16T14:14:17.778Z"}
{"cache_key":"1cc5d0481f4da5164b8f4a3612fa9c8c436ac0eb445d4f68e2e471e4d1780b60","model":"gpt-5.5","provider":"openai","segment_id":"connection.snapshot.status","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Status","text_hash":"920e413c7d411b61ef3e8c63b1cb6ad058d5f95f8b481dbafe60248387d8c355","tgt_lang":"es","translated":"Estado","updated_at":"2026-07-05T21:00:41.074Z"}
@ -833,6 +834,7 @@
{"cache_key":"6f13aa82fec1312b440a33f2fbaaf977fa7c86b6c48a78d77f498f1d6e7226f8","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.workspaceFiles.search","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Search files","text_hash":"179fed85ec50a433bb23932745d18f1ade2f84a6ebe145b0025ed3ce5f89fd5a","tgt_lang":"es","translated":"Buscar archivos","updated_at":"2026-06-16T14:14:23.912Z"}
{"cache_key":"6f1d40b46c758726496a5dc7d69bb658fe8bab4dfb745c5b46578c45daf7d018","model":"gpt-5.6-sol","provider":"openai","segment_id":"skillWorkshop.selfLearning.pitchBody","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"OpenClaw reviews corrections and substantial completed runs, then drafts skill proposals for this board. It spends extra background tokens and drafts arrive as pending proposals.","text_hash":"cdf9fee6c4e704b9cf13cf585d63364f0167bc0046da7fe4943228d5c9ef7dbd","tgt_lang":"es","translated":"OpenClaw revisa las correcciones y las ejecuciones sustanciales completadas y, a continuación, redacta propuestas de Skills para este tablero. Consume tokens adicionales en segundo plano y los borradores aparecen como propuestas pendientes.","updated_at":"2026-07-13T06:40:19.906Z"}
{"cache_key":"6f62f7636946409dac22df794e16efaf8eb2683fa74603677bc0d28e28968495","model":"gpt-5.5","provider":"openai","segment_id":"sessionsView.pinSession","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Pin session","text_hash":"813273b54d2df112a0fa1903110e9386779f8848ae288142d3f91d7a5891c8ff","tgt_lang":"es","translated":"Fijar sesión","updated_at":"2026-07-02T14:30:06.460Z"}
{"cache_key":"6f84512f713bb5e02417c751efc1b3cfe0ebf19025ae0e848c368cbe5197d8d6","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"es","translated":"Añadir archivos al terminal","updated_at":"2026-07-14T10:36:20.719Z"}
{"cache_key":"6f852256bea0d6ca4027b2f45137143601df35a7ad662adf569273ec1039cdde","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillStatus.disabled","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"disabled","text_hash":"17eb3c0168d0d7b21ede5481150f17233427d89833ec121b4dbc4fb96cfab71e","tgt_lang":"es","translated":"deshabilitado","updated_at":"2026-07-12T06:33:56.437Z"}
{"cache_key":"6fdf530ee58e871c5d18c02337eb60db3cd8e5c280da2fc4de62cc1a8533d3dc","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.noSettingsInSection","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"No settings in this section","text_hash":"e5fe71779954d756282be0995ce95183bb9ff370d67c6b63b9f8335f51c7ab9a","tgt_lang":"es","translated":"No hay ajustes en esta sección","updated_at":"2026-07-12T06:32:15.141Z"}
{"cache_key":"6fe07fc719b080e9f63a4cc33be2423eb835640f2d97cf4d042e053e617f3799","model":"gpt-5.5","provider":"openai","segment_id":"chat.sessionDiff.truncatedResult","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Some changes were omitted because the diff is very large.","text_hash":"1c0564ef3281e6e1c551539688c40190bb2124fa83bd3ff896c6fed8d4537d8d","tgt_lang":"es","translated":"Se omitieron algunos cambios porque el diff es muy grande.","updated_at":"2026-07-11T04:52:43.697Z"}
@ -1087,6 +1089,7 @@
{"cache_key":"9293474dd2f449b6e0db785e9668f9e8eafa861bf91ce051050a52c05eaaeb47","model":"gpt-5.5","provider":"openai","segment_id":"pluginsPage.mcpNameTaken","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"An MCP server named “{name}” already exists.","text_hash":"32cef939d87970acbaf7a2dbc668f06f2e6f78f3e2f21252f66eb6a4148477cd","tgt_lang":"es","translated":"Ya existe un servidor MCP llamado “{name}”.","updated_at":"2026-07-10T02:23:49.859Z"}
{"cache_key":"929e61ada27a15fbcbc23540e0c12ede046dff17df300af443382149733abb8f","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.detail.supportFilesTitle","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Support files","text_hash":"7850bc0717416285d154ec1a5e279172ec32d2173d5058ac0f456ebbb07c53ec","tgt_lang":"es","translated":"Archivos de apoyo","updated_at":"2026-07-12T06:34:29.611Z"}
{"cache_key":"92b63e63b5f48e252c589bf75f82c9a292cff8946345e7148752384241efc35b","model":"claude-opus-4-8","provider":"anthropic","segment_id":"dreaming.wiki.loadingInsights","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Loading imported insights…","text_hash":"6f15375302e8340787a035bd20edd48102fa6aa24d500dce660ed6087c0d163b","tgt_lang":"es","translated":"Cargando información importada…","updated_at":"2026-07-12T06:34:59.169Z"}
{"cache_key":"92bd0b9c824451b799c3abe4fb39e1b175ee7884c759dc8f590094da0cffbb44","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"es","translated":"Suelta los archivos para añadirlos","updated_at":"2026-07-14T10:36:20.719Z"}
{"cache_key":"9317949764f5b5d50e5f9bd1c0d03000ddb0186df92ae2105327a3d21e159be5","model":"claude-opus-4-8","provider":"anthropic","segment_id":"dreaming.wiki.unavailable","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Memory Wiki is not enabled","text_hash":"bbef7667ef8aa44c7ac1cc52bcf925a27baf524186f513f333bdd41331fb9939","tgt_lang":"es","translated":"Memory Wiki no está habilitado","updated_at":"2026-07-12T06:35:05.818Z"}
{"cache_key":"932d29ab2368d1385f2cd5aef90bb33c395b8d7dc80915ad9a473ecb7ba02cd2","model":"gpt-5.6-sol","provider":"openai","segment_id":"channels.setup.starting","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"Starting setup…","text_hash":"696abab0be63faeb1adbd218caf069dc625bd43bda829b60d6ad7c239241d6cd","tgt_lang":"es","translated":"Iniciando configuración…","updated_at":"2026-07-13T16:51:32.277Z"}
{"cache_key":"9388b37364e754f8738e76f1e85ca62d97e593486578c03b340690ed48076ab0","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.sensitiveHidden","source_path":"ui/src/i18n/locales/es.ts","src_lang":"en","text":"{count} sensitive value hidden. Use the reveal button above to edit the raw config.","text_hash":"b3abcddb81ee262d824f021934f3b43bfb753900f46005d02c94632ce0d56313","tgt_lang":"es","translated":"{count} valor sensible oculto. Usa el botón de mostrar de arriba para editar la configuración en bruto.","updated_at":"2026-07-12T06:33:26.031Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:54.089Z",
"generatedAt": "2026-07-14T15:37:46.633Z",
"locale": "fa",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -15,6 +15,7 @@
{"cache_key":"018684e9a42b5490d2b35522c39111b2fc482bfb075e4f4d363b8f5da074c822","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.appearance.clear","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Clear {name}","text_hash":"c83ca98005e2d590d784242d9a70bab2285f92b69f1088c93bff09a7da0071af","tgt_lang":"fa","translated":"پاک‌کردن {name}","updated_at":"2026-07-12T06:55:29.728Z"}
{"cache_key":"0188362ada7975d19c376b2bd02d8dbf0b3281261a61c72181242d09e8faaac7","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.revision.send","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Send revision","text_hash":"953cc98c1bd59e81931f812a7edcb0f9e313737c18b15e1743e1c01a32d9fbbf","tgt_lang":"fa","translated":"ارسال بازبینی","updated_at":"2026-07-12T06:57:42.109Z"}
{"cache_key":"018eb138469c3b09ebd23d82da2a50dfc242e957dd5213c29e5621fcec828312","model":"gpt-5.6-sol","provider":"openai","segment_id":"aboutPage.linkChangelog","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Changelog","text_hash":"ead07c84baac57a9542f388a07a2a5209456ce790b04251bc9bd7d179ea85cb1","tgt_lang":"fa","translated":"تغییرات","updated_at":"2026-07-13T17:00:24.058Z"}
{"cache_key":"019f527530a8cad08f972ef85ee8256f60b7fb225e44a46888d249b4eb4feb3e","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"fa","translated":"برای افزودن، فایل‌ها را اینجا رها کنید","updated_at":"2026-07-14T10:36:58.649Z"}
{"cache_key":"01a580ba8d16feda69f05cc3763f19a73ffee12f1d3ab904d348a31e8e843f2a","model":"gpt-5.6-sol","provider":"openai","segment_id":"connection.help.step3","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Paste the WebSocket URL and token above, or open the tokenized URL directly.","text_hash":"9c978945315941b9182aa1d51e3465e2250e626234123299ff5fc59b7b01b0ab","tgt_lang":"fa","translated":"نشانی URL وب‌سوکت و توکن را در بالا جای‌گذاری کنید، یا نشانی URL توکن‌دار را مستقیماً باز کنید.","updated_at":"2026-07-12T00:11:15.410Z"}
{"cache_key":"0231c1d6527f34072e8e43aea7ca0070ac1aac228356d2170dee26f3a9b8f190","model":"gpt-5.6-sol","provider":"openai","segment_id":"aboutPage.productName","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"OpenClaw","text_hash":"a7b90ee8facf0aed66654381629a6ae2983257dfe5daad4ae455dbf49fc6d39b","tgt_lang":"fa","translated":"OpenClaw","updated_at":"2026-07-13T17:00:24.058Z"}
{"cache_key":"02335432c12a7b1897346cf2c3f47d1c6901decaf514c43514888e4d14f0d42e","model":"claude-opus-4-8","provider":"anthropic","segment_id":"approvalPage.commandLabel","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Command","text_hash":"713166971d730f81fcf8b757f2ea239d1a0360d9f74e8f5afe60fba97105879c","tgt_lang":"fa","translated":"دستور","updated_at":"2026-06-16T14:18:51.277Z"}
@ -1058,6 +1059,7 @@
{"cache_key":"96ed738e6f6ccedbb4a41f9ee43e931c442421558108966a5cf5522b8ea1df5d","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.agentCurrentUnconfigured","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"{agent} (not configured)","text_hash":"d138ab0079dea760c723d7c947d0c31178252e28e7dd70a40b9d3d85e5549b1d","tgt_lang":"fa","translated":"{agent} (پیکربندی‌نشده)","updated_at":"2026-06-17T14:17:45.319Z"}
{"cache_key":"9701519cddd04f892dd0bb08f1dd8d5ad7bf3b342a2c485949b1d2cca12a7cda","model":"claude-opus-4-8","provider":"anthropic","segment_id":"quickSettings.security.configure","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Configure →","text_hash":"3853cdcbe571c3cc86f127a799dfbcc2540b79f092761008c94f70976f8d9e7c","tgt_lang":"fa","translated":"پیکربندی →","updated_at":"2026-07-12T06:54:30.738Z"}
{"cache_key":"9716452071a69f64a651265be84f518ba1b5451bc36660a220704db3a2866504","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.categories.communication","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Communication","text_hash":"3981a2b9c1ef7fce8dbf5e3d44fefc58746dee11b3de35655e166c25142612ba","tgt_lang":"fa","translated":"ارتباطات","updated_at":"2026-07-12T06:54:55.127Z"}
{"cache_key":"9746fecfd5cfdac9a96eb126e53fe5d9ce830baff48cc6f6373366dc8d8b670b","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"fa","translated":"افزودن فایل‌ها به ترمینال","updated_at":"2026-07-14T10:36:58.649Z"}
{"cache_key":"974b6ff9785e1a2811910a1e541f50cfdcc6607ea441b7d09af3698d4dc9483b","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.add","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Add","text_hash":"9fd728c66c9a256b121472dabf32a34317aed01d8427d70ec830289cf23a7cc8","tgt_lang":"fa","translated":"افزودن","updated_at":"2026-07-12T06:53:45.652Z"}
{"cache_key":"975a105c5fbc124586523c7b366b85ed8995b75eff5bb52038249a3e17caf50c","model":"gpt-5.5","provider":"openai","segment_id":"chat.pullRequests.checksPassed","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Passed","text_hash":"436fe71bb9561f0596161c4d50c7b23327b4189acaf63dc89f4f9205b67a7528","tgt_lang":"fa","translated":"موفق","updated_at":"2026-07-10T23:12:56.540Z"}
{"cache_key":"978530616850724b324dc88ea19a41fe2d221759ee174298ea7bea8d2b9f2f65","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.commands.arguments","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Command arguments","text_hash":"55fa47390d07fd1ab8f6012db1ec61b3db5c4eb58392cbaeeb2d9a8c054a7d5a","tgt_lang":"fa","translated":"آرگومان‌های دستور","updated_at":"2026-07-12T06:59:00.077Z"}
@ -1152,6 +1154,7 @@
{"cache_key":"a63186f92f68ab0571da7caa5a0159ccbeaf3794f99747ffd98edb15c6e03995","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.healthLabel","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Workboard health","text_hash":"85416c4a6d64e35611bdd9747b82815936c38b41d820796ba1fbfbb7539d906b","tgt_lang":"fa","translated":"سلامت Workboard","updated_at":"2026-06-17T14:17:52.321Z"}
{"cache_key":"a6549ea80d7a8320bff4161aeacad61b35acd63f9520f9773fc13a7abb368aa9","model":"claude-opus-4-8","provider":"anthropic","segment_id":"mcpApp.title","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"MCP App","text_hash":"02cc8d80ba6a1d436ead6100fcbfa433910ee0f6213ac1f0967a892d3e36da4b","tgt_lang":"fa","translated":"اپلیکیشن MCP","updated_at":"2026-07-12T06:52:07.804Z"}
{"cache_key":"a65dce319fb8244b86036b1972f5eb11fd5ab7fa84d0551a8b2131f0f8514083","model":"claude-sonnet-4-6","provider":"anthropic","segment_id":"cron.suggestions.ideas.hackerNewsScout.tagline","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Three links worth your coffee, with hot takes.","text_hash":"922d22c3e5d733801932294931d820adb4dae9b35ddf8651388152ea85b62d6f","tgt_lang":"fa","translated":"سه لینک ارزشمند برای وقت قهوه‌ات، با نظرات تند.","updated_at":"2026-07-11T22:49:26.248Z"}
{"cache_key":"a65f83463be8bceb30a069b36cdd309c36dc2b48db91df8e0c96d17ffd3ed923","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"fa","translated":"در حال بارگذاری فایل‌ها…","updated_at":"2026-07-14T10:36:58.649Z"}
{"cache_key":"a66f60fc010d62dba87d7de61f3d11a9c706299059f8476dc1a8393960b59731","model":"gpt-5.5","provider":"openai","segment_id":"sessionsView.deletePreservedWorktrees","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"{count} session worktree(s) with uncommitted or unpushed work were kept ({branches}). Manage them under Settings -> Worktrees.","text_hash":"ea23d20337ae63b1674d725c6fb960a81e6d704e02c38f48690ed41418fbfe04","tgt_lang":"fa","translated":"{count} worktree نشست با تغییرات commitنشده یا pushنشده نگه داشته شد ({branches}). آن‌ها را از Settings -> Worktrees مدیریت کنید.","updated_at":"2026-07-10T18:00:09.518Z"}
{"cache_key":"a6a89aa113409d149192e5f1a5e8f05726369bef330cf6e1d607ec200131ca74","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configPage.channels.discord","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Discord","text_hash":"053bc65874ad6098e58c41c57b378a2f36b0220e5e0b46722245e6c2f796818c","tgt_lang":"fa","translated":"Discord","updated_at":"2026-07-12T06:54:55.127Z"}
{"cache_key":"a6b5fcc0f2a8f9eb8ea1e56dd21845cf85f9e0bbb8c8e7900abe1521365d9f82","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillsPage.filterPlaceholder","source_path":"ui/src/i18n/locales/fa.ts","src_lang":"en","text":"Filter installed skills","text_hash":"9b54d448946084f1c7c13dbfe037ea9d75bc3f29e0c77e4dd023741d6c34001e","tgt_lang":"fa","translated":"فیلتر Skills نصب‌شده","updated_at":"2026-07-12T06:56:35.267Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:51.450Z",
"generatedAt": "2026-07-14T15:37:45.312Z",
"locale": "fr",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -102,6 +102,7 @@
{"cache_key":"0de4c241e0dc1b7fb9548e87fb360da258cb390d45c1463ea2018bc52299233b","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agents.skillsPanel.allEnabled","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"All skills are enabled. Disabling any skill will create a per-agent allowlist.","text_hash":"1e82fad3faa79bbad0de4d4d2430a0e419a9f7d8eaf7a8b526d7b04343c774a4","tgt_lang":"fr","translated":"Tous les Skills sont activés. Désactiver un Skill créera une liste d'autorisation par agent.","updated_at":"2026-07-12T06:32:51.965Z"}
{"cache_key":"0df9235ae85f06f1a0ca46eafdc6ffcb27124c5da4573aae446c1290f50471c3","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentChip.agents","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Agents","text_hash":"279b44d2ab4b40c0fc132f8f3051293544cca91de9c8aa14f2cd29adb132b0ee","tgt_lang":"fr","translated":"Agents","updated_at":"2026-07-12T06:33:42.229Z"}
{"cache_key":"0e35020d1adb415eb12da2e7664a2a10258ceac5aa34e4f1ccde3f0193b8f9eb","model":"gpt-5","provider":"openai","segment_id":"codexSessions.status.idle","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Idle","text_hash":"ab0171ca0494d441cb6fe96e2efbe1c2a129f1d87cd6c17f03613cfd111149dd","tgt_lang":"fr","translated":"Inactive","updated_at":"2026-07-09T10:01:43.739Z"}
{"cache_key":"0e489681177b8acc0a2e2aa82ba450040f570c0eebc3ac9fb99693a0abf8a197","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"fr","translated":"Téléversement des fichiers…","updated_at":"2026-07-14T10:36:28.546Z"}
{"cache_key":"0e4b9c05b139c190952060fb88b6941e6b67eb375455366a809eeb78992de60b","model":"gpt-5.5","provider":"openai","segment_id":"workboard.eventAttachmentAdded","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Attachment added","text_hash":"f39a309fb0054d8e6c512733d6f3a4791c6b63157a388d72f635574d98b49b3e","tgt_lang":"fr","translated":"Pièce jointe ajoutée","updated_at":"2026-05-30T15:38:23.998Z"}
{"cache_key":"0ebf3031872afc9f1d9ab83044cf8543f9be006020153dcf041392637a14fdc4","model":"gpt-5","provider":"openai","segment_id":"codexSessions.empty.subtitle","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Enable Codex session sharing on the gateway or a paired computer, then refresh this view.","text_hash":"608ae8a39625a0da1b6804480e57835af5a1e566af2095d11cca8bf0a6e421a9","tgt_lang":"fr","translated":"Activez le partage des sessions Codex sur le Gateway ou un ordinateur jumelé, puis actualisez cette vue.","updated_at":"2026-07-09T10:01:43.739Z"}
{"cache_key":"0f1db0da82207aaaa7ab08e10af7a928b123759f645c3600a8075073378bfd2b","model":"gpt-5.6-sol","provider":"openai","segment_id":"debug.callFailed","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Call failed","text_hash":"f5da6de3a9801f3e8b05f8f99ecf1f6c3b72b2865f2355fb3004551e2f2233fd","tgt_lang":"fr","translated":"Échec de lappel","updated_at":"2026-07-13T16:00:32.584Z"}
@ -690,6 +691,7 @@
{"cache_key":"5edefba270f5bd737188ce800e5f459b00c39506ada2f8b4cf023de567b7d592","model":"gpt-5.6-sol","provider":"openai","segment_id":"pluginsPage.hubTablistLabel","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Plugins sections","text_hash":"406d17a78b9662b89e0bde0e53699cf8702e066524b07226f0e4073633806231","tgt_lang":"fr","translated":"Sections des plugins","updated_at":"2026-07-12T02:11:15.947Z"}
{"cache_key":"5f0740cce62cd24970f716d10b5e62d3056ccc99bb1ef5e8feb4810b396ddb64","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.commands.categories.model","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Model","text_hash":"5e2c614c23f02239bc03c6c04fcb681950f9e72bf8fdff6be79c79841cbb10c0","tgt_lang":"fr","translated":"Modèle","updated_at":"2026-07-06T20:20:02.809Z"}
{"cache_key":"5f16d115ffe9e89761fff4bcaf5ed813a8f4de140bd458d6ad0c8cbbc087d9af","model":"gpt-5.5","provider":"openai","segment_id":"subtitles.mcp","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"MCP servers, auth, tools, and diagnostics.","text_hash":"3eb7bf08a81e00ed41da1b60096320c5b90ff4d4e78b3f84ecd9ce45a62eaea1","tgt_lang":"fr","translated":"Serveurs MCP, authentification, outils et diagnostics.","updated_at":"2026-05-31T05:36:40.482Z"}
{"cache_key":"5f207d763f2589438243bd6dbe3e70ae67cd19b304eb4f6f6f94a71a2c24d59b","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"fr","translated":"Déposez des fichiers pour les ajouter","updated_at":"2026-07-14T10:36:28.546Z"}
{"cache_key":"5f210b70ec285a1fdb5309333b64ed2f2efbf2a51def2ca7e0e079bf9f612706","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.detailNoNotes","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"No operator notes yet.","text_hash":"497e07f47e33851483b6fb1254e88dc640d9fb25525c51f89934a7d39d7b2b9c","tgt_lang":"fr","translated":"Aucune note d'opérateur pour le moment.","updated_at":"2026-06-16T14:14:33.243Z"}
{"cache_key":"5f66e5dd16cec079b524a179ec0716ec7add4bd53b120708825a783a3bfab443","model":"claude-opus-4-8","provider":"anthropic","segment_id":"mcpPage.filtered","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Filtered","text_hash":"0ba993b39efb02f1505045d3817f64edaf72945816bc8740073cbd220e1b86a5","tgt_lang":"fr","translated":"Filtré","updated_at":"2026-07-12T06:34:41.786Z"}
{"cache_key":"5f6f0a3f8c7523c59168734b9cee5b4d91eed45257edf3e63e53dc44b36e51d1","model":"gpt-5.5","provider":"openai","segment_id":"pluginsPage.enabledRestart","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Enabled {name}. A Gateway restart is required to apply the change.","text_hash":"083874feeadefa0eb380551b0f3050737c11bd8d667747d7e8ec6a185a35ff01","tgt_lang":"fr","translated":"{name} activé. Un redémarrage de Gateway est nécessaire pour appliquer la modification.","updated_at":"2026-07-10T02:24:56.669Z"}
@ -1442,6 +1444,7 @@
{"cache_key":"c57b6089a8064cf26172436a1e12bc7cc7b9a38b747a13ea3bb5f69143dac266","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.detailAutomationBoard","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Board: {board}","text_hash":"96d7493589e40e17803b3bf643dff1b891a4ebf57f5d2b36af0a7ddd09e64b84","tgt_lang":"fr","translated":"Tableau : {board}","updated_at":"2026-06-16T14:14:26.985Z"}
{"cache_key":"c5aa4914162e9bee0f3f7a6b0f7b3d1fcdb3ff742ff9b6efd1305e6af788f809","model":"claude-opus-4-8","provider":"anthropic","segment_id":"quickSettings.security.execPolicy","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Exec policy","text_hash":"8b5851a4f8118ca3f0529eaba53f1779d3d686f3db44d12566633c800948c972","tgt_lang":"fr","translated":"Politique d'exécution","updated_at":"2026-07-12T06:33:25.514Z"}
{"cache_key":"c5b9bc04bedc60c9a1dc2273e55211947239433fea287d584da5716384a8a135","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.composer.removeAttachment","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Remove attachment","text_hash":"595b066a8838734a2b17efe5b7860be04047105d705203219d0b4c3cccd13c57","tgt_lang":"fr","translated":"Supprimer la pièce jointe","updated_at":"2026-07-12T06:36:13.855Z"}
{"cache_key":"c5d2afd002f5d0d83c7c1ed70c25b516b8721bf83bed0b27a24117e0bfa6fb10","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"fr","translated":"Ajouter des fichiers au terminal","updated_at":"2026-07-14T10:36:28.546Z"}
{"cache_key":"c6171f6edb7d1b6e28b1249b731c05392519678125fefd8d84e27d30aba55b2c","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.empty.allTitle","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"No proposals here","text_hash":"30289613b7f4e190e5a04e8544571a9ef3fadac44112c7378c49a3bff5688270","tgt_lang":"fr","translated":"Aucune proposition ici","updated_at":"2026-07-12T06:35:23.166Z"}
{"cache_key":"c64faca6f54bfc43e0ae21e59efce762658b40416a64c3c830d37c1a3b5e7bef","model":"gpt-5","provider":"openai","segment_id":"codexSessions.empty.search","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"No sessions on this host match your search.","text_hash":"53e8e235da1a4490f8514580987af37d3693f5232882f414ce75de09cd4203f9","tgt_lang":"fr","translated":"Aucune session de cet hôte ne correspond à votre recherche.","updated_at":"2026-07-09T10:01:43.739Z"}
{"cache_key":"c66add0a2c3b5d359c7e94fcb993a5375102b04bcde0474146aa9680c5681814","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentTools.access","source_path":"ui/src/i18n/locales/fr.ts","src_lang":"en","text":"Access","text_hash":"ec5ba0abb717da87aab2655bd4b4a40f93f2a591a0ade63611c42925c49c17e9","tgt_lang":"fr","translated":"Accès","updated_at":"2026-07-12T06:34:31.353Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:51.668Z",
"generatedAt": "2026-07-14T15:37:45.429Z",
"locale": "hi",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -421,6 +421,7 @@
{"cache_key":"20f9e28644c112af543776dbc0648d3ed0030f9bf546525d1660a551cbcb2c88","model":"gpt-5.6-sol","provider":"openai","segment_id":"cron.list.viewLabel","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Automation views","text_hash":"2c9fc1a975fc498bf6056ec99aa385b4a3cba193f8ea635f508ed9a350d572ea","tgt_lang":"hi","translated":"ऑटोमेशन दृश्य","updated_at":"2026-07-13T13:04:07.008Z"}
{"cache_key":"20fee00ed89aca024976cb437cf89d4213eddb9710390a575105c398a4a44974","model":"gpt-5.5","provider":"openai","segment_id":"workboard.autoRefresh60s","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"60s","text_hash":"f79f071ab5b033ca8fb42c077f39708930d194b18f4608eb26ac1d9665a8836f","tgt_lang":"hi","translated":"60s","updated_at":"2026-06-26T21:32:33.484Z"}
{"cache_key":"212a67822ca54782c7ec8b877648577bf7be75e7214a564645af424e7e0a3fb0","model":"gpt-5.5","provider":"openai","segment_id":"dreaming.phase.light","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Light","text_hash":"dbcd5e7bb7a0f538810de44c3efbd813037ee3fa358747bb71fa58e157af45f7","tgt_lang":"hi","translated":"हल्का","updated_at":"2026-06-26T21:33:54.151Z"}
{"cache_key":"212f4ee5314a932a3f5fa882403dd86fffced1a3e570071c34665968a04fe2ba","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"hi","translated":"फ़ाइलें जोड़ने के लिए उन्हें यहाँ छोड़ें","updated_at":"2026-07-14T10:36:33.477Z"}
{"cache_key":"2139082f521fa4dcf16644646fb1de6ff28059ad373dfc98af6d12bbd4b8d9c9","model":"gpt-5.5","provider":"openai","segment_id":"agents.files.coreFilesTitle","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Core Files","text_hash":"83c68c93244246cb86ff828bc82864f1e01057b3c0cc5745fde4ccf162b81cdf","tgt_lang":"hi","translated":"मुख्य फ़ाइलें","updated_at":"2026-06-26T21:30:58.804Z"}
{"cache_key":"213e7c6f6e55bed8283ea9b5ea5356d3d1cc8f037b4c4500f6a12f25ae375f36","model":"claude-opus-4-8","provider":"anthropic","segment_id":"nodes.execApprovals.defaultPrompt","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Default prompt policy.","text_hash":"706caab005a665c6f47fd0b836c7b86adc029afb5a7779e4c8149dbbdeab2750","tgt_lang":"hi","translated":"डिफ़ॉल्ट प्रॉम्प्ट नीति।","updated_at":"2026-07-12T06:38:07.948Z"}
{"cache_key":"21428dc93d46802310271328a0d6080b0ddefcf7e658c850761b87daa855a9da","model":"gpt-5.5","provider":"openai","segment_id":"lazyView.unknownError","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Unknown module load error.","text_hash":"aac7340f2785adb609e98dd446aa05dff6d6a839e94c666cf3663aaab9ec75da","tgt_lang":"hi","translated":"अज्ञात मॉड्यूल लोड त्रुटि।","updated_at":"2026-06-26T21:29:59.416Z"}
@ -1165,6 +1166,7 @@
{"cache_key":"59e85e42260b9bb57b86e01e4bad2369bef9698f622721e1521a6f84c2677391","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentTools.enabledSummary","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"{enabled}/{total} enabled.","text_hash":"459c4e1be47cb122e6b393dad90a635ade6a40cb54e6470bbb29170fd77ca3b8","tgt_lang":"hi","translated":"{enabled}/{total} सक्षम।","updated_at":"2026-07-12T06:40:23.142Z"}
{"cache_key":"5a109f7e5a1023bda5a791c487bbc081269d1cda65df70fbd0348a66ca0f2057","model":"gpt-5.5","provider":"openai","segment_id":"sessionsView.pinSession","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Pin session","text_hash":"813273b54d2df112a0fa1903110e9386779f8848ae288142d3f91d7a5891c8ff","tgt_lang":"hi","translated":"सत्र पिन करें","updated_at":"2026-07-02T14:30:19.917Z"}
{"cache_key":"5a19fa0379637f71b89a82cdd07ac554c084ff0894bad77bedf40fc8a3202cae","model":"gpt-5.5","provider":"openai","segment_id":"usage.overview.messagesAbbrev","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"msgs","text_hash":"8dc321b9135ee4fbee83a304b911e871f83e7ae84d344bae6f464804f77b2f86","tgt_lang":"hi","translated":"msgs","updated_at":"2026-06-26T21:34:59.501Z"}
{"cache_key":"5a3d816d615aa599bc0b526ac4e276eeac4d5b6ca81a635af4fa1134e6b18add","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"hi","translated":"फ़ाइलें अपलोड की जा रही हैं…","updated_at":"2026-07-14T10:36:33.477Z"}
{"cache_key":"5a652472b26a8feff8e9d1677ddd78a783930fdb1d61f3598db00857bf79339e","model":"gpt-5.5","provider":"openai","segment_id":"quickSettings.appearance.lobsterdexSeen","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"{seen}/{total} visited","text_hash":"e256f4f2c8acf9532195feecb6268817520de975b7e7e6d02c346126c660f556","tgt_lang":"hi","translated":"{seen}/{total} देखे गए","updated_at":"2026-07-09T23:55:54.447Z"}
{"cache_key":"5a6cca28eb3069da1ccbe5794d1f19a02ae808f1261a30a8bc3769afdaacbb3a","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agents.skillsPanel.missing","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Missing: {items}","text_hash":"cbac89d53f3ea69adc70232eba66bdfa63ea0764887769f263870b2b35e36723","tgt_lang":"hi","translated":"अनुपस्थित: {items}","updated_at":"2026-07-12T06:38:32.661Z"}
{"cache_key":"5a778d51a9edd7000f9834384901aae5b108042f69975bbb1306b1c3d70f854d","model":"gpt-5.5","provider":"openai","segment_id":"workboard.enableConfigKey","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"plugins.entries.workboard.enabled = true","text_hash":"a518af5219772b9cbcbf63f90c12c6e048059e4e5b23a97e9785b36850a77022","tgt_lang":"hi","translated":"plugins.entries.workboard.enabled = true","updated_at":"2026-06-26T21:31:58.515Z"}
@ -2200,6 +2202,7 @@
{"cache_key":"b2275a379314f0960dfe84e0fc1e09c63e7bf0163d92bb21ee586469f7853fae","model":"gpt-5.6-sol","provider":"openai","segment_id":"worktrees.cleanupMaxCount","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Max worktrees","text_hash":"a834511e1162b37b5fb8400bd75b47b6388ab7185eba0f3725af74412a142401","tgt_lang":"hi","translated":"अधिकतम worktrees","updated_at":"2026-07-13T08:57:14.358Z"}
{"cache_key":"b22bdd81558ad589b24db340a380f3d92d4775bc9958126d22f5481f2a09e8b9","model":"gpt-5.5","provider":"openai","segment_id":"workboard.fieldNotes","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Notes","text_hash":"8a7525b1492fb84833f5c4a69b30f4bfbb134f9b666b61a2c1872d63d234c085","tgt_lang":"hi","translated":"नोट्स","updated_at":"2026-06-26T21:32:39.899Z"}
{"cache_key":"b23a40d7376c68818ceb6b2d78fa1e3933ba8d0a4708e4c3230cdd236f24454a","model":"gpt-5.5","provider":"openai","segment_id":"overview.palette.descriptions.shellCommand","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Run shell","text_hash":"154bfb96f42aa0efee3099944c7f98497cdb0a90e8f77fefa9ccecad51c20ff5","tgt_lang":"hi","translated":"शेल चलाएँ","updated_at":"2026-06-26T21:33:46.154Z"}
{"cache_key":"b27abd093748d8cd5d8c4ad6a17eade7f97ed9a5f31afd3b30268d50fb3c2009","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"hi","translated":"टर्मिनल में फ़ाइलें जोड़ें","updated_at":"2026-07-14T10:36:33.477Z"}
{"cache_key":"b28e661da20b1da0cfb9b67adbd62eed56f76125df5f49295d3dc0894597d3eb","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillGroups.builtIn","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Built-in Skills","text_hash":"eb4f7789eadee2923123c6c7cffa5295c22e4e1b3158d71a792fa643f2ed8d66","tgt_lang":"hi","translated":"बिल्ट-इन Skills","updated_at":"2026-07-12T06:40:40.860Z"}
{"cache_key":"b294d8a6cd0afc841fb5636eb366187660463b198d0be303a4b1ba7df1a55cf3","model":"gpt-5","provider":"openai","segment_id":"codexSessions.host.gateway","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Gateway","text_hash":"41ed52921661c7f0d68d92511589cc9d7aaeab2b5db49fb27f0be336cbfdb7df","tgt_lang":"hi","translated":"Gateway","updated_at":"2026-07-09T10:01:43.755Z"}
{"cache_key":"b29b518c768eec10585d6355f36a7d604ccc85f66267a125755b5e1b25dd2a11","model":"gpt-5","provider":"openai","segment_id":"claudeSessions.host.gateway","source_path":"ui/src/i18n/locales/hi.ts","src_lang":"en","text":"Gateway","text_hash":"41ed52921661c7f0d68d92511589cc9d7aaeab2b5db49fb27f0be336cbfdb7df","tgt_lang":"hi","translated":"Gateway","updated_at":"2026-07-09T10:01:43.755Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:52.879Z",
"generatedAt": "2026-07-14T15:37:46.057Z",
"locale": "id",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -410,6 +410,7 @@
{"cache_key":"3ab0d9168f9ac736467618b707669bc71a24ccf251c98693bc81f7fdb39773b7","model":"gpt-5.5","provider":"openai","segment_id":"worktrees.restorable","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Restorable","text_hash":"bc97d2ddd2dba3ab2391f21314316556111065c4b870bc05679fadd60a754c01","tgt_lang":"id","translated":"Dapat dipulihkan","updated_at":"2026-07-05T21:01:23.086Z"}
{"cache_key":"3ae4d820a23d0c77bddfceac0a45673b8fee0fc4300e65b81f9c88cf9e020b47","model":"gpt-5.6-sol","provider":"openai","segment_id":"nodes.pairing.transportLimitedTitle","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Limited for network safety","text_hash":"ada889416d378c6da2028f6faa23e2f365c26311940988adb9662079994f35c6","tgt_lang":"id","translated":"Dibatasi demi keamanan jaringan","updated_at":"2026-07-13T10:03:00.962Z"}
{"cache_key":"3b98e88dcb3c0b4707b8f3d1781e028f3e57722a05d9e8bcb16da5aef30ecd5d","model":"claude-opus-4-8","provider":"anthropic","segment_id":"cron.form.failureAlertAccountId","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Alert account ID","text_hash":"a3bb290b5e682539f86e4c0459011c8e6c7ac6fa69939422a524b4ce95e02214","tgt_lang":"id","translated":"ID akun peringatan","updated_at":"2026-07-12T06:49:42.387Z"}
{"cache_key":"3bec5ecd4568aff4bedba3500e43c93ebd5e6163d02ed2980565a88dbc7d6516","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"id","translated":"Letakkan file untuk menambahkannya","updated_at":"2026-07-14T10:36:45.102Z"}
{"cache_key":"3c28f09c821f5f86dc1d11efa4bdcc9525dc756524f3cbc6ebe5633a2f7e2649","model":"gpt-5.6-sol","provider":"openai","segment_id":"filePreview.navigate","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"navigate","text_hash":"d0cda6559bb347db706f6fa92a5b2491658e0c1e5bda98bb14e3c8a711b8fa33","tgt_lang":"id","translated":"navigasi","updated_at":"2026-07-12T00:09:56.794Z"}
{"cache_key":"3c4f0a9df77a544a9783ab44f918eec393e11457ed1876ac87d36ff7a4b02391","model":"gpt-5.5","provider":"openai","segment_id":"chat.sessionDiff.loading","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Loading changes…","text_hash":"99f48f20532c48dcd9f2bfcd0f4d4ba230fb0396b320e67bdfa2f3383901fd1a","tgt_lang":"id","translated":"Memuat perubahan…","updated_at":"2026-07-11T04:53:24.485Z"}
{"cache_key":"3c5e5f12e693a6bec8942647373a2f89c6377925e17d80ae0241388d0089d062","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.detailAutomationTenant","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Tenant: {tenant}","text_hash":"e896dc96a6847d7aaa593069e890e7a712fd60d7be60280ee24e1942e10411b0","tgt_lang":"id","translated":"Tenant: {tenant}","updated_at":"2026-06-16T14:16:44.079Z"}
@ -943,6 +944,7 @@
{"cache_key":"874e4d4efe4e2c56709626897fe86b21277e67a5632ccb0e433cde51c6232fc4","model":"claude-opus-4-8","provider":"anthropic","segment_id":"nodes.execApprovals.allowlistHint","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Case-insensitive glob patterns.","text_hash":"db5c89db24461b936404c53fe2f7ddc83315691aec34f90bdafdf14d290c0601","tgt_lang":"id","translated":"Pola glob tidak peka huruf besar/kecil.","updated_at":"2026-07-12T06:45:23.023Z"}
{"cache_key":"874ef1acf69c677f1bb3e542246b679c889c33fa136b5be449b19e9de6ee1f5e","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.secretCount","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"{count} secret","text_hash":"0e6d25bb2eb2d8b98f478224b4330f249de6465d2c06a012c51575b3dd56cb6b","tgt_lang":"id","translated":"{count} rahasia","updated_at":"2026-07-12T06:47:03.441Z"}
{"cache_key":"877c58e89108104fb6f3bcfc687aafa696032ad8ed6d7644dbbbdaa2f9af1391","model":"gpt-5.5","provider":"openai","segment_id":"browser.hide","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Hide browser panel","text_hash":"9addb46dd1c2c965fc79703cb42b245c24a1745ff662cf67c255ad840e576b72","tgt_lang":"id","translated":"Sembunyikan panel browser","updated_at":"2026-07-11T02:19:24.198Z"}
{"cache_key":"8789e246bc90fd01e40fe9cae84b6a609c7e623630f7b908d4a0e52cd8ea181a","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"id","translated":"Mengunggah file…","updated_at":"2026-07-14T10:36:45.102Z"}
{"cache_key":"878f87dabaf9343ff41d5d431fcc14814bc83b418a776a0798aac69aef7142a4","model":"gpt-5.5","provider":"openai","segment_id":"nodes.pairing.generating","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Creating a secure setup code…","text_hash":"eca7942aeec595e3a1ebf01564b7dfc4ad90868636da4337f0470dcf1d97bc52","tgt_lang":"id","translated":"Membuat kode penyiapan yang aman…","updated_at":"2026-07-04T16:48:34.014Z"}
{"cache_key":"8855d7f6ab333f84ca2a0f00fd0656abfa64c217657ba73ab90a4bab91438905","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentTools.availableNowSubtitle","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"What this agent can use in the current chat session.","text_hash":"3972b644e6c3212107fc9c119c2897c2c786ca08ee620880f321f92496a5e7d2","tgt_lang":"id","translated":"Apa yang dapat digunakan agen ini dalam sesi obrolan saat ini.","updated_at":"2026-07-12T06:47:18.623Z"}
{"cache_key":"885cda26181cd31f6c7e6f87bb677c4edb816c80a19bd9ad2115a5a83eb31fbd","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.relative.hoursAgo","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"{count}h ago","text_hash":"520c737ea62430c4aa3e953abb60cf6bf7ecde97f0aef8f5e3fab5a9011db2a0","tgt_lang":"id","translated":"{count} jam lalu","updated_at":"2026-07-12T06:48:36.617Z"}
@ -1040,6 +1042,7 @@
{"cache_key":"93f4e2229d0512876512a2994f0ac1d48dfcf45d4e1e185eed3e19c337d3b85d","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillStatus.bundled","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"bundled","text_hash":"4c4164b5039c360603643de4507bf8a558e50513b01281aa5ecbe5c22be298c9","tgt_lang":"id","translated":"terpaket","updated_at":"2026-07-12T06:47:41.436Z"}
{"cache_key":"9446f27abdee059faf95779bbcfb40e953bf50e22083f685f7ef7695fa7d1739","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agents.overview.modelSelection","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Model Selection","text_hash":"beb7e8ee46abaab1e331b72c4f58088d77549445da67b03eaccec31e0a5b22c0","tgt_lang":"id","translated":"Pemilihan Model","updated_at":"2026-07-12T06:45:28.345Z"}
{"cache_key":"949a0e722ede1328898e9eab6f486a808489631fe03a6bf05afb786dac90c764","model":"claude-sonnet-4-6","provider":"anthropic","segment_id":"cron.suggestions.ideas.repoPulse.prompt","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Review overnight activity in my repositories: new issues, pull requests, and CI failures. Summarize the three things that most need my attention today, each with a link and a one-line reason.","text_hash":"147ee8f8d7e86cc46e6daf4b1d987ecd34e3582be6fa6146d199425c4dc060b8","tgt_lang":"id","translated":"Tinjau aktivitas semalam di repositori saya: isu baru, pull request, dan kegagalan CI. Rangkum tiga hal yang paling membutuhkan perhatian saya hari ini, masing-masing dengan tautan dan alasan satu baris.","updated_at":"2026-07-11T22:47:43.038Z"}
{"cache_key":"94db56c407aa3096a7f4a006b74a208c6d73361170a405e86ca133241a3a1b49","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"id","translated":"Tambahkan file ke terminal","updated_at":"2026-07-14T10:36:45.102Z"}
{"cache_key":"94f289f7abcde1dff0cad2911ec05cdca125562fa557cfed85fedd3db2a33bb1","model":"gpt-5","provider":"openai","segment_id":"claudeSessions.refresh","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Refresh","text_hash":"0e91610117029a62a478b7fa7df0b8598bebe3ab1e192d4b1882e310719c9671","tgt_lang":"id","translated":"Muat ulang","updated_at":"2026-07-09T10:01:43.737Z"}
{"cache_key":"950b6f1c7fb06d01d82675befc910ec36fd134d1cae180b949079bb0246815ce","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillsPage.skillCardNotLoaded","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Skill Card not loaded.","text_hash":"31c1bbe69949671bf11cea9fd168518f3b219d1f1b5eebdeff575048f3ebfbea","tgt_lang":"id","translated":"Skill Card tidak dimuat.","updated_at":"2026-07-12T06:47:41.436Z"}
{"cache_key":"953eed65c64158ccff955f49666b2273efb8751c998e6ec6a08aa21432b8fe3f","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.detailAutomationBoard","source_path":"ui/src/i18n/locales/id.ts","src_lang":"en","text":"Board: {board}","text_hash":"96d7493589e40e17803b3bf643dff1b891a4ebf57f5d2b36af0a7ddd09e64b84","tgt_lang":"id","translated":"Board: {board}","updated_at":"2026-06-16T14:16:44.079Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:52.167Z",
"generatedAt": "2026-07-14T15:37:45.670Z",
"locale": "it",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -38,6 +38,7 @@
{"cache_key":"04ffebf265ed2c2f33aeb8c7ee5552a7311b922e6e88f95a39a47510aeac37be","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.dependenciesReady","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"{count} ready","text_hash":"f5f5fd424d7c18f19a51ee147857efddc320a0ec6e1eeb4354be129425632f05","tgt_lang":"it","translated":"{count} pronte","updated_at":"2026-06-16T14:15:46.111Z"}
{"cache_key":"0501c4f9e479b9a5c6227d812e1bab1fb355fbbb0c76751f21dac3ad6840cb98","model":"claude-opus-4-8","provider":"anthropic","segment_id":"channels.nostr.placeholders.lightningAddress","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"you@getalby.com","text_hash":"7c433ad5c3a532bd4ab1a634c4ac4d75cbd857e41b1de75b50ac8c8b16ccf319","tgt_lang":"it","translated":"you@getalby.com","updated_at":"2026-07-12T06:37:51.163Z"}
{"cache_key":"052c1f6ff7ccb0efb85fb69eebafacb094ce587041c6a3088ca727f5ba1b541a","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.noSettingsInSection","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"No settings in this section","text_hash":"e5fe71779954d756282be0995ce95183bb9ff370d67c6b63b9f8335f51c7ab9a","tgt_lang":"it","translated":"Nessuna impostazione in questa sezione","updated_at":"2026-07-12T06:38:56.155Z"}
{"cache_key":"056a378fc21ad8da22250d14a5c6b4e73082b00ba83aa6e23e9616fccece0de3","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"it","translated":"Caricamento dei file…","updated_at":"2026-07-14T10:36:38.544Z"}
{"cache_key":"058caf10de87397f8f9d5cfe4f5718b56a00bcfa57f19ef9089a00db6a49390a","model":"claude-opus-4-8","provider":"anthropic","segment_id":"cron.actions.runIfDue","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Run if due","text_hash":"1d9f1ae334e7591bf242d30542768eb1d4f91d01836b69642cfcea2eebd24663","tgt_lang":"it","translated":"Esegui se in scadenza","updated_at":"2026-07-12T06:42:36.545Z"}
{"cache_key":"05a4be73360e62ce17ea5c586afd0be2802f7ae24cf064dbdc00929804539811","model":"gpt-5","provider":"openai","segment_id":"codexSessions.loadMore","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Load more","text_hash":"ac8991ef01019cf55a2426194a05959e0cb886333f1a332ff4f442320d165400","tgt_lang":"it","translated":"Carica altro","updated_at":"2026-07-09T10:01:43.724Z"}
{"cache_key":"05b034f6d74632afa65521076e7ad1aac7da96cf0b72e6a1abe1f1a5d7c8c98a","model":"claude-opus-4-8","provider":"anthropic","segment_id":"cron.actions.clone","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Clone","text_hash":"5779f32fab00c2aae390fe9f63877444b90eb7c12cca5e8903f7c02d2759f9db","tgt_lang":"it","translated":"Clona","updated_at":"2026-07-12T06:42:36.545Z"}
@ -1170,6 +1171,7 @@
{"cache_key":"a675fcc83e5ce976dadb8c993e2382e2dafc3b78758a4cae2aec1794325e9bd1","model":"gpt-5.5","provider":"openai","segment_id":"chat.sessionDiff.unmodifiedLines","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"{count} unmodified lines","text_hash":"34185cef239bc25347ee50aa60f7932c291708fc5aa68846a0d54414bf828e1a","tgt_lang":"it","translated":"{count} righe non modificate","updated_at":"2026-07-11T04:53:14.035Z"}
{"cache_key":"a6b132f3dda9bc84079c956cfa3a248b8f3a12b76adba9a8494c8761e3221dfd","model":"gpt-5","provider":"openai","segment_id":"codexSessions.status.active","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Active","text_hash":"92340695899bd2d86223e4a007620e0d6502fc0e08809773634c7e0743764a9c","tgt_lang":"it","translated":"Attiva","updated_at":"2026-07-09T10:01:43.724Z"}
{"cache_key":"a6d752221eb272ad179891069ee4c0d9de98003e78127b383489fdcd36cc9233","model":"gpt-5.6-sol","provider":"openai","segment_id":"newSession.nodeOffline","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Device is offline","text_hash":"3571104eb98b4de871b743f3f2993d1aea3f6bf9636730c858201c902464fa44","tgt_lang":"it","translated":"Il dispositivo è offline","updated_at":"2026-07-12T18:40:15.522Z"}
{"cache_key":"a7155fa1ead30fbc27134e5438c488eca4eececea7e391626d81cf43c586ab53","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"it","translated":"Trascina qui i file per aggiungerli","updated_at":"2026-07-14T10:36:38.544Z"}
{"cache_key":"a73b5fdb3e8b929ea5cc4d1a678270520494ca21cb6126858259fcebe63416f5","model":"gpt-5.5","provider":"openai","segment_id":"connection.offlineHint","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Live updates and actions are paused until the connection returns.","text_hash":"7a60105cdafb6aa95b9081a370308a9ccd495199c9bfb90d3e0f70af68680f26","tgt_lang":"it","translated":"Gli aggiornamenti in tempo reale e le azioni sono in pausa finché la connessione non viene ripristinata.","updated_at":"2026-07-05T21:55:37.627Z"}
{"cache_key":"a7867c34eead891c1d984f16d8299d358c344adc34d538d54a67c6e20b646617","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentTools.noAvailable","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"No tools are available for this session right now.","text_hash":"c4740f01669d25875b42714e4539159decb0ab13921921433c40bb22618bb171","tgt_lang":"it","translated":"Nessuno strumento è disponibile per questa sessione al momento.","updated_at":"2026-07-12T06:40:25.148Z"}
{"cache_key":"a7ee2d7220a7951caa96298cf728c699d849beeda4ec3498c2f19b3e74388538","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentTools.enabledByProfile","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Enabled by the current profile.","text_hash":"e71ef6fd7aa42db4fc46c718cf658538f54c7d8ea665911bb4eb492f1710107a","tgt_lang":"it","translated":"Abilitato dal profilo corrente.","updated_at":"2026-07-12T06:40:12.582Z"}
@ -1649,6 +1651,7 @@
{"cache_key":"ea860e44a07fc7609db9bdc08a5892b163dfba0d9275acad9b704d48605a2677","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.compaction.label","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Compacted history","text_hash":"1c066091aa0c37ad253bfe195469b0cf82b276a06dea4ccc55e246e175b2e68d","tgt_lang":"it","translated":"Cronologia compattata","updated_at":"2026-07-12T06:42:07.065Z"}
{"cache_key":"ea8829feb8cc873b612c13a08e24ed151e90eb88b46350fa9dfbda518cdf6475","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.cli.description","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"CLI banner and startup behavior","text_hash":"5b70d7277424ed3bebe6fc32c1fff1249303801cc0fea5f7d95d226eb073c86d","tgt_lang":"it","translated":"Banner della CLI e comportamento all'avvio","updated_at":"2026-07-12T06:39:08.874Z"}
{"cache_key":"ea97241abad4a20a058f870cb347aac1bbeb3d3e0f08e4ada96441b78e6430e0","model":"gpt-5","provider":"openai","segment_id":"codexSessions.scope.active","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Active","text_hash":"92340695899bd2d86223e4a007620e0d6502fc0e08809773634c7e0743764a9c","tgt_lang":"it","translated":"Attive","updated_at":"2026-07-09T10:01:43.724Z"}
{"cache_key":"ea99bd9f8e42562974b542dfc115e8b63a5b1256026ec94362abc07817d97253","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"it","translated":"Aggiungi file al terminale","updated_at":"2026-07-14T10:36:38.544Z"}
{"cache_key":"eaf02e5b4ba84a2d6cdda27d28e772c930240ad03bae57f187cc7ee06279bf29","model":"gpt-5.5","provider":"openai","segment_id":"sessionsView.archiveSession","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Archive session","text_hash":"740ded37480365eae8bf833ccaaa58350fc9434a77b7bb65b5516eba476fbec3","tgt_lang":"it","translated":"Archivia sessione","updated_at":"2026-07-02T14:30:25.278Z"}
{"cache_key":"eb07ef0c5445f8b34649fe536b041cd353bdf6286950a44dd776e96e4ba4aa7f","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.categories.appearance","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Appearance","text_hash":"3907fa7f80722a6fc58cd8c1bd30abf7638095d6774f183b6e831b7093957d1b","tgt_lang":"it","translated":"Aspetto","updated_at":"2026-07-12T06:39:38.924Z"}
{"cache_key":"eb112f2fb78f6155f999d66a2fcfa5cc24e2712f046420874e6b11f1ed7672cf","model":"gpt-5.6-sol","provider":"openai","segment_id":"configView.connection.title","source_path":"ui/src/i18n/locales/it.ts","src_lang":"en","text":"Connection","text_hash":"639a40e82b9a96f0cbeed5f006cf5634c8d1b990b3c83753c00a910fc268d2a6","tgt_lang":"it","translated":"Connessione","updated_at":"2026-07-12T00:09:21.741Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:51.009Z",
"generatedAt": "2026-07-14T15:37:45.065Z",
"locale": "ja-JP",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -855,6 +855,7 @@
{"cache_key":"79303c10665a224b7688e262115087be9734ba775de740a60c8b3a52565c3e0b","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentTools.plugin","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Plugin: {id}","text_hash":"26edf462e12944443c124758e11997967fd73c62e30fb651ab30449e19597772","tgt_lang":"ja-JP","translated":"プラグイン: {id}","updated_at":"2026-07-12T06:33:58.934Z"}
{"cache_key":"793bb50795bd8366577739ad92107e8a2e894436f03d36296cafa7933cc39850","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.detail.clickToPreview","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"· click to preview","text_hash":"e7122b28694c3a1928054e15e27f203aaae8d00f9c34ae04dedad01d8b652fb2","tgt_lang":"ja-JP","translated":"· クリックしてプレビュー","updated_at":"2026-07-12T06:35:04.039Z"}
{"cache_key":"794abb76a8879754e0dc4980cd50bcdeef6f178bd30e78c1a43a4fed8c132804","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.messages.label","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Messages","text_hash":"04d7b48339271ea67d3c8493e07e90bc68dc565485eebe5e0b67c21c1586e3c0","tgt_lang":"ja-JP","translated":"メッセージ","updated_at":"2026-07-12T06:32:33.064Z"}
{"cache_key":"79536c5f28e799753bf73abbda39970f7ec1b76d88f83a3807cc430da85c753c","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"ja-JP","translated":"ターミナルにファイルを追加","updated_at":"2026-07-14T10:36:23.505Z"}
{"cache_key":"79708e851179bf76dc6e64c65c886111b1b509ab6ae3f72bff30a4bae38e9414","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agents.toolCatalog.groups.nodes","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Nodes","text_hash":"7ac362063b9f204602f38f9f1ec9cf047f03e0d7b83896571c9df6d31ad41e9c","tgt_lang":"ja-JP","translated":"ノード","updated_at":"2026-07-12T06:32:10.310Z"}
{"cache_key":"79be8f9b2864e6959f580c1af744e4d400f1bd7cf4bcc031bf2bd7c7fc05a523","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.composer.runStatus","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Run status: {status}","text_hash":"f1a452538bcedff3f592a48e2ccc33b1f0fced879d45d2dac8454421c96a3836","tgt_lang":"ja-JP","translated":"実行ステータス: {status}","updated_at":"2026-07-12T06:36:09.755Z"}
{"cache_key":"79e248fda7a0aebfebf4fd0b09ae97a0c6078a2dc7b245e252c7bbb503f7c33b","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillsPage.noClawHubResults","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"No skills found on ClawHub.","text_hash":"a3b2387163dc439615c00ab811a92f533225c5c02a529b68074ef56fac75821f","tgt_lang":"ja-JP","translated":"ClawHub に Skills が見つかりません。","updated_at":"2026-07-12T06:34:22.550Z"}
@ -1013,6 +1014,7 @@
{"cache_key":"92376a71e9e9268ff8faea327b0ca1eecdddeea394aaadf7761cdeb4b905e7e8","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configPage.channels.telegram","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Telegram","text_hash":"acdd1e734125f341604c0efbabdcc4c4b0597e8f6235d66c2445edd1812838c1","tgt_lang":"ja-JP","translated":"Telegram","updated_at":"2026-07-12T06:33:16.238Z"}
{"cache_key":"923c2e6dd041be17f61a8c90d5b2dad6f58cf05eb8c437efcdfbec1c2a55b923","model":"gpt-5.5","provider":"openai","segment_id":"claudeSessions.summaryLabel","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Claude session summary","text_hash":"e9a8e980b4fdaf946d89158d257b45486ae816ffd162d317092d3bd0332f6021","tgt_lang":"ja-JP","translated":"Claude セッションの概要","updated_at":"2026-07-11T13:50:30.155Z"}
{"cache_key":"92547544815e91368dde8a575a0fe2bda8d052e3a689958294822d8487bc0a27","model":"claude-opus-4-8","provider":"anthropic","segment_id":"mcpPage.publishing","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Publishing...","text_hash":"5f51143bee08cfefae1db0c6391de01da33003ca422be3d96e1e1e658da2ce7b","tgt_lang":"ja-JP","translated":"公開中...","updated_at":"2026-07-12T06:34:37.704Z"}
{"cache_key":"92bb1ccba7d583c514edec0662779af841d3bd474160c8091d6b9ae75d1776e9","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"ja-JP","translated":"ファイルをドロップして追加","updated_at":"2026-07-14T10:36:23.505Z"}
{"cache_key":"9308d3bb778b4f138e86945efe3383dff27da2815893424d7344c1e56033b09d","model":"claude-opus-4-8","provider":"anthropic","segment_id":"sessionsView.user","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"User","text_hash":"b512d97e7cbf97c273e4db073bbb547aa65a84589227f8f3d9e4a72b9372a24d","tgt_lang":"ja-JP","translated":"ユーザー","updated_at":"2026-07-12T06:33:04.097Z"}
{"cache_key":"930b4261874ff647adada2f16f8b5a96fd7a8b59abce94264c2f32865860e0dc","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.sections.wizard","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Setup Wizard","text_hash":"13d16249923201c79eafdacbbdfee6a1dbe87bf8345a30781c9aac334c406779","tgt_lang":"ja-JP","translated":"セットアップウィザード","updated_at":"2026-07-12T06:33:25.246Z"}
{"cache_key":"93309fb097ac6115ffa01bb8a34c155ed43cae5a9c78fc137d45bb1d1bd13c0a","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.header.useCurrentChatTooltip","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Send revision requests to the current chat session instead of the proposal's workshop session.","text_hash":"9db782d40e88750d4faed33c8a73c24552070f101483881c60af8cf446c674a6","tgt_lang":"ja-JP","translated":"修正リクエストを提案のワークショップセッションではなく現在のチャットセッションに送信します。","updated_at":"2026-06-16T14:14:04.101Z"}
@ -1569,6 +1571,7 @@
{"cache_key":"e978f6f548a7aa5c9fe926d7da44db0dd518d14c53986572321382df32d1372f","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillsPage.clawHub","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"ClawHub","text_hash":"a2019fe71279ebb59b7876298299699524a6eb7885a04484409a1b556c8548f3","tgt_lang":"ja-JP","translated":"ClawHub","updated_at":"2026-07-12T06:34:17.485Z"}
{"cache_key":"e9b63ab120af0c7dc6a29087ae5f87b2db144144f51c960fc134dfa23786ab2b","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.discovery.description","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Service discovery and networking","text_hash":"3d379911481327582b93519e4c7d1e1a9f97015c9b579f2753c71e7db96d22d0","tgt_lang":"ja-JP","translated":"サービスディスカバリーとネットワーク","updated_at":"2026-07-12T06:32:47.571Z"}
{"cache_key":"e9bf668e20b33a58666e7830aad6b06f64e8e005c22006b52cf0c3496889fd96","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.notifications.available","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Available","text_hash":"e674447337e83c1346f6122ed69f35bf5526e2a11842b2f2b788f3fb67d714ca","tgt_lang":"ja-JP","translated":"利用可能","updated_at":"2026-07-12T06:33:30.333Z"}
{"cache_key":"e9dd8fc1c0e85e83f9f7177bf01b2a2f6e4e98cb1a52c94f2e52d32f29ccbc47","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"ja-JP","translated":"ファイルをアップロード中…","updated_at":"2026-07-14T10:36:23.505Z"}
{"cache_key":"ea4846bf9189ec34668040b3f9577f3386f7ed79fdec9ec0c4577dac4ac04b00","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.rawTitle","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Edit raw JSON/JSON5 config","text_hash":"d6ecf3de8d568e401bc5e1adeb0b9e2fb2c0a12b3d222c01616a69604616b03d","tgt_lang":"ja-JP","translated":"Raw JSON/JSON5 設定を編集","updated_at":"2026-07-12T06:33:44.131Z"}
{"cache_key":"ead52f7124448c610a5870356eaa925d271a2a806ca4c287743c49b32a6aa4e8","model":"gpt-5","provider":"openai","segment_id":"claudeSessions.host.offline","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Offline","text_hash":"a1794783aab72d205dc532b1170d1be63ebdce8816b57c21acb451c15dab969a","tgt_lang":"ja-JP","translated":"オフライン","updated_at":"2026-07-09T10:01:43.715Z"}
{"cache_key":"eb472182ec7521d199f725fd4e9c83a9ef7eb91bb34f851cc046c05a225969ab","model":"claude-opus-4-8","provider":"anthropic","segment_id":"dreaming.wiki.pageDetails","source_path":"ui/src/i18n/locales/ja-JP.ts","src_lang":"en","text":"Page details","text_hash":"86bbe3b1127c4076f48948f6a5a526db2d32efdef1f116d951b8f790dbb811b9","tgt_lang":"ja-JP","translated":"ページの詳細","updated_at":"2026-07-12T06:35:46.041Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:51.234Z",
"generatedAt": "2026-07-14T15:37:45.187Z",
"locale": "ko",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -807,6 +807,7 @@
{"cache_key":"73e51d1573f30c8af6f9ac3d17872e26ec704d0845f1ce8b5084396b02560033","model":"claude-opus-4-8","provider":"anthropic","segment_id":"githubPreview.ariaLabel","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"{state} {kind} {repo} #{number}: {title}, by {author}","text_hash":"e18c624550814e4318a45e1e0f8782913409763d046aa703519e91c887be205b","tgt_lang":"ko","translated":"{state} {kind} {repo} #{number}: {title}, 작성자 {author}","updated_at":"2026-07-12T06:31:35.667Z"}
{"cache_key":"73fbfc3876cadb2ea1d5cd77ecbc20e7caa42ff8c1864121745e504dc7945775","model":"claude-opus-4-8","provider":"anthropic","segment_id":"pluginsPage.connectorDescriptions.canva","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Create and edit Canva designs, manage assets, and export results.","text_hash":"477116e721204b2cb119ec9421cc7880b7000563dcefce02bfd12d1825918a47","tgt_lang":"ko","translated":"Canva 디자인을 생성 및 편집하고, 에셋을 관리하고, 결과를 내보냅니다.","updated_at":"2026-07-12T06:35:04.296Z"}
{"cache_key":"74ba211d53d60564b9cdab522a834fe0aefba831d2303504e2fcbacdbcc65503","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.goals.edit","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Edit goal","text_hash":"8828def9d7005363cea56a57771854964560a91522cc23932bdb6074b52ac307","tgt_lang":"ko","translated":"목표 편집","updated_at":"2026-07-12T06:36:13.954Z"}
{"cache_key":"74c1cf8da6a1b07f30cf66b2c8abcfcdd6e7ee7fc40a455c8c2528b1071b0d2a","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"ko","translated":"파일을 추가하려면 여기에 놓으세요","updated_at":"2026-07-14T10:36:26.151Z"}
{"cache_key":"74d20e356e010b978276f251e579c009443a689c2e385a5d439181cb57b33779","model":"gpt-5.6-sol","provider":"openai","segment_id":"attention.modelAuthExpired","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Model auth expired: {providers}","text_hash":"1af839b53686632bd3d0b5e0b89025a75052d0b7cfa84ce5e1654d4cd2469c61","tgt_lang":"ko","translated":"모델 인증 만료됨: {providers}","updated_at":"2026-07-12T00:08:48.860Z"}
{"cache_key":"74fff86b4db9ba6d8856679d8628c381f096ea4b65f0debad0f98dd648b5093e","model":"claude-opus-4-8","provider":"anthropic","segment_id":"worktrees.ownerSession","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Session","text_hash":"6959b4159575d8dd76d9f3bbe2c6437904f861e7860c35abd18deffb1c3425a0","tgt_lang":"ko","translated":"세션","updated_at":"2026-06-16T14:14:34.760Z"}
{"cache_key":"751b949daa67daf6ac2b57b56c5ccb6c82009eb9d4679f05040fbd66c9670115","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillsPage.by","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"By","text_hash":"125466b821c6448a68d22c6ddbdbbc921f6b174a620f0fcbc3d219afd7d22b47","tgt_lang":"ko","translated":"제작자","updated_at":"2026-07-12T06:34:39.346Z"}
@ -1190,6 +1191,7 @@
{"cache_key":"ab318cfb91fd4c14318b6ebf1d29b6500a59d22ccc594e002f498cdd3be552b4","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.workspaceFiles.browserCount","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"{count} shown","text_hash":"e57b4adfe868fd74a183650103d820176d4960bd0bdb677d9985db09f9752867","tgt_lang":"ko","translated":"{count}개 표시됨","updated_at":"2026-06-16T14:14:34.761Z"}
{"cache_key":"ab3becff74ee2eb4b027450f7956e8db882e3157519a5b089b513c4a67434602","model":"gpt-5.5","provider":"openai","segment_id":"worktrees.newWorktree","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"New worktree","text_hash":"4f210afedcabde192cf04e3c8c1ff21f79149bc696d1b8abaece56e8e3faa4dd","tgt_lang":"ko","translated":"새 worktree","updated_at":"2026-07-10T17:59:02.700Z"}
{"cache_key":"ab5faec281b31699b625b0b389f0a017b2f6b8bae0d76ca84eeb2bcef446c6a3","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.commands.fill","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"fill","text_hash":"dcd32479a72e55b29a03a586d8a483a05be0ce87cc5c25c7bad23079fc0356b3","tgt_lang":"ko","translated":"채우기","updated_at":"2026-07-12T06:36:13.954Z"}
{"cache_key":"abb1cd63f904250895ccbd1baaa6893e5ee588a6ccff740b9f5bf2426f97fe43","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"ko","translated":"파일을 업로드하는 중…","updated_at":"2026-07-14T10:36:26.151Z"}
{"cache_key":"ac121a4495218e30180ef339886397d2bc69f965222b318979abccf53ae81874","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.autoRefresh30s","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"30s","text_hash":"d3382a4f0e03f8b14cf99424376886c236f1503d4b332137667484fc96d58fc4","tgt_lang":"ko","translated":"30초","updated_at":"2026-06-17T14:14:20.553Z"}
{"cache_key":"acaaa75beca381f1920643146c0d483fd1497337dd60f263af0719610e71ceef","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.revision.description","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Tell the agent what should change. The proposal stays pending and the workshop will create a revised version.","text_hash":"c9eb5236c5b73f0eec0f11927862295a2259dff5b052b04f0b01d846b0c97b22","tgt_lang":"ko","translated":"무엇을 변경할지 에이전트에게 알려주세요. 제안은 대기 상태로 유지되며 워크숍이 수정된 버전을 만듭니다.","updated_at":"2026-07-12T06:35:19.851Z"}
{"cache_key":"acc02946785027f34abca6d39a412d371bd75edb5b1b252c2e5a26dd9c76d2dc","model":"gpt-5","provider":"openai","segment_id":"codexSessions.empty.search","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"No sessions on this host match your search.","text_hash":"53e8e235da1a4490f8514580987af37d3693f5232882f414ce75de09cd4203f9","tgt_lang":"ko","translated":"이 호스트에 검색어와 일치하는 세션이 없습니다.","updated_at":"2026-07-09T10:01:43.732Z"}
@ -1354,6 +1356,7 @@
{"cache_key":"c468f0a9df3f45b03ce8858f5c135835af7e18e0182d4ea0e0601d4e94f2dde8","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agents.toolCatalog.descriptions.read","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Read file contents","text_hash":"4b24d940f5836c690daf7c56f5735e35962fdf3de849ad858b3fad72e5468a8b","tgt_lang":"ko","translated":"파일 내용 읽기","updated_at":"2026-07-12T06:32:31.554Z"}
{"cache_key":"c4aa03b43d324f829c9cea82c3296e21c9b65f7388dba7979b5dd57318a5f957","model":"gpt-5.5","provider":"openai","segment_id":"sessionsView.goal","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Goal","text_hash":"cdbf6975e8a35b0d03558be6822dfae166482c24fb86b0433f60e8167f5c91e4","tgt_lang":"ko","translated":"목표","updated_at":"2026-05-29T21:00:36.520Z"}
{"cache_key":"c4b61e566871edd79890c3e0264838e4c4d47b874bfb6f0e9526c23368994ded","model":"gpt-5.6-sol","provider":"openai","segment_id":"agentChip.help","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Help","text_hash":"b79cac926e0b2e347e72cc91d5174037c9e17ae7733fd7bdb570f71b10cd7bfc","tgt_lang":"ko","translated":"도움말","updated_at":"2026-07-13T11:29:56.930Z"}
{"cache_key":"c4f7f829c5bff2ddbcb9bfb8a91fc6fa1c3e455e45e6b9fd37c6f92db84c8b42","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"ko","translated":"터미널에 파일 추가","updated_at":"2026-07-14T10:36:26.151Z"}
{"cache_key":"c50f87c2bb2ad52173a1996b852ddd6a5024b90ebe0c4fa375023467c56c7551","model":"gpt-5.5","provider":"openai","segment_id":"chat.pullRequests.checksPassed","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Passed","text_hash":"436fe71bb9561f0596161c4d50c7b23327b4189acaf63dc89f4f9205b67a7528","tgt_lang":"ko","translated":"통과","updated_at":"2026-07-10T23:12:31.895Z"}
{"cache_key":"c546578f352ed895b343b2f708c822b0e36c93024df8590a8cd0bea0bd758309","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.pullRequests.checksRunning","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Running","text_hash":"f4ccae29e1bb0c20a124570a1b43f4347ea94bba9f84ffdfddd9c7445b126128","tgt_lang":"ko","translated":"실행 중","updated_at":"2026-06-17T14:14:15.283Z"}
{"cache_key":"c547ba4c6cb476a60cdb532b8c7050c72edb478d8d51e9d3d8773a97c00ba05d","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.audio.description","source_path":"ui/src/i18n/locales/ko.ts","src_lang":"en","text":"Audio input/output settings","text_hash":"d70fcb3aaa161944288b14569860811bd38ba7c1753d31cbbcf62b18b9034e45","tgt_lang":"ko","translated":"오디오 입력/출력 설정","updated_at":"2026-07-12T06:33:05.231Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:53.811Z",
"generatedAt": "2026-07-14T15:37:46.517Z",
"locale": "nl",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -49,6 +49,7 @@
{"cache_key":"059c9466f8b3144e8854d9e9bb30f7484e07ee4018caf17d5b9ab65ff738b02f","model":"claude-opus-4-8","provider":"anthropic","segment_id":"quickSettings.appearance.themes.claw","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Claw","text_hash":"587cfbbbcd42a71ba7f33f8051d5c354707fa1ff227cab11452c3ba2147a8682","tgt_lang":"nl","translated":"Claw","updated_at":"2026-07-12T06:53:28.373Z"}
{"cache_key":"0601340e68eeb527878c83d12ec8963d9a2e0e3bfb72268cbc8a76918ce557aa","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillsPage.source","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Source:","text_hash":"c707ee4ecc24044266322a90cf1a23752824f57a628facc169ddbe215ada4adb","tgt_lang":"nl","translated":"Bron:","updated_at":"2026-07-12T06:54:50.731Z"}
{"cache_key":"063813358c99f0a3cf73b7e0278c11afe0244864ea84a5b6d114d0dcef95c8f3","model":"gpt-5","provider":"openai","segment_id":"configView.sections.gateway","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Gateway","text_hash":"41ed52921661c7f0d68d92511589cc9d7aaeab2b5db49fb27f0be336cbfdb7df","tgt_lang":"nl","translated":"Gateway","updated_at":"2026-07-09T10:01:43.729Z"}
{"cache_key":"064bcf4b2ba31d7bcccdb9e7ce3395ec8a6fd95a97d42317443a4990a4704d52","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"nl","translated":"Bestanden uploaden…","updated_at":"2026-07-14T10:36:55.667Z"}
{"cache_key":"06696ef7eb525d3adda4323083d030b433a2b8eff13c04cf53c130daf12d946c","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.workspaceFiles.loading","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Loading session workspace…","text_hash":"bc6b2400fad20ee1d95d8de4ec6eef9ff1818ab080f86513384029519eaf4f4e","tgt_lang":"nl","translated":"Sessiewerkruimte laden…","updated_at":"2026-06-16T14:18:17.492Z"}
{"cache_key":"0678546ffe9c900316827219594b7657d7c1409a98bbe3126018d58b12db23e5","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.canvasHost.description","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Canvas rendering and display","text_hash":"b1bf5986d125dac92fb30e91c5f83e3b97d18b54ff5a628a5eef267efe9ebcba","tgt_lang":"nl","translated":"Canvas-rendering en -weergave","updated_at":"2026-07-12T06:53:16.528Z"}
{"cache_key":"0683f6f95ba1e2f67c47e619b0e1da8f14ff4abd53c918b056547de6028229b5","model":"gpt-5.6-sol","provider":"openai","segment_id":"channels.hub.runSetup","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Run setup","text_hash":"5066259b6cb888a7d2d0d6f4c94fb37634eeaf62672836e121b68698bc59eace","tgt_lang":"nl","translated":"Configuratie starten","updated_at":"2026-07-13T16:53:20.143Z"}
@ -248,6 +249,7 @@
{"cache_key":"217084377d6b57938caec6284d495b0a20b5eeb770a3deddf714a2b24280da55","model":"gpt-5.6-sol","provider":"openai","segment_id":"agentScope.label","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Agent scope","text_hash":"0833bc070d2c153692bc25fcc0b30f774cb415efdbf95fe8cd132feab8053698","tgt_lang":"nl","translated":"Agentbereik","updated_at":"2026-07-13T11:01:32.795Z"}
{"cache_key":"21799c4b51ca2542331cf9e029cba0a96d1d0a8d06cc4198e3418d6e9d4ba82d","model":"claude-opus-4-8","provider":"anthropic","segment_id":"filePreview.fileCount","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"{count} files","text_hash":"63352fdc2cd6bbbfb4ac957d4fb6e0b03eda6d5240381ec7a0f3a9b8db3a231f","tgt_lang":"nl","translated":"{count} bestanden","updated_at":"2026-07-12T06:51:48.927Z"}
{"cache_key":"217eed24dbc4ddb59c379558e2af804bbea8f54ff957e1d8e9aaa19275aa9aec","model":"gpt-5.5","provider":"openai","segment_id":"skillsPage.disabled","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Disabled","text_hash":"75081b593d15cf6e631971bc6768723f593b88b172477e40ae7d363e4829816d","tgt_lang":"nl","translated":"Uitgeschakeld","updated_at":"2026-07-10T02:29:02.639Z"}
{"cache_key":"2181c35282685a23e979ee3d9c73d4192ab6288c449ea6554351fd5b1c516da2","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"nl","translated":"Bestanden toevoegen aan terminal","updated_at":"2026-07-14T10:36:55.667Z"}
{"cache_key":"21e41809b89295271743ed1d2d8072b6be9c49fd04539022b68cf0a645fb6e59","model":"gpt-5.6-sol","provider":"openai","segment_id":"agentChip.noAgentMatches","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"No matching agents","text_hash":"38b006752ec7a0a6e18631050994899431708df2707bbc0792315deaf8e3a933","tgt_lang":"nl","translated":"Geen overeenkomende agents","updated_at":"2026-07-13T05:31:09.464Z"}
{"cache_key":"220327afea3a18167b0b4937ff708090cc3c6c8bd5e645a0a8b4a890ba2a2f70","model":"gpt-5.5","provider":"openai","segment_id":"pluginsPage.disabledRestart","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Disabled {name}. A Gateway restart is required to apply the change.","text_hash":"1ee58e882a46a89d43cc9118873fede5aa815a1f80b407b3d6ebe79576a56e37","tgt_lang":"nl","translated":"{name} uitgeschakeld. De Gateway moet opnieuw worden gestart om de wijziging toe te passen.","updated_at":"2026-07-10T02:29:07.297Z"}
{"cache_key":"2203de5776afaa62540974cefc2fda7c5349b39f19c57091a27a1e9bc6b8e3e1","model":"gpt-5.5","provider":"openai","segment_id":"pluginsPage.changesDisabled","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Browsing only. This gateway does not allow plugin changes.","text_hash":"82793ee1ebd503db74b8b599d8609e1c25986db3ab0eae0eea351c3d8d6e2488","tgt_lang":"nl","translated":"Alleen bekijken. Deze Gateway staat geen pluginwijzigingen toe.","updated_at":"2026-07-10T02:29:07.297Z"}
@ -1401,6 +1403,7 @@
{"cache_key":"b9c6243c46039f08a17a422477febba8e9e612b5ef7bc07a71bf94bd20a6d580","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agents.overview.inheritDefault","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Inherit default","text_hash":"8f4c85f7f3228202d2c3549496a9ae2a2427ed7101411fe97fb96ad9959c1d7d","tgt_lang":"nl","translated":"Standaard overnemen","updated_at":"2026-07-12T06:52:40.692Z"}
{"cache_key":"b9efd0417f8e8f4a173192647cee40c7cb339c08962a3c0d39b2d0f4467fe783","model":"claude-opus-4-8","provider":"anthropic","segment_id":"quickSettings.model.thinkingLevels.high","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"High","text_hash":"c4ebc6d4a5832cd9415f906ad03661110c705a72381c8b8b145761d02e2dd23a","tgt_lang":"nl","translated":"Hoog","updated_at":"2026-07-06T20:20:02.809Z"}
{"cache_key":"ba1b4d113785cde94d8f87f093e1df31ec2010418b046d9319e9129a0443b423","model":"gpt-5.5","provider":"openai","segment_id":"sessionsView.groupByNone","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"None","text_hash":"dc937b59892604f5a86ac96936cd7ff09e25f18ae6b758e8014a24c7fa039e91","tgt_lang":"nl","translated":"Geen","updated_at":"2026-07-05T14:40:20.847Z"}
{"cache_key":"ba28e8b6c6f6de4111e99e7694231177c4a6eab146d895c268c0bece32278667","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"nl","translated":"Sleep bestanden hierheen om ze toe te voegen","updated_at":"2026-07-14T10:36:55.667Z"}
{"cache_key":"ba5e978531e5280efb3bdfc6002cad6e85d027748167f89001128b280ee16127","model":"claude-opus-4-8","provider":"anthropic","segment_id":"nodes.execApprovals.addPattern","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Add pattern","text_hash":"d57e0aac9bfb822d6e9d05908d0f813fa353ba71e49f22d7d497f8f660679a6d","tgt_lang":"nl","translated":"Patroon toevoegen","updated_at":"2026-07-12T06:52:34.186Z"}
{"cache_key":"ba836a3f9d51203223da82f01c6e8b6ebc935ea23a5a9da2cea89a93b21a7878","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.queue.search","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Search proposals…","text_hash":"920a1bd7a15443b762e0d8f9f5aac701346342c3cd5ce3583b42a0e63e43ec0c","tgt_lang":"nl","translated":"Voorstellen zoeken…","updated_at":"2026-07-12T06:55:27.460Z"}
{"cache_key":"ba90dc8543c800376f75b5eca95a20154b9fad0f28a546dfc42e9bf1ab745777","model":"claude-opus-4-6","provider":"anthropic","segment_id":"chat.composer.realtimeTalkRequiresMicrophone","source_path":"ui/src/i18n/locales/nl.ts","src_lang":"en","text":"Realtime voice input requires browser microphone access.","text_hash":"a70d86265802e30aac70647cde33c62c5386741941d2ea9f54636a0242109dcd","tgt_lang":"nl","translated":"Realtime spraakinvoer vereist toegang tot de microfoon van de browser.","updated_at":"2026-07-06T22:42:32.827Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:53.093Z",
"generatedAt": "2026-07-14T15:37:46.171Z",
"locale": "pl",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -196,6 +196,7 @@
{"cache_key":"1a0efd24c6d9b6468d9882f49fb4387fb938cc63e6f21dacb2bacac417eb829a","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.diagnostics.label","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Diagnostics","text_hash":"268f14bbfe119c1e92150583af960a086d7db9619a097f8aa72ff6779842f610","tgt_lang":"pl","translated":"Diagnostyka","updated_at":"2026-06-16T14:17:07.423Z"}
{"cache_key":"1a2c7f329020e9357f6f3a780acc5242411eb50694e2d68d4384a075cb715666","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.wizard.description","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Setup wizard state and history","text_hash":"ea73e739c8e20733ee3654f4aa60202b41683b94ead2fe7dff4eba05271be544","tgt_lang":"pl","translated":"Stan i historia kreatora konfiguracji","updated_at":"2026-07-12T06:46:47.247Z"}
{"cache_key":"1a54eb7f4469f30a5f8a785787ae8f91a046361abebdc6e299ed11f187da2724","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.revealEnvValues","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Reveal env values","text_hash":"b9a0cce6bac408334c7f5e5a60058a51d099e5300514e7b449106385b7219f78","tgt_lang":"pl","translated":"Pokaż wartości env","updated_at":"2026-07-12T06:47:56.488Z"}
{"cache_key":"1a6c894d2ecca15f1c8315943a9b219e5e4e6f0dbc88b6eab8ff68f244967016","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"pl","translated":"Upuść pliki, aby je dodać","updated_at":"2026-07-14T10:36:47.635Z"}
{"cache_key":"1a6cc69fe1794633e23d335b64e50e511a54f1a4eab74a273aa5fb8fb9d864a0","model":"claude-opus-4-8","provider":"anthropic","segment_id":"pluginsPage.connectorDescriptions.maps","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Places, routing, and travel-time answers.","text_hash":"86d006fbc3fb69ebcbd1735bb635e9ddd5767f82cf7d19eae1ebd180fc1a0030","tgt_lang":"pl","translated":"Odpowiedzi dotyczące miejsc, tras i czasu podróży.","updated_at":"2026-07-12T06:49:08.686Z"}
{"cache_key":"1ae8841ecfe18ff7f01a4bc6b10c01e94a75823bedd06c76476039d0bd8cbb0b","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.agentFilterConfiguredDefault","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"{agent} (default)","text_hash":"7e996234f0fa55605720f9dc954a58411795bd882e948c87c739d43bd02137c3","tgt_lang":"pl","translated":"{agent} (domyślny)","updated_at":"2026-06-17T14:16:32.528Z"}
{"cache_key":"1afde4078e79e4bd9c95a3695c14ff7734b562c1925d75dbda3865e707409803","model":"gpt-5.5","provider":"openai","segment_id":"browser.annotatePrompt.elementDetail","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Marked element (page-reported): {descriptor} — {width}×{height}px at ({x}, {y}).","text_hash":"26f6a06bb620377485f379992db59e348653f7dd09db7ebbad9984c6da3c1d37","tgt_lang":"pl","translated":"Oznaczony element (zgłoszony przez stronę): {descriptor} — {width}×{height}px w ({x}, {y}).","updated_at":"2026-07-11T02:19:38.200Z"}
@ -479,6 +480,7 @@
{"cache_key":"43a0b0c2d116888e59eaf0ac1cd0ff5ad716ef36872c3c71aa180c41ae867b26","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.themes.dash.description","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Chocolate blueprint","text_hash":"b378cca81b5eac22e00e8ec4fd031bd441b818e92d4ed4a5edb65733e8d8becd","tgt_lang":"pl","translated":"Czekoladowy plan","updated_at":"2026-07-12T06:47:33.953Z"}
{"cache_key":"43a118abd4e13045a8a48cf10dcf163f41ac6bb8a66caf3f4cb6453c0d65d450","model":"gpt-5","provider":"openai","segment_id":"codexSessions.empty.subtitle","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Enable Codex session sharing on the gateway or a paired computer, then refresh this view.","text_hash":"608ae8a39625a0da1b6804480e57835af5a1e566af2095d11cca8bf0a6e421a9","tgt_lang":"pl","translated":"Włącz udostępnianie sesji Codex na Gateway lub sparowanym komputerze, a następnie odśwież ten widok.","updated_at":"2026-07-09T10:01:43.766Z"}
{"cache_key":"43b6f941f1550c67ac31bb74c5b688df998ea5df59b2832a01810d79281feca1","model":"gpt-5.6-sol","provider":"openai","segment_id":"agentScope.label","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Agent scope","text_hash":"0833bc070d2c153692bc25fcc0b30f774cb415efdbf95fe8cd132feab8053698","tgt_lang":"pl","translated":"Zakres agenta","updated_at":"2026-07-13T11:01:28.916Z"}
{"cache_key":"43c0bc453ae36034c645231a84990e953d51e89afda78a2f5dec699ce627b51a","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"pl","translated":"Przesyłanie plików…","updated_at":"2026-07-14T10:36:47.635Z"}
{"cache_key":"43feb4b64014def414338361c0ff9be3d426cd0451fffd6d18eaa641a57ee521","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.toggleRawRedaction","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Toggle raw config redaction","text_hash":"c5399110ce02553ab9242227980687b57b8eca8c64bd3b85224f888c49ed5648","tgt_lang":"pl","translated":"Przełącz ukrywanie surowej konfiguracji","updated_at":"2026-07-12T06:48:03.350Z"}
{"cache_key":"4422f53c82a54b48c27d83551b09889968f0ac753e9943e59562a45bda622e0e","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.appearance.inlineHintAfter","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"to add one browser-local tweakcn theme. In tweakcn, use Share and paste the copied link here.","text_hash":"e6c946eeb47e2543aee4c4df56f6083c410ce72c103903990e1d69bec34ca5f8","tgt_lang":"pl","translated":"aby dodać jeden lokalny motyw tweakcn w przeglądarce. W tweakcn użyj opcji Udostępnij i wklej skopiowany link tutaj.","updated_at":"2026-07-12T06:47:49.737Z"}
{"cache_key":"4456a49590a40b38ed009e73c1b73627841e621d38b24d697a00413cfad64573","model":"gpt-5.5","provider":"openai","segment_id":"worktrees.restore","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Restore","text_hash":"a76e13b9839270eb73ed11417f7d8acca55df0ad52065799361631d0fff74f27","tgt_lang":"pl","translated":"Przywróć","updated_at":"2026-07-05T21:01:26.445Z"}
@ -1413,6 +1415,7 @@
{"cache_key":"c81659a71f0382701d58b36d7320fb345423472ed3a7aff1221b96d3b5e7229e","model":"gpt-5","provider":"openai","segment_id":"cron.detail.active","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Active","text_hash":"92340695899bd2d86223e4a007620e0d6502fc0e08809773634c7e0743764a9c","tgt_lang":"pl","translated":"Aktywne","updated_at":"2026-07-09T10:01:43.766Z"}
{"cache_key":"c825d11f882daa4379f165048482b68c03b2b86e7c8efbd22b4570a7b44a3a21","model":"gpt-5.5","provider":"openai","segment_id":"browser.annotatePrompt.outro","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Please look at the marked area and tell me what you make of it.","text_hash":"fdf6ad77887cf4668105f142e42a6fc67d025d92f7852d80c352e2fbacebd9bf","tgt_lang":"pl","translated":"Spójrz proszę na oznaczony obszar i powiedz mi, co o nim sądzisz.","updated_at":"2026-07-11T02:19:38.200Z"}
{"cache_key":"c840a5098eefacd4bd6d161fa5433a9d32df2a304437024d9b026b45dbcac5a8","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agents.toolCatalog.descriptions.message","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Send messages","text_hash":"27a3f5335350f18465a1bb8c950fe1aad4c5909c77610e64844ff7714848d640","tgt_lang":"pl","translated":"Wysyłaj wiadomości","updated_at":"2026-07-12T06:46:19.681Z"}
{"cache_key":"c87ed952c9f0d0a44728d8d664be30cd5c02208155581e9a28a76ada0408bf76","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"pl","translated":"Dodaj pliki do terminala","updated_at":"2026-07-14T10:36:47.635Z"}
{"cache_key":"c8b146c4c78777af269c8b88bde5775f4e8e7fb57071d5989ae215bfe822cd35","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.viewPendingChanges","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"View {count} pending changes","text_hash":"56a0ea55b7862b3f83cf7b2af895dc21be5c9a45f2fe58fcce7564fb7e51043e","tgt_lang":"pl","translated":"Wyświetl oczekujące zmiany: {count}","updated_at":"2026-07-12T06:47:56.488Z"}
{"cache_key":"c8bb57f0a39779621f5725bd31c4dd6b38317f253b85fabffca99962c091c065","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.empty.noProposalsBody","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"{agent} hasn't drafted any skill proposals.","text_hash":"499e6a82a2c1b11837a9b08d4ceb23ba0f9e0291b5d9cfb52337b23231400cde","tgt_lang":"pl","translated":"{agent} nie przygotował jeszcze żadnych propozycji umiejętności.","updated_at":"2026-07-12T06:49:26.281Z"}
{"cache_key":"c973773ec9457e515b893ec5c027acc70eaf0e4f2779a1c79d149174d4adcb96","model":"gpt-5.5","provider":"openai","segment_id":"browser.annotatePrompt.moreRegions","source_path":"ui/src/i18n/locales/pl.ts","src_lang":"en","text":"…plus {count} more marked region(s), all visible in the screenshot.","text_hash":"d11184c08b1bb4c0899c97fdd9a27bb719de7b7f5540a9b2cdafe66c975ca65d","tgt_lang":"pl","translated":"…oraz {count} kolejnych oznaczonych regionów, wszystkie widoczne na zrzucie ekranu.","updated_at":"2026-07-11T02:19:38.200Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:50.322Z",
"generatedAt": "2026-07-14T15:37:44.696Z",
"locale": "pt-BR",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -963,6 +963,7 @@
{"cache_key":"85cb4e6c4de65570dd4475c45d5dba088ff2f3357fbff1e733d3ab8faea26343","model":"gpt-5.5","provider":"openai","segment_id":"chat.splitView.splitDown","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Split down","text_hash":"8730b89df7caaf5b5090f9b7365a0a03e0a13d9682dc6418f556b8a676d9e98f","tgt_lang":"pt-BR","translated":"Dividir para baixo","updated_at":"2026-07-06T07:23:13.378Z"}
{"cache_key":"8624097f9d10fb615da66a4341195eba407f92f016c3bfc9d407283c100dfa3d","model":"claude-opus-4-8","provider":"anthropic","segment_id":"githubPreview.ariaLabel","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"{state} {kind} {repo} #{number}: {title}, by {author}","text_hash":"e18c624550814e4318a45e1e0f8782913409763d046aa703519e91c887be205b","tgt_lang":"pt-BR","translated":"{state} {kind} {repo} #{number}: {title}, por {author}","updated_at":"2026-07-12T06:24:58.182Z"}
{"cache_key":"8626b07aa9a791dc6a5438a7bad1b0b86ce826ee1f24ea14c96e5d3daad755f7","model":"gpt-5.5","provider":"openai","segment_id":"chat.composer.microphoneFallback","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Microphone {number}","text_hash":"357eae20db9739dfdbb59ec21db70200f6ca9ee257c28ed637712f147af419ec","tgt_lang":"pt-BR","translated":"Microfone {number}","updated_at":"2026-07-06T17:56:11.051Z"}
{"cache_key":"86349621fd2b61dd8e5d285705f6768c1b8cf3e1653a4ca70d6abeeabe68e3ce","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"pt-BR","translated":"Adicionar arquivos ao terminal","updated_at":"2026-07-14T10:35:48.873Z"}
{"cache_key":"8664caed8c1accb472a9c8353d80ddfbe8abc92e8fde18185a92b80add2d12b5","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.backgroundTasks.statusPreviewMore","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"+{count} more","text_hash":"ecccea94c62457a718fff608b635a8fdeb2a9d43b60a9db2680fa35e800b5dd6","tgt_lang":"pt-BR","translated":"+{count} mais","updated_at":"2026-07-12T06:25:16.155Z"}
{"cache_key":"869adaaf933f58ebce0de74cca77566e54c11d15467234708b2838d31d125536","model":"gpt-5","provider":"openai","segment_id":"codexSessions.searchPlaceholder","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Search session titles","text_hash":"9a6bdede84234fa08d6294e1636a34d26cbdd8eca425248f8d3c6cf8844a0cf9","tgt_lang":"pt-BR","translated":"Pesquisar títulos de sessões","updated_at":"2026-07-09T10:01:43.718Z"}
{"cache_key":"869e8d4c7aacef3723f24c727154274125df8d963a93a7a3b751832bf7cb47fa","model":"claude-opus-4-8","provider":"anthropic","segment_id":"cron.form.accountId","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Account ID","text_hash":"919bb4cb2182c322ed2e1d13d112570bfcff57a2b9260bf3ff19939975d042b2","tgt_lang":"pt-BR","translated":"ID da conta","updated_at":"2026-07-12T06:29:38.006Z"}
@ -990,6 +991,7 @@
{"cache_key":"8a0d9b8e5d25ec43bb76531df3b96b64cfab1b61dbbd1f08d667cdbfcb8b3af0","model":"claude-opus-4-8","provider":"anthropic","segment_id":"quickSettings.personal.user","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"User","text_hash":"b512d97e7cbf97c273e4db073bbb547aa65a84589227f8f3d9e4a72b9372a24d","tgt_lang":"pt-BR","translated":"Usuário","updated_at":"2026-07-12T06:26:38.130Z"}
{"cache_key":"8a4c1ba0dde3db6bc2fe7eec30bedcd565b85ccd6326c09ac27446d62d1c8d64","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.workspaceFiles.root","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Root","text_hash":"44cb005ee2e65d9cc817b0a083579369fb6c24a4be728cb43fd9d4c3ca7f4c2e","tgt_lang":"pt-BR","translated":"Raiz","updated_at":"2026-06-16T14:13:25.058Z"}
{"cache_key":"8a5394bf53b38de5b08d8c7fb25c98d145b9f8808056b2b3e181824fb52f5888","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.unknownStatus","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Unknown","text_hash":"b764cdc0eab7137467211272fa539f1260d1bf2e71bcf6ff3bdc960f5c16aa14","tgt_lang":"pt-BR","translated":"Desconhecido","updated_at":"2026-06-16T14:13:17.394Z"}
{"cache_key":"8a94dcd17f97dbfe334da48e5dcca5c954f593f5a0f36957193fd24781c45d62","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"pt-BR","translated":"Solte os arquivos para adicioná-los","updated_at":"2026-07-14T10:35:48.873Z"}
{"cache_key":"8ad5a52fe9d71279f6cf57e8d5d3b5d74621191515f0bbb08d7bd31e535ccaee","model":"gpt-5.5","provider":"openai","segment_id":"worktrees.newWorktree","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"New worktree","text_hash":"4f210afedcabde192cf04e3c8c1ff21f79149bc696d1b8abaece56e8e3faa4dd","tgt_lang":"pt-BR","translated":"Novo worktree","updated_at":"2026-07-10T17:58:42.698Z"}
{"cache_key":"8b46b3a9420a33cc7c0da76ddcfba982382f4aea1e048f6ed070572051f2a5ae","model":"gpt-5.5","provider":"openai","segment_id":"worktrees.restorable","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Restorable","text_hash":"bc97d2ddd2dba3ab2391f21314316556111065c4b870bc05679fadd60a754c01","tgt_lang":"pt-BR","translated":"Restaurável","updated_at":"2026-07-05T21:00:34.411Z"}
{"cache_key":"8b48e222baf6c74f53949de0d752d54cb13b18eee0792cdd032a5f273d98325a","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.logging.label","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Logging","text_hash":"d3ef01b4a9c9910364c9b26b2499c8787a0461d2d24ab80376fff736a288b34c","tgt_lang":"pt-BR","translated":"Registro","updated_at":"2026-07-12T06:26:11.562Z"}
@ -1157,6 +1159,7 @@
{"cache_key":"a3812845e343980a1fd4747adb382e07d7bcef42f2de4951700c541837a9fef2","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.detailPanel.overwrite","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Overwrite","text_hash":"b24963ea2cbc74b97321a347754137aa207b126695a95c860406098528966b55","tgt_lang":"pt-BR","translated":"Sobrescrever","updated_at":"2026-07-12T06:29:15.360Z"}
{"cache_key":"a3d62cbb62e0644bd0a33206d8fe224d4949acaf1391c983552ae8e99ede1e1a","model":"claude-opus-4-8","provider":"anthropic","segment_id":"cron.form.runsIn","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Runs in","text_hash":"617579d5e7578130fcb7aaeeccc3d7f0d2597bd10b7f007bff5e563e255fdec2","tgt_lang":"pt-BR","translated":"Executa em","updated_at":"2026-07-12T06:29:38.006Z"}
{"cache_key":"a3ed8aac7b293199f786dec9533b299d5197f9282dd722fda4a63279c2309462","model":"gpt-5.5","provider":"openai","segment_id":"workboard.eventOrchestration","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Orchestration","text_hash":"ed4fdd1721677737cffb2862fe34d5b63901c7cc76b8c67c51e92a467b31a5e7","tgt_lang":"pt-BR","translated":"Orquestração","updated_at":"2026-05-30T15:38:08.357Z"}
{"cache_key":"a407a4d1934985e4156e87904b3de5363c5c1166495b0425478904dffbe86bc1","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"pt-BR","translated":"Enviando arquivos…","updated_at":"2026-07-14T10:35:48.873Z"}
{"cache_key":"a42348a92c7f2b355caffb2211845c06851100e590b3b519aa6329e19fcbf6f5","model":"gpt-5.5","provider":"openai","segment_id":"workboard.badgeWorkerProtocol","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"worker {state}","text_hash":"f16b9e04d42182b421ce4f4e982b2ef75fab9bd581bdc8b87e62899ba28de11c","tgt_lang":"pt-BR","translated":"worker {state}","updated_at":"2026-05-30T15:38:08.357Z"}
{"cache_key":"a4468d719ce5f21ac7654de28741697e218ebe69f8a46eb9e1423b003e7844f9","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.peek","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"Peek","text_hash":"d5fa5ccb11de722d3e722afe7ce4228774b6dc0b51b71c90ba69d5999185663d","tgt_lang":"pt-BR","translated":"Espiar","updated_at":"2026-07-12T06:27:22.409Z"}
{"cache_key":"a46e0c2225dbbbd1578928e1448446a27c4dbf7db14caced1a3e21c72dbd6bbd","model":"gpt-5.5","provider":"openai","segment_id":"configForm.sections.mcp.label","source_path":"ui/src/i18n/locales/pt-BR.ts","src_lang":"en","text":"MCP","text_hash":"53f13ae99ed53bd346eb8e1c8cefb7ef8260683b50401caf101360967ea052aa","tgt_lang":"pt-BR","translated":"MCP","updated_at":"2026-05-31T05:36:33.676Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:54.394Z",
"generatedAt": "2026-07-14T15:37:46.764Z",
"locale": "ru",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -695,6 +695,7 @@
{"cache_key":"37958e5a0374a1c7932ba498938bb55449f3647a628b24678dcf87757ab87eb7","model":"gpt-5.5","provider":"openai","segment_id":"sessionsView.newGroup","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"New group…","text_hash":"ce58c189f2045434c28a50c9875a7362d28c79fb34d4b365c09f59180ca2712a","tgt_lang":"ru","translated":"Новая группа…","updated_at":"2026-07-05T14:40:26.836Z"}
{"cache_key":"37c53936f414e237fae201cbc697a8c0eb0679e6573d3f8e41a8f699182f582e","model":"gpt-5.5","provider":"openai","segment_id":"workboard.hideArchived","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Hide archived cards","text_hash":"60c01f7b3b145b9c99ba3cf83900ef322102262cbb37d1267708dc2b83f2fc34","tgt_lang":"ru","translated":"Скрыть архивные карточки","updated_at":"2026-06-26T21:39:54.162Z"}
{"cache_key":"37ca6c0b03c0a98b7c3d5bc7ad9c5cd4805cc2656f775e5551a89c059e7b1d5f","model":"claude-opus-4-8","provider":"anthropic","segment_id":"dreaming.wiki.candidateSignals","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Potentially useful signals","text_hash":"f69754a152eee8659a29581c065c96c4b9dc1cad14ed57c8c5cfa4bd6c1a1b9c","tgt_lang":"ru","translated":"Потенциально полезные сигналы","updated_at":"2026-07-12T07:02:20.103Z"}
{"cache_key":"37d1c001dbc93851151caec9c230d1d44f189438da13d3181a597b4b508716fe","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"ru","translated":"Добавить файлы в терминал","updated_at":"2026-07-14T10:37:01.155Z"}
{"cache_key":"37ddf1aac6724627b1a66390aea57bebb677926ffde62b4f9aec53c1bc83d8fe","model":"claude-opus-4-8","provider":"anthropic","segment_id":"quickSettings.system.gatewayHost","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Gateway Host","text_hash":"3a3f756a0473349f21d2b9fe6ace8684b3218d89b9db83c59f5071183fe97ec7","tgt_lang":"ru","translated":"Хост Gateway","updated_at":"2026-07-12T06:59:50.969Z"}
{"cache_key":"37e8e7a3b5b867d82a7dd38f9e26dc67d7ebb70dcfeccde8ce1b2212277a301a","model":"gpt-5.5","provider":"openai","segment_id":"chat.workspaceFiles.summary","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Session workspace summary","text_hash":"1ed422c34dc1802d4c7366164ae810c496e206fe82e8e6565cefc38230b56bb4","tgt_lang":"ru","translated":"Сводка рабочей области сеанса","updated_at":"2026-06-26T21:42:06.902Z"}
{"cache_key":"37e9f8a91ade9b8f3f043532230a28a431ba88e958ce311377af5c71d613bd16","model":"gpt-5.5","provider":"openai","segment_id":"chat.workspaceFiles.showFiles","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Show session files","text_hash":"88e60963b00018033f164b496f29e784fddfdb400cd19baf3311e04645bab27a","tgt_lang":"ru","translated":"Показать файлы сеанса","updated_at":"2026-07-10T06:08:53.986Z"}
@ -1753,6 +1754,7 @@
{"cache_key":"8a069381e75a79d663aa30500350b64fc652038fa03a73f060424e29d32dbe98","model":"claude-opus-4-8","provider":"anthropic","segment_id":"usage.details.filterByRole","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Filter by role","text_hash":"67fd9c1a7c7d0baff8a98f0c5cf70b3b5f826ca3835b02d6f380b06f349180c8","tgt_lang":"ru","translated":"Фильтр по роли","updated_at":"2026-07-12T07:02:32.992Z"}
{"cache_key":"8a100fb940cf2340e0d1127de6adb0dabfcb97df5351b0d209418b88ef729d5a","model":"claude-opus-4-8","provider":"anthropic","segment_id":"pluginsPage.connectorDescriptions.markets","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Live stocks and crypto with price alerts and daily digests.","text_hash":"b6410f326e27df23d2bf50e3c22a14063644d715f33f24222d54c6ba1687e6ab","tgt_lang":"ru","translated":"Актуальные акции и криптовалюты с оповещениями о ценах и ежедневными сводками.","updated_at":"2026-07-12T07:01:38.753Z"}
{"cache_key":"8a1e77df6f5d1c12d2ebacda7bbbd69fe627bab24387d240eb4ebdfa27de4627","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.status.rejected","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Rejected","text_hash":"aea4a04a80426ed865ec2058b16854b9146166d22c1f3282a18f285941c42eba","tgt_lang":"ru","translated":"Отклонено","updated_at":"2026-07-12T07:01:38.753Z"}
{"cache_key":"8a210d2bf22e672a41ea497120192de4ce4be40391f0cc0763b8af0d4c8dafa0","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"ru","translated":"Перетащите файлы, чтобы добавить их","updated_at":"2026-07-14T10:37:01.155Z"}
{"cache_key":"8a3f94df336f50a1eaf865e6d25a96f42687032772289208185c2981fc5b5442","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentTools.loadingCatalog","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Loading runtime tool catalog…","text_hash":"4219f435cd9da1794976ea616fdf071b2eaabe43e846f0a410927c0b6ed3aa1f","tgt_lang":"ru","translated":"Загрузка каталога инструментов среды выполнения…","updated_at":"2026-07-12T07:00:50.137Z"}
{"cache_key":"8a5a433f635e0c3e466da4d6de3537f1626e6391bfba5c0d6714e2f2a193287d","model":"claude-opus-4-8","provider":"anthropic","segment_id":"dreaming.wiki.loadingPalace","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Loading memory palace…","text_hash":"3121bef4fa33fc881c0b5bd7a187537c0c37fd0de06f901ee7a5b6b99739473f","tgt_lang":"ru","translated":"Загрузка дворца памяти…","updated_at":"2026-07-12T07:02:26.761Z"}
{"cache_key":"8a6ed44e6e673ef779ec1c2cbdd557932cf9c5d812000d0b0eca57a4c621b03c","model":"gpt-5.5","provider":"openai","segment_id":"usage.overview.throughputHint","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Throughput shows tokens per minute over active time. Higher is better.","text_hash":"25aa92e440598aef332a7addc6d14989f1f7562c8fa83110304de0ecd228d8a1","tgt_lang":"ru","translated":"Пропускная способность показывает количество токенов в минуту за активное время. Чем выше, тем лучше.","updated_at":"2026-06-26T21:41:16.423Z"}
@ -2887,6 +2889,7 @@
{"cache_key":"eb2c1b606d82478ca1fc44afcf913ee079b04906cd54019b6d7b88982021bff3","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.themes.claw.description","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Chroma family","text_hash":"895768becc23f9a7cd5f8eb8ab535e02b3458bc6bb2efadca3368e5e7d623d0a","tgt_lang":"ru","translated":"Семейство Chroma","updated_at":"2026-07-12T07:00:07.907Z"}
{"cache_key":"eb483fc3c9b3c96210194de8f4e7b91ca44ebe69ed7efc543333a96d012ef116","model":"gpt-5.5","provider":"openai","segment_id":"cron.jobs.ascending","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Ascending","text_hash":"77184595bde3befc7f5a20efc97caea43f4858e4c97cd2ee406af2c61db3266c","tgt_lang":"ru","translated":"По возрастанию","updated_at":"2026-06-26T21:42:21.706Z"}
{"cache_key":"eb5ac90c0ca22a2e585aa17503deb63ada54512226289f693de914444857906e","model":"gpt-5.6-sol","provider":"openai","segment_id":"connection.snapshot.lastError","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Last error","text_hash":"5488d837f5f65d6f0774b85c0f2bccacbfdd3e94b976c5ed423021da341bdd96","tgt_lang":"ru","translated":"Последняя ошибка","updated_at":"2026-07-13T16:01:20.786Z"}
{"cache_key":"eb5ebd835c1b36e8371b4ceac3b1ed6b716a1794830b5e929a8d0b12878580cd","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"ru","translated":"Загрузка файлов…","updated_at":"2026-07-14T10:37:01.155Z"}
{"cache_key":"eb9505b6df9985f232335f389040b52f0ce007296c4d7699f4991289d8552dd5","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.canvasHost.description","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Canvas rendering and display","text_hash":"b1bf5986d125dac92fb30e91c5f83e3b97d18b54ff5a628a5eef267efe9ebcba","tgt_lang":"ru","translated":"Рендеринг и отображение Canvas","updated_at":"2026-07-12T06:59:34.273Z"}
{"cache_key":"eb96f0576e12d9233ee12ff3f2291bf73f5c649e05031e153fa5361c1df07701","model":"gpt-5.5","provider":"openai","segment_id":"cron.jobList.remove","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"Remove","text_hash":"c3812fc4acb861d5182fc2b8155f327f736fbe5e5eb86a7bd7afcb6dc5497282","tgt_lang":"ru","translated":"Удалить","updated_at":"2026-06-26T21:42:47.554Z"}
{"cache_key":"ebb0521f06df4e63538364c049f7975d7b8f50d0c572e1f93a9e1744a437e490","model":"gpt-5.5","provider":"openai","segment_id":"dreaming.status.nextSweepPrefix","source_path":"ui/src/i18n/locales/ru.ts","src_lang":"en","text":"next sweep","text_hash":"836b65b782a40d015ac29fa976e399ea979cc1c659c551f5de304c4004ed8dd4","tgt_lang":"ru","translated":"следующая проверка","updated_at":"2026-06-26T21:40:41.209Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:53.306Z",
"generatedAt": "2026-07-14T15:37:46.291Z",
"locale": "th",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -456,6 +456,7 @@
{"cache_key":"3e0597a8064154eb68bf2399f6403aef0365756a57e03391a52c88562508513e","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.appearance.importedTheme","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Imported theme","text_hash":"8831d7bcb67b703fb2b1ed5647711bef8498b81bd038f3fc5376f0825a98f40c","tgt_lang":"th","translated":"ธีมที่นำเข้า","updated_at":"2026-07-12T06:53:20.853Z"}
{"cache_key":"3e0827ad211db78646b561f4139e69a78b0572d4b4aae0639580d7ee692f6684","model":"gpt-5.6-sol","provider":"openai","segment_id":"connection.access.hidePassword","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Hide password","text_hash":"a60a56c584b3b05b1a95076a36edbab7131a447910cf21124efcb35f769502df","tgt_lang":"th","translated":"ซ่อนรหัสผ่าน","updated_at":"2026-07-12T00:10:17.485Z"}
{"cache_key":"3e48e96393e8dec095163ec83ff20c50fb52fc38d4f375045c95904736e38312","model":"gpt-5.6-sol","provider":"openai","segment_id":"debug.callFailed","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Call failed","text_hash":"f5da6de3a9801f3e8b05f8f99ecf1f6c3b72b2865f2355fb3004551e2f2233fd","tgt_lang":"th","translated":"การเรียกใช้ล้มเหลว","updated_at":"2026-07-13T16:01:03.178Z"}
{"cache_key":"3e79bb3b1c0ab629b7da4025e93c6e19b086527030d94744c9b117b3e6fa377a","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"th","translated":"เพิ่มไฟล์ไปยังเทอร์มินัล","updated_at":"2026-07-14T10:36:50.100Z"}
{"cache_key":"3e804e53feacda47008da85f58fa15a5f4b0fe9313764b5a3779b24f61342ffa","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.acp.label","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"ACP","text_hash":"75ad69d7586c3d7e42c1ac14e80c7938dc0e7413f7f6f867c3be14d5304cc66b","tgt_lang":"th","translated":"ACP","updated_at":"2026-07-12T06:51:59.866Z"}
{"cache_key":"3ec7e5c1ffad1f6ff867594cf51c3872c052bd964c4a683c06217ff448b56ab0","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.commentaryToggle","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Keep commentary after the final answer","text_hash":"febdff0791d1ceeddb2b7596da8282f4dcfd5cff4cad11dea4c0a23944cd8ffe","tgt_lang":"th","translated":"เก็บคำอธิบายหลังคำตอบสุดท้าย","updated_at":"2026-07-01T01:08:34.109Z"}
{"cache_key":"3ed1c013620ec37de83e4f13151c5e88869f26c05b3edac234d46d6665e1d034","model":"claude-opus-4-8","provider":"anthropic","segment_id":"cron.form.failureAlertWebhook","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Webhook (HTTP POST)","text_hash":"02ad6f27c8f776fb40227ab86832c482ab1b3a487db43f5adc69645430a1b9cd","tgt_lang":"th","translated":"Webhook (HTTP POST)","updated_at":"2026-07-12T06:58:44.975Z"}
@ -869,6 +870,7 @@
{"cache_key":"768675c8e206c73dc7296f34c1fd83dba0f674f3ccb59d3cfdf81eed536d5de7","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillsPage.tabs.disabled","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Disabled","text_hash":"75081b593d15cf6e631971bc6768723f593b88b172477e40ae7d363e4829816d","tgt_lang":"th","translated":"ปิดใช้งาน","updated_at":"2026-07-12T06:54:44.653Z"}
{"cache_key":"7691e81135a40088d74ce39347366612e3ba7a29ee056a7c1cf3758c88d410d8","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.auth.description","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"API keys and authentication profiles","text_hash":"513c3d5b197fbd18d7cfaf12cd51f2598a00e886c108bd6e595d506ef24caa98","tgt_lang":"th","translated":"คีย์ API และโปรไฟล์การยืนยันตัวตน","updated_at":"2026-07-12T06:51:31.234Z"}
{"cache_key":"76a105680f440eab4e5c9b2f1b4f89d4e4477a4d27ab9ed70ed08cf8c1b42b43","model":"gpt-5","provider":"openai","segment_id":"codexSessions.empty.archived","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"No archived sessions on this host.","text_hash":"5de6bb0c0036228e8732a675c33ab05843952419ef985706e349bb761da87c40","tgt_lang":"th","translated":"ไม่มีเซสชันที่เก็บถาวรบนโฮสต์นี้","updated_at":"2026-07-09T10:01:43.768Z"}
{"cache_key":"76e614f9ba8e34b5f5013ee6e36eaabdf59e1f8e87abfa859074a1a12d4e0282","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"th","translated":"วางไฟล์เพื่อเพิ่ม","updated_at":"2026-07-14T10:36:50.100Z"}
{"cache_key":"76f96d9c89486745a0f8e7676d77673bb9fa246c96616e99b7a2010cbb5b6ea1","model":"claude-opus-4-8","provider":"anthropic","segment_id":"cron.stats.tasks","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Tasks","text_hash":"b3a60e61a5233d0506ac737405a2a45280349683cac68722f18d0b73eb495ef4","tgt_lang":"th","translated":"งาน","updated_at":"2026-07-12T06:58:11.766Z"}
{"cache_key":"76f985ad75e47e8097dda6a2d0f8b05cbdba19501acb64865bd1e10021fca140","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentTools.disableAll","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Disable All","text_hash":"cd265895b3d90a6774b7a744fec7b1bee63d15638800905e1320bc72f0f3505a","tgt_lang":"th","translated":"ปิดใช้งานทั้งหมด","updated_at":"2026-07-12T06:54:14.347Z"}
{"cache_key":"77163a367f0c86a79d897fb37677e10960e42082aac10dd9bf4c2336e3eaa3f3","model":"claude-opus-4-8","provider":"anthropic","segment_id":"nodes.inventory.autoPaired","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"auto-paired","text_hash":"32bc56099d008345493a67a4a83ba0f8530f81cdfae6e3b03e7baab520b05f7e","tgt_lang":"th","translated":"จับคู่อัตโนมัติ","updated_at":"2026-07-12T06:49:52.359Z"}
@ -1329,6 +1331,7 @@
{"cache_key":"b8f88bf6ae0ba02598cafa1dc6fd7d4116d85d423a2dc34334d4ae0ec84f3cc9","model":"gpt-5","provider":"openai","segment_id":"nodes.execApprovals.gateway","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Gateway","text_hash":"41ed52921661c7f0d68d92511589cc9d7aaeab2b5db49fb27f0be336cbfdb7df","tgt_lang":"th","translated":"Gateway","updated_at":"2026-07-09T10:01:43.768Z"}
{"cache_key":"b950b7fb6a9469e4df9ba95fa9a36d3065a0bd1e6a704eb93026717246e8be7c","model":"gpt-5.5","provider":"openai","segment_id":"claudeSessions.eyebrow","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Claude fleet","text_hash":"81e1decd8455ccf13fccde21497bd4235846a39b58ce79cbdb01d3ac6a8b2626","tgt_lang":"th","translated":"กลุ่ม Claude","updated_at":"2026-07-11T13:51:20.603Z"}
{"cache_key":"b96964a55ae7c394a0cdcfedcfe80aff9e9e734eede13912b2e0b38f7d5855b5","model":"gpt-5.6-sol","provider":"openai","segment_id":"agentChip.getHelp","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Get help","text_hash":"fd64e81bf74ddf97a7e79318e68ad3af232c351f50b20dfd5e981a5e7e1e537c","tgt_lang":"th","translated":"ขอความช่วยเหลือ","updated_at":"2026-07-13T01:36:51.373Z"}
{"cache_key":"b969ddf6f99a22b9a71b57415e7197d00d1cfb2083c76e8e56c7f6bd7af2e4b4","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"th","translated":"กำลังอัปโหลดไฟล์…","updated_at":"2026-07-14T10:36:50.100Z"}
{"cache_key":"b96cef5cf22657cfc7768264eddb54221e8657b25948ef8f441f3241d6d9cc06","model":"claude-opus-4-8","provider":"anthropic","segment_id":"nodes.inventory.title","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Devices","text_hash":"4ba5121d4d1be174a80a063a823df8b496c83ed05ee60af962a9f65d686533bc","tgt_lang":"th","translated":"อุปกรณ์","updated_at":"2026-07-12T06:49:52.359Z"}
{"cache_key":"b97c52c974d3d2dbf0a9e85e36396f4a28994cc89ef6ca63655045416abdb0bb","model":"gpt-5.6-sol","provider":"openai","segment_id":"channels.hub.stateConfigured","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Configured","text_hash":"84aebc69a1bf739a343be9c66edfd3160f77220ea69789a8147dd4ae261fd188","tgt_lang":"th","translated":"กำหนดค่าแล้ว","updated_at":"2026-07-13T16:52:50.541Z"}
{"cache_key":"b98bb8e15cee471c054f385a1723154055351f35ffa3bafcc917043db8069d40","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentTools.title","source_path":"ui/src/i18n/locales/th.ts","src_lang":"en","text":"Tool Access","text_hash":"cf8084fcb3ba5158b83bed00ade2acfcba14311d9da2e7f7891f321addcd1c6c","tgt_lang":"th","translated":"การเข้าถึงเครื่องมือ","updated_at":"2026-07-12T06:54:14.347Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:52.411Z",
"generatedAt": "2026-07-14T15:37:45.814Z",
"locale": "tr",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -901,6 +901,7 @@
{"cache_key":"8418c37683b8eaeaea436a002211be82c66d2142d933c1f5dedf60cb609cb859","model":"gpt-5.5","provider":"openai","segment_id":"chat.sidebar.workSessions","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Work","text_hash":"104ab9213e28e4ff5ba0b4086457503e8a4656815cfec7bcf2799d76a3db081d","tgt_lang":"tr","translated":"Çalışma","updated_at":"2026-07-10T17:59:36.278Z"}
{"cache_key":"84306424624615f70a4e7fd9c33c2363c02921242eae05a987429d480ad1b8b6","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillsPage.shown","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"{count} shown","text_hash":"e57b4adfe868fd74a183650103d820176d4960bd0bdb677d9985db09f9752867","tgt_lang":"tr","translated":"{count} gösteriliyor","updated_at":"2026-06-16T14:15:55.679Z"}
{"cache_key":"844153722689938c0bc0c035ad1d56ea4b468bf05ce383fde60c6457f60eff89","model":"claude-opus-4-8","provider":"anthropic","segment_id":"nodes.execApprovals.defaultSecurity","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Default security mode.","text_hash":"1d38d860302aed9bcefbd4ca4a2ea15366e7ca937186d8c4e5ddc633503cf1d6","tgt_lang":"tr","translated":"Varsayılan güvenlik modu.","updated_at":"2026-07-12T06:38:44.811Z"}
{"cache_key":"8443e52b47ed0dca63401c72103c861c5f23cc99eac2d55c0a1fddb7d31005d6","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"tr","translated":"Dosyalar yükleniyor…","updated_at":"2026-07-14T10:36:40.732Z"}
{"cache_key":"8491b50b46999e8a8fd532c806e70d1ddf832d4faaa2fb0a17bc9cb75d1ef69a","model":"claude-opus-4-8","provider":"anthropic","segment_id":"mcpPage.noServers","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"No MCP servers configured.","text_hash":"9729297abe88767d0ca31bd027c45fbbadc5aca0ad396c0fb39292341f7968cc","tgt_lang":"tr","translated":"Yapılandırılmış MCP sunucusu yok.","updated_at":"2026-07-12T06:41:39.223Z"}
{"cache_key":"84ab80bba233675b4b30c49a2f3b60c6577bb5225cc55db2e820c63a1427a433","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.update.description","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Auto-update settings and release channel","text_hash":"e61b824d77d8e34d4e3ede3d018533f02848cc6f2071b15a7682beed13a315e7","tgt_lang":"tr","translated":"Otomatik güncelleme ayarları ve sürüm kanalı","updated_at":"2026-07-12T06:39:28.784Z"}
{"cache_key":"84d25b2a96bf7ec5caa0cddfd2726c51a3242b890c7002aae948e782a4cb918c","model":"gpt-5","provider":"openai","segment_id":"codexSessions.eyebrow","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Codex fleet","text_hash":"64e0510e4f9e07ad1283b7c1d55e67b5b853081b6ca4013fc8d710aa658d5127","tgt_lang":"tr","translated":"Codex filosu","updated_at":"2026-07-09T10:01:43.764Z"}
@ -1569,6 +1570,7 @@
{"cache_key":"e647e52c996a0fe3788a3e1817082094a757aa165e9c073ca203750c4641400d","model":"claude-opus-4-8","provider":"anthropic","segment_id":"pluginsPage.connectorDescriptions.linear","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Triage issues, update cycles, and file bugs straight from chat.","text_hash":"9ac5ab0db3f984cec1f653b56e4d930ea8e519c7a6482724f3822381b8fb6645","tgt_lang":"tr","translated":"Sorunları önceliklendirin, döngüleri güncelleyin ve doğrudan sohbetten hata bildirin.","updated_at":"2026-07-12T06:41:39.223Z"}
{"cache_key":"e64a4157c689d624219d0db441070595e86341effb14ac909f3a4ef79b38c641","model":"gpt-5.5","provider":"openai","segment_id":"sessionsView.deleteSessionsConfirm","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Delete {count} sessions and their transcripts?","text_hash":"1a75ddcf6aef0115cd256df8f5f4bebd87ba3edd5d30fa5927a9cafb9df47243","tgt_lang":"tr","translated":"{count} oturum ve bunların dökümleri silinsin mi?","updated_at":"2026-07-11T10:41:05.371Z"}
{"cache_key":"e6628c0fff1357d79ad12f2370bfc00298e1cfae6e8e9f0795a454af6f7f92e8","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agents.overview.allSkills","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"all skills","text_hash":"b4b26039425d8c24efa68e4192cd76c2a6566594948b15d866e9dd98ee5af113","tgt_lang":"tr","translated":"tüm skills","updated_at":"2026-07-12T06:38:57.731Z"}
{"cache_key":"e6aa36950488c0b8e67e157b73c16256ab60e1a22854e4c061853ed1bea08618","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"tr","translated":"Eklemek için dosyaları buraya bırakın","updated_at":"2026-07-14T10:36:40.732Z"}
{"cache_key":"e6d955856bb891dda15fefea2ce840f83e6e51a19e94c302d6ead0876b2599e5","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.detailAutomation","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Automation","text_hash":"d909750b1bbb71a39b6330ba8f81f4f8f6e889ed96d7ab366e74857909750c64","tgt_lang":"tr","translated":"Otomasyon","updated_at":"2026-06-16T14:15:38.462Z"}
{"cache_key":"e6e730ab3fc359aa5af24276870030e0561d17888a2e937f7c21c7609786764f","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentTools.disableAll","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Disable All","text_hash":"cd265895b3d90a6774b7a744fec7b1bee63d15638800905e1320bc72f0f3505a","tgt_lang":"tr","translated":"Tümünü Devre Dışı Bırak","updated_at":"2026-07-12T06:41:04.649Z"}
{"cache_key":"e716d1bd28b87ece7f1f342f02ed986b2a1a8072f1899c4a0a3213ed1fa13d09","model":"claude-opus-4-8","provider":"anthropic","segment_id":"cron.form.action","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Action","text_hash":"64cff1319d2fd2cbb7a1e84ccecf22c1cc07b24435cdb522f8c0aa525d6002a6","tgt_lang":"tr","translated":"Eylem","updated_at":"2026-07-12T06:43:47.715Z"}
@ -1643,6 +1645,7 @@
{"cache_key":"f0c5d1c142ff10671a3ebdf663234207259029c9ed18091c2e9aa3691d33daee","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.revision.preparing","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Preparing revision handoff","text_hash":"5287e6bef2d49751246bf986791a7301aac84c62be232d707210fc1abe74833f","tgt_lang":"tr","translated":"Revizyon devri hazırlanıyor","updated_at":"2026-07-12T06:42:12.959Z"}
{"cache_key":"f0cb3a1c01cac2de986410f7a45ff3030392e7073699433003588ae7e32546a7","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.empty.noProposalsBody","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"{agent} hasn't drafted any skill proposals.","text_hash":"499e6a82a2c1b11837a9b08d4ceb23ba0f9e0291b5d9cfb52337b23231400cde","tgt_lang":"tr","translated":"{agent} henüz herhangi bir skill önerisi hazırlamadı.","updated_at":"2026-07-12T06:42:29.259Z"}
{"cache_key":"f0f1faedff3bf0a596ac2bd36335aced8f48e14965e14d38566507612d6e2689","model":"gpt-5.6-sol","provider":"openai","segment_id":"skillWorkshop.selfLearning.pitchBody","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"OpenClaw reviews corrections and substantial completed runs, then drafts skill proposals for this board. It spends extra background tokens and every proposal waits for your review.","text_hash":"b06e460a44a232840a13f7cefdb87910f61da21ddafe0c9cc40eecb9be9e6757","tgt_lang":"tr","translated":"OpenClaw, düzeltmeleri ve tamamlanan kapsamlı çalıştırmaları inceler, ardından bu pano için beceri önerileri taslağı oluşturur. Ek arka plan token'ları harcar ve her öneri incelemenizi bekler.","updated_at":"2026-07-13T06:16:02.880Z"}
{"cache_key":"f0fccd607c28b7930351d02a9de8cbdf8105d04f5e3c71a8a429ef8db9435f50","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"tr","translated":"Terminale dosya ekle","updated_at":"2026-07-14T10:36:40.732Z"}
{"cache_key":"f145a0fd82e03ec842591b9f13ba1d8d1c88f30977aecf223caff81fcd366b4f","model":"claude-opus-4-8","provider":"anthropic","segment_id":"pluginsPage.connectorDescriptions.huggingFace","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Search models, datasets, and papers; run Spaces as tools.","text_hash":"033b3a261cea9e33efa7ce41e2c65c29d0a09c2e8bcc540290fdecbf5cbee354","tgt_lang":"tr","translated":"Modelleri, veri kümelerini ve makaleleri arayın; Spaces'i araç olarak çalıştırın.","updated_at":"2026-07-12T06:41:55.091Z"}
{"cache_key":"f14e1c2f3e836753a59f96d479b058a229c8630e2f4265b96296ab7b3649e4a0","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentTools.enableAll","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Enable All","text_hash":"87b3b5dda6254823c6bb59d3c280c56154f4e5fa463b4b4918fa28d46b89f1ee","tgt_lang":"tr","translated":"Tümünü Etkinleştir","updated_at":"2026-07-12T06:41:04.649Z"}
{"cache_key":"f17c622c498111ba2faee38d1a6d5105ba664bb3bda412a002871cc3115d8a25","model":"gpt-5.6-sol","provider":"openai","segment_id":"chat.workRun.workedForError","source_path":"ui/src/i18n/locales/tr.ts","src_lang":"en","text":"Worked for {duration}, includes errors.","text_hash":"66118efe01df30b774788c6b32fec5c0bff79a91c38f03c9e66d5a19b8b76538","tgt_lang":"tr","translated":"{duration} boyunca çalıştı, hatalar içeriyor.","updated_at":"2026-07-12T17:49:42.668Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:52.635Z",
"generatedAt": "2026-07-14T15:37:45.946Z",
"locale": "uk",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -194,6 +194,7 @@
{"cache_key":"19681f1c1e8ee2b10cd67537ff94d0715477adcc4df8f66f4cb2927146d4f25e","model":"gpt-5.5","provider":"openai","segment_id":"browser.newTab","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"New tab","text_hash":"1e08fda9c966d3bafb00c51e70935fad9f56990d4bfd0fdb70300ce15a60c7a6","tgt_lang":"uk","translated":"Нова вкладка","updated_at":"2026-07-11T02:19:15.248Z"}
{"cache_key":"1968676738d2619c7836dfddf65da13bb910bdfaa108c6752e8d517dd1141026","model":"claude-opus-4-8","provider":"anthropic","segment_id":"cron.detail.frequencySection","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Frequency","text_hash":"16b6668d9831a1b8d2d003496db6a62b7f525df6c556d7c04681fbed2251c845","tgt_lang":"uk","translated":"Частота","updated_at":"2026-07-12T06:50:17.822Z"}
{"cache_key":"1970b5179fa4461d4929b4d1e07bf902d8f32714cc0cdab798410a05ef940f7f","model":"claude-opus-4-8","provider":"anthropic","segment_id":"quickSettings.personal.avatarIssues.outsideWorkspace","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Outside workspace","text_hash":"993f0ebd3b3e492e86b0d64955cb5dc76359b3390e97863b22f5a94398b6b36e","tgt_lang":"uk","translated":"Поза робочою областю","updated_at":"2026-07-12T06:46:34.430Z"}
{"cache_key":"197ec91ddf1f8c2fb1890f2a52a94fafeb33f29f3701eb137f3fcc34e337134d","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"uk","translated":"Завантаження файлів…","updated_at":"2026-07-14T10:36:43.301Z"}
{"cache_key":"19827660639fcf5717cbcef01911056d62bea86215f23b3970b9cbe51bf260bc","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillsPage.acknowledgeRisk","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Acknowledge risk and install","text_hash":"22492375100f74cd283f0f80143eb70c1d46d05e2762834bd8563e77a9bf99da","tgt_lang":"uk","translated":"Визнати ризик і встановити","updated_at":"2026-07-12T06:47:52.017Z"}
{"cache_key":"19a8793a5d52e8b6ff0469dd6717a324541a12cff782f7f42a4c72b5f6af4b3a","model":"gpt-5.5","provider":"openai","segment_id":"chat.sessionDiff.loading","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Loading changes…","text_hash":"99f48f20532c48dcd9f2bfcd0f4d4ba230fb0396b320e67bdfa2f3383901fd1a","tgt_lang":"uk","translated":"Завантаження змін…","updated_at":"2026-07-11T04:53:21.654Z"}
{"cache_key":"19d523889b1ec1bdf605f523cefbe17db5b1bf08bf5913370d57a21c8d70f8ee","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentTools.enabledToolsOne","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"{count} Enabled Tool","text_hash":"6b7c073bcc6d38c855a575b7b9accc6de245038342adfcf08832ae876f80d049","tgt_lang":"uk","translated":"{count} увімкнений інструмент","updated_at":"2026-07-12T06:47:38.942Z"}
@ -1579,6 +1580,7 @@
{"cache_key":"db5082566479a3c5a6a0c532ee64b0741384b6f37822020168ad80b50537fe32","model":"claude-sonnet-4-6","provider":"anthropic","segment_id":"cron.suggestions.ideas.standupGhostwriter.prompt","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Draft my standup update from yesterday's commits, merged pull requests, and open review threads. Three bullets max: done, doing, blocked.","text_hash":"f579d93618226238ca346e3f109c798d24bf913c43f2ace07315fc0dfbb507cb","tgt_lang":"uk","translated":"Склади мій стендап-звіт на основі вчорашніх commits, змерджених pull request та відкритих review-тредів. Максимум три пункти: зроблено, роблю, заблоковано.","updated_at":"2026-07-11T22:47:26.603Z"}
{"cache_key":"db580dd99fd5d73ea39ec155684bc6e0ea58a5c9aa350d37d7ee5e457fa638a4","model":"gpt-5.6-sol","provider":"openai","segment_id":"connection.access.showToken","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Show token","text_hash":"2faef0ba40dc420f67de983b6c1be8f0f4b9b60f18409f2d2368b53b3c28a7bd","tgt_lang":"uk","translated":"Показати токен","updated_at":"2026-07-12T00:09:41.150Z"}
{"cache_key":"db5d8fca69427232500422a1a3e301c90bfff4852cf2167a5973e0e637df256e","model":"gpt-5","provider":"openai","segment_id":"usage.costWindows.perDay","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"/ day","text_hash":"122faff7033fbaa4fac55b95788a16f370e13ab272d734f33bfcf15021170fe7","tgt_lang":"uk","translated":"/ день","updated_at":"2026-07-05T20:24:32.108Z"}
{"cache_key":"dbbbf791b8f0b987bbccfca475a3c43c71a4aa27a377e1903894cc4075b9ef94","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"uk","translated":"Перетягніть файли, щоб додати їх","updated_at":"2026-07-14T10:36:43.301Z"}
{"cache_key":"dbfab650c6403878533c5d6f72c4c70f492649b188488224d303d8bc321bf40a","model":"claude-opus-4-8","provider":"anthropic","segment_id":"nodes.inventory.pendingApproval","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Pending approval","text_hash":"bb33a7f41817b38d13854b7f47501050851951e77bba690419fc75be5cd5a372","tgt_lang":"uk","translated":"Очікує підтвердження","updated_at":"2026-07-12T06:44:42.620Z"}
{"cache_key":"dc1a8378de543c5a5defe4e852329b686a204bada61be7a286e88a15e0c362e4","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.commands.instant","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"instant","text_hash":"618dc58379dda348eba010597accf72a98ab4cd357b42acdda4091901b2ff144","tgt_lang":"uk","translated":"миттєво","updated_at":"2026-07-12T06:49:42.713Z"}
{"cache_key":"dc22b597810446f1efea929b6ecf90bbd446c7379c2779f887d8ebc38b3ec6c7","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configPage.themeImported","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Imported {name}.","text_hash":"98cd11c4a9deee0133a5f4e24edf85a1c38c330a5c8a47628465e21cdc87ae4e","tgt_lang":"uk","translated":"Імпортовано {name}.","updated_at":"2026-07-12T06:46:39.786Z"}
@ -1587,6 +1589,7 @@
{"cache_key":"dc8278118dbc050b70fb48531beda379eaf64f53c14454dda10e990bab6057e1","model":"claude-opus-4-8","provider":"anthropic","segment_id":"dreaming.wiki.openConfig","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Open Config","text_hash":"63697308e9be76a975649e826a0640b5badf2e94f21a82af5e2c66c4a75889c4","tgt_lang":"uk","translated":"Відкрити конфігурацію","updated_at":"2026-07-12T06:49:42.713Z"}
{"cache_key":"dceed65a548412d3937b2e46a6fb544f68e60bf87ecb0cf8fcd8b0e9f32d79a8","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.categories.ai","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"AI & Agents","text_hash":"89e321609d70e936387221ba795c9c609c994fe27b4d5fe9fe226a95d6153e7e","tgt_lang":"uk","translated":"ШІ та агенти","updated_at":"2026-07-12T06:46:39.786Z"}
{"cache_key":"dd14db9b89ec146d7d78b32d2afd9aabaaa1771f984328273723abec401228af","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.sections.broadcast","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Broadcast","text_hash":"17bc9178343601795dbd6d0e4328dcade21e406e6514640250c79ac9317ee81a","tgt_lang":"uk","translated":"Трансляція","updated_at":"2026-07-12T06:46:44.532Z"}
{"cache_key":"dd14e41d1379efb2dbd005e22519115067d26fb1e28688222686265660670d74","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"uk","translated":"Додати файли до термінала","updated_at":"2026-07-14T10:36:43.301Z"}
{"cache_key":"dd19146565c25f16681c23abadc8ff54cee48f1b2d2a72fc51903fbe24b07991","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.ui.label","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"UI","text_hash":"7c32699ff595e13b5c1315db137593163f4e28052592c776bea23471139b2422","tgt_lang":"uk","translated":"UI","updated_at":"2026-07-12T06:45:55.278Z"}
{"cache_key":"ddb0e8362921662413473acd95bf9c60a7ee679a244a6830afcb2711a1d23d02","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.sections.cli","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"CLI","text_hash":"e759793341ff3757eaa76e814db0170ec13b6b0a988a742d9a81240c505f48ec","tgt_lang":"uk","translated":"CLI","updated_at":"2026-07-12T06:46:44.532Z"}
{"cache_key":"ddea3c1cbf0c0d06755e23d246656a6944923b5d0cc165a1e43f9c4e26c5c051","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.themes.dash.label","source_path":"ui/src/i18n/locales/uk.ts","src_lang":"en","text":"Dash","text_hash":"8c3ea2ea786aee267ed410e1043ac86787a47ffceba86efc59367dcb7df40f1b","tgt_lang":"uk","translated":"Dash","updated_at":"2026-07-12T06:46:50.031Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:53.523Z",
"generatedAt": "2026-07-14T15:37:46.409Z",
"locale": "vi",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -388,6 +388,7 @@
{"cache_key":"38fcc76d8edef283626ade0b143428df75359f2355ec395367f177ada5f9374f","model":"claude-opus-4-8","provider":"anthropic","segment_id":"channels.whatsapp.title","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"WhatsApp","text_hash":"6a40edf1fc87a29f243a7eefdbed57d19bfe16ab2e039d7ae1a44c097297e2f3","tgt_lang":"vi","translated":"WhatsApp","updated_at":"2026-07-12T06:51:22.816Z"}
{"cache_key":"3937a370a4335e7b1a33220a517da0d93320c51ac320c9353c96f1ab66f1fc18","model":"gpt-5.5","provider":"openai","segment_id":"nav.settingsGroupSystem","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"System","text_hash":"6725e7bbcd28f3a8a586fa34bf191fd72dde8b61756932cd3237c17a6f196f1a","tgt_lang":"vi","translated":"Hệ thống","updated_at":"2026-07-09T08:08:12.733Z"}
{"cache_key":"393ac9647c58627bc8c45fc9852b872b810dc746a5d9629f46a4b3b90b5923bc","model":"claude-sonnet-4-6","provider":"anthropic","segment_id":"cron.suggestions.ideas.watchdog.tagline","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Hourly health check with a one-line verdict.","text_hash":"8945cd3f1bc6620e14b68a1ad20929d38ef69de8915aecec9ef86339632957d1","tgt_lang":"vi","translated":"Kiểm tra sức khỏe hàng giờ với một dòng kết luận.","updated_at":"2026-07-11T23:00:01.923Z"}
{"cache_key":"393e0e560d4526221f926747ed7e0b8c7b98b18882164d4c31390e6bc72f26a7","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"vi","translated":"Thêm tệp vào terminal","updated_at":"2026-07-14T10:36:53.476Z"}
{"cache_key":"395e535e5594c4484880473c024e73da42879a09a5ad0917930ada63d3f511a0","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.toolCards.openDetails","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Open tool details in side panel","text_hash":"c6056b4228d222d66008f2ddf0d39980d4d451f1590b08a15999b629a32ff5db","tgt_lang":"vi","translated":"Mở chi tiết công cụ trong bảng bên","updated_at":"2026-07-12T06:56:54.544Z"}
{"cache_key":"395f0a1a22f4138b6723c376cc80f29995f9d081d406d24a512d6f46ac59bf8c","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillGroups.extra","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Extra Skills","text_hash":"1999b1716503a67377522c9416f5d2b2a424668ec761c5007655f0c8d284d686","tgt_lang":"vi","translated":"Skills Bổ sung","updated_at":"2026-07-12T06:54:42.571Z"}
{"cache_key":"397936ac5f7d70ca18a62e581f4322570037f0909e7356c81ac160cb18fadea6","model":"gpt-5.6-sol","provider":"openai","segment_id":"connection.access.hideToken","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Hide token","text_hash":"ae132305cb4bfbfe5508d7a36a29a914ce321156b8b2e26d5cbddd29d033c713","tgt_lang":"vi","translated":"Ẩn token","updated_at":"2026-07-12T00:10:47.384Z"}
@ -746,6 +747,7 @@
{"cache_key":"69743fe09d5ac14567f0ed94382fa2fe5015deed65b79ae75e8048d2e67aba23","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configPage.advanced","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Advanced","text_hash":"9f088dbebd6c3c70a5ddbc2c943b11e4ca9acea5757b0b4f2b32479f0dbb747e","tgt_lang":"vi","translated":"Nâng cao","updated_at":"2026-07-12T06:53:32.061Z"}
{"cache_key":"69ca0b8746e1374378103c38683bacd434f0740adae7efe5d4f7ccb74425b77f","model":"gpt-5.6-sol","provider":"openai","segment_id":"agentChip.agentSettings","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Agent settings","text_hash":"41cd6b4ee879e8ed1f6a41d0a77b75ddaadfdc0e17bc4e9b83f0055892facf3c","tgt_lang":"vi","translated":"Cài đặt agent","updated_at":"2026-07-13T10:57:42.215Z"}
{"cache_key":"69d4ad3c23584a52077f7eff106f8ce3f667aa05913aa9247ef8754d38ecbc53","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.appearance.themeLink","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Theme link or ID","text_hash":"5c6e9a2d22ee3070ff697719d1236c9381856b1737b511563084ffca7f74d797","tgt_lang":"vi","translated":"Liên kết hoặc ID giao diện","updated_at":"2026-07-12T06:53:57.127Z"}
{"cache_key":"6a00eefd2d3c5f1743f9c8bf7486683e76a8f388b56ec3a95c0ea0b81dff778a","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"vi","translated":"Thả tệp để thêm","updated_at":"2026-07-14T10:36:53.476Z"}
{"cache_key":"6a1dfde2a54a096bb1f9b0b16959ac1a081a91245bae12aecb9437a2c3434089","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.sections.wizard","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Setup Wizard","text_hash":"13d16249923201c79eafdacbbdfee6a1dbe87bf8345a30781c9aac334c406779","tgt_lang":"vi","translated":"Trình hướng dẫn thiết lập","updated_at":"2026-07-12T06:53:48.470Z"}
{"cache_key":"6a5d7bf5a9b8e2405eb89a6f1cc77918ceb5efd65ec7630f2e3c9f724f853115","model":"claude-opus-4-8","provider":"anthropic","segment_id":"nodes.execApprovals.options.off","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Off","text_hash":"ca7981b46ecf2c1787b6d76d81d9fd7fa0ca95842e2fcc2a452869891a9334d1","tgt_lang":"vi","translated":"Tắt","updated_at":"2026-06-17T14:17:26.553Z"}
{"cache_key":"6a852f3ea6296404d8ef1de96c0493185c0f644acf16e5535a5ad07eda9fbe1f","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.messages.activity","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Activity","text_hash":"38da1505ca8373288489495101b14f24ac95078f520ad64df18272aa6054f750","tgt_lang":"vi","translated":"Hoạt động","updated_at":"2026-07-12T06:56:39.707Z"}
@ -1754,6 +1756,7 @@
{"cache_key":"fb37a57c91e7fd88dc535561453f838523a3059f7c8f4040bea170e94371f36f","model":"gpt-5.5","provider":"openai","segment_id":"chat.backgroundTasks.collapse","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Collapse background tasks","text_hash":"e793371743248cb45412e03ad89929c99a0018f1c517a1d71f11bdc9c854f357","tgt_lang":"vi","translated":"Thu gọn tác vụ nền","updated_at":"2026-07-11T00:45:36.411Z"}
{"cache_key":"fb67030033dd67a9e139f6137af39f3e6fa454b5c8dfca6fac6c9cb0e3f2b4e6","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.workspaceFiles.readCount","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"{count} read","text_hash":"b3c6c64f1153fb7b2672d2894f532d3f7adea1dd1c473363587fc520be35998e","tgt_lang":"vi","translated":"{count} đã đọc","updated_at":"2026-06-16T14:17:25.260Z"}
{"cache_key":"fb6f9783a3027b616b05081edb2fa88bb37c8e7731e8174bc503cb40f86857a4","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.cli.label","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"CLI","text_hash":"e759793341ff3757eaa76e814db0170ec13b6b0a988a742d9a81240c505f48ec","tgt_lang":"vi","translated":"CLI","updated_at":"2026-07-12T06:53:04.214Z"}
{"cache_key":"fb75dde627fb3c506bb6508c5ff04516f92da046b165b9dfd9467273751a4465","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"vi","translated":"Đang tải tệp lên…","updated_at":"2026-07-14T10:36:53.476Z"}
{"cache_key":"fbe7507469319c05bcfbd615f6df59ebbd682e249f4a7dfbabb6419013c5ee3e","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.emptyFilteredHint","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Change the view, search, priority, agent, or archive filter.","text_hash":"049dfae940263ace9707334af06b298c1223c38a449b1cec5a712553badebbd0","tgt_lang":"vi","translated":"Thay đổi chế độ xem, tìm kiếm, mức ưu tiên, agent, hoặc bộ lọc lưu trữ.","updated_at":"2026-06-17T14:17:32.599Z"}
{"cache_key":"fbef58c1dcd91cb77eb0400365ab0f8ea65fa512a8428670a07764532a69554b","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.header.board","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Board","text_hash":"4816cbfd74aa8297b9c9cdaae89e2f0d2ced6041e952dfcd114e01b4c82e9c6d","tgt_lang":"vi","translated":"Bảng","updated_at":"2026-07-12T06:55:29.228Z"}
{"cache_key":"fbf53ace5332bdbf9b6864979d5f9eff4a810f2bc7efad7e9468cfddcf6dc93e","model":"gpt-5.6-sol","provider":"openai","segment_id":"subtitles.connection","source_path":"ui/src/i18n/locales/vi.ts","src_lang":"en","text":"Gateway endpoint, credentials, and handshake status.","text_hash":"5d6324ca52f899e2db988c9a0b14314fe2240f17cb129b8ff2bf16bf87bef2e7","tgt_lang":"vi","translated":"Điểm cuối Gateway, thông tin xác thực và trạng thái bắt tay.","updated_at":"2026-07-12T00:10:47.384Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:49.429Z",
"generatedAt": "2026-07-14T15:37:44.428Z",
"locale": "zh-CN",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -821,6 +821,7 @@
{"cache_key":"755586a37db45f212d47392a911664b766cc70f9d1dc823493379d790fb2612b","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.search","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Search settings","text_hash":"255b076dd82855431a4ce9a722d77d41f47755ab11be14fc686fd71415cdeef0","tgt_lang":"zh-CN","translated":"搜索设置","updated_at":"2026-07-12T06:27:11.226Z"}
{"cache_key":"757a9ffbe8d769e1eaa5cebd7cd40e0249171994dc6e8d172204d9cbd8d04c56","model":"gpt-5.6-sol","provider":"openai","segment_id":"channels.setup.doneBody","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Configuration saved. The gateway reloads the channel automatically; check its card for live status.","text_hash":"752caa1598003a22472698b267be1e0c4f3dd4fb3edaa63d40d4de93b134a0d4","tgt_lang":"zh-CN","translated":"配置已保存。Gateway 会自动重新加载该渠道;请查看其卡片以了解实时状态。","updated_at":"2026-07-13T16:51:05.582Z"}
{"cache_key":"75de6d18c652f64ed90c256fcd715d7f5bd61f857c212304753b0e77ea1d9d5a","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.sessions","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Terminal sessions","text_hash":"467e76a9fd4306fcbfa5eef95e0bd91baab63bc7005df93153390649ca94bdbe","tgt_lang":"zh-CN","translated":"终端会话","updated_at":"2026-07-14T12:25:58.197Z"}
{"cache_key":"75f19538f2c07881069e4cd90812bc62c8d223093570dc0464a909a9eeddaf7e","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"zh-CN","translated":"将文件添加到终端","updated_at":"2026-07-14T10:35:44.171Z"}
{"cache_key":"761e6577b676d0388588a137089af0398f3aa26f85de8e73cc339a207a6bc3cb","model":"claude-opus-4-8","provider":"anthropic","segment_id":"pluginsPage.connectorDescriptions.huggingFace","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Search models, datasets, and papers; run Spaces as tools.","text_hash":"033b3a261cea9e33efa7ce41e2c65c29d0a09c2e8bcc540290fdecbf5cbee354","tgt_lang":"zh-CN","translated":"搜索模型、数据集和论文;将 Spaces 作为工具运行。","updated_at":"2026-07-12T06:28:10.634Z"}
{"cache_key":"765a7570411c3556d08b75440efbba2a1645dfb72ca61c46b3dab5a3f9aa2eec","model":"gpt-5.6-sol","provider":"openai","segment_id":"skillWorkshop.selfLearning.pitchBody","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"OpenClaw reviews corrections and substantial completed runs, then drafts skill proposals for this board. It spends extra background tokens and every proposal waits for your review.","text_hash":"b06e460a44a232840a13f7cefdb87910f61da21ddafe0c9cc40eecb9be9e6757","tgt_lang":"zh-CN","translated":"OpenClaw 会审查更正内容和已完成的重要运行,然后为此看板起草技能提案。此过程会消耗额外的后台令牌,并且每项提案都需等待你的审查。","updated_at":"2026-07-13T06:15:06.600Z"}
{"cache_key":"76a0ddd8d5c28bf64fc12e160ebf61d0f141d5017a13fd371806d43c63ac3274","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agentTools.session","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Current Session","text_hash":"386c79325aa5aa229d63169fafb6c4642e2c413ddf6efd5df5a9dc75f0c01165","tgt_lang":"zh-CN","translated":"当前会话","updated_at":"2026-07-12T06:27:28.537Z"}
@ -909,6 +910,7 @@
{"cache_key":"83daedef96d3df47046bb323986dc227cf73d4d94a5f3aea425878c1e8e0372a","model":"gpt-5.6-sol","provider":"openai","segment_id":"chat.progressLabels.krilling","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Krilling","text_hash":"7f0a603d5a401abe0bbee42f146cee43eaa40850b30815c9853c774d71bcc06d","tgt_lang":"zh-CN","translated":"磷虾游动中","updated_at":"2026-07-14T04:52:48.651Z"}
{"cache_key":"83e6a198426627d98dd2adbe8d10a3d1c73dd13e687b6871f47be3d886545d25","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.healthStale","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"stale","text_hash":"a03f2386ae06b21109577020844df367857b72c2fcce384c1896fed98a89c82b","tgt_lang":"zh-CN","translated":"已过期","updated_at":"2026-06-17T14:13:17.789Z"}
{"cache_key":"840ca403978877c8b14458eee7cbc5fe3e3ccb91cf332de222d4eaa2acf6bdd0","model":"claude-opus-4-8","provider":"anthropic","segment_id":"nodes.execApprovals.autoAllowSkills","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Auto-allow skill CLIs","text_hash":"4178d09139bee5d793a0f2bbd9864f4eb02cb6ebad7f9803b4d3ccbd922b385a","tgt_lang":"zh-CN","translated":"自动允许 skill CLI","updated_at":"2026-07-12T06:25:34.328Z"}
{"cache_key":"841197790b1a99403e805eb11f670f43336ceec10a05640d6c8a69d77546374e","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"zh-CN","translated":"正在上传文件…","updated_at":"2026-07-14T10:35:44.171Z"}
{"cache_key":"84236818e6010d8d9d617fbe9d4cabcdcb2f96525bf35ca5554c1de8e3f375e4","model":"gpt-5","provider":"openai","segment_id":"codexSessions.title","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Sessions across your computers","text_hash":"23b30c777a12daeb3e5471cd51530189b621db9fdec4e6ea976e5a97516fac22","tgt_lang":"zh-CN","translated":"所有电脑上的会话","updated_at":"2026-07-09T10:01:43.701Z"}
{"cache_key":"84458f6936f3dd9319ed96d6a7a203013ed6538c5c85003073c2723335337d06","model":"claude-opus-4-8","provider":"anthropic","segment_id":"quickSettings.security.title","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Security","text_hash":"8f6fb4eb7f42c0e245e29e63f5b82cc3ba19852681d1ed9aed291f59cf75ec0e","tgt_lang":"zh-CN","translated":"安全","updated_at":"2026-07-12T06:26:29.379Z"}
{"cache_key":"847af1a927fa455ca46dbb4aa45ced05520eb59a5e4a4961978c2ae1e27c97c8","model":"claude-opus-4-8","provider":"anthropic","segment_id":"workboard.viewPreset","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Workboard view","text_hash":"cc2b05179ad742029156bb45578e880c46599fd28e1c2ab66f5a6f9e7f8fa08e","tgt_lang":"zh-CN","translated":"工作板视图","updated_at":"2026-06-17T14:13:12.872Z"}
@ -1078,6 +1080,7 @@
{"cache_key":"9dbca5199be3faa2f32c0b0cbe6dbec95d064c47e52bddf82e696cd703fcf017","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.empty.staleTitle","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"No stale proposals","text_hash":"25b0c88fbfe8b10fdf21af3c5a2970c0576750c9d5990ac0106d61accfb73d78","tgt_lang":"zh-CN","translated":"没有过期的提案","updated_at":"2026-07-12T06:28:31.142Z"}
{"cache_key":"9df04f62aad41195b81ed3eb222cdfe7e97b9eb68b0dbb0636598658e6508c06","model":"gpt-5","provider":"openai","segment_id":"codexSessions.subtitle","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"A read-only view of Codex sessions on this gateway and every connected computer that shares them.","text_hash":"ea7ea85488243bacdbe28edb2fba0617ec90ebcf587f8ecce6f62858ca85aed4","tgt_lang":"zh-CN","translated":"以只读方式查看此 Gateway 和所有已连接且启用会话共享的电脑上的 Codex 会话。","updated_at":"2026-07-09T10:01:43.701Z"}
{"cache_key":"9df70d65c0a7d1e9a686bc454d0fad582310d4d8eb2cbd92522f79545f899e31","model":"gpt-5.5","provider":"openai","segment_id":"chat.composer.systemDefaultMicrophone","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"System default","text_hash":"b0459211f9f76871059135050a2afd9a01e7e41dc32ea58006c51483b9ceab6d","tgt_lang":"zh-CN","translated":"系统默认","updated_at":"2026-07-06T17:33:17.802Z"}
{"cache_key":"9e0aa46ddec97ead7dadb89a82704e5ae7ee4dcaaa25082eed7b02b3a72e0949","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"zh-CN","translated":"拖放文件以添加","updated_at":"2026-07-14T10:35:44.171Z"}
{"cache_key":"9e1a8bdc693db6a4271890918a445d58df87e03b5096f48fdcad472286700bd7","model":"claude-opus-4-8","provider":"anthropic","segment_id":"cron.tabs.paused","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Paused","text_hash":"e159b06187d369a0615f66ce577582b5c983d4ea59b3a62b702049f61753f0bf","tgt_lang":"zh-CN","translated":"已暂停","updated_at":"2026-07-12T06:29:22.604Z"}
{"cache_key":"9e3364c43984ce8fc652279216a9d6690d66b75b52bcd0acd8b3a33465ed0a99","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.detailPanel.copyPath","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Copy path","text_hash":"720ff4160412b943370afdb8fc1c082ff057d54713d5fb4b4b7a9634bfabf5fe","tgt_lang":"zh-CN","translated":"复制路径","updated_at":"2026-06-16T14:13:09.659Z"}
{"cache_key":"9e6b3c33a9bc55d4d5455deb9ae5a09be359ce41e6f6c74307a45dd21d0fb4ae","model":"claude-opus-4-8","provider":"anthropic","segment_id":"cron.form.promptPlaceholder","source_path":"ui/src/i18n/locales/zh-CN.ts","src_lang":"en","text":"Describe what OpenClaw should do...","text_hash":"81afbe360be2d62d23ea39306a351c9b95b2d9a5a653c7469343454dc2ac706b","tgt_lang":"zh-CN","translated":"描述 OpenClaw 应执行的操作……","updated_at":"2026-07-12T06:29:33.424Z"}

View file

@ -1,11 +1,11 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-14T14:29:50.052Z",
"generatedAt": "2026-07-14T15:37:44.558Z",
"locale": "zh-TW",
"model": "claude-opus-4-6",
"provider": "anthropic",
"sourceHash": "9403f57b504fce2f2f912d47a4c94ed0175d4d7041e17cdac28b6dda1cef743b",
"totalKeys": 3339,
"translatedKeys": 3339,
"sourceHash": "778cf22166ab57460b9473fecf190f1b1eaf6b1fcf28d63d2c32e8e1086effe1",
"totalKeys": 3342,
"translatedKeys": 3342,
"workflow": 1
}

View file

@ -582,6 +582,7 @@
{"cache_key":"5908515aa8604870d9515a93841699ccd7e7e82b7c03d86c5c63ff91735fb08e","model":"gpt-5.5","provider":"openai","segment_id":"tabs.skillWorkshop","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Skill Workshop","text_hash":"3912c65bdd0a43563438762a43ecbd4b14637844a18decbf9249df73d21152a0","tgt_lang":"zh-TW","translated":"Skill Workshop","updated_at":"2026-05-31T21:48:14.460Z"}
{"cache_key":"590958b237f600f33af473b78a9fccce764a65c1ca8ab045f9c12eee3bfffaa1","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configPage.channels.discord","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Discord","text_hash":"053bc65874ad6098e58c41c57b378a2f36b0220e5e0b46722245e6c2f796818c","tgt_lang":"zh-TW","translated":"Discord","updated_at":"2026-07-12T06:27:20.413Z"}
{"cache_key":"591d2f124ed23f115f6b99ee1660428d31dad2c1a1b9414ccd2442fc143d52d1","model":"gpt-5.6-sol","provider":"openai","segment_id":"palette.items.skills","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Skills","text_hash":"66d0f523a379b2de6f8d5fba3a817ebc395f7bcaa54cc132ca9dfa665d1e9378","tgt_lang":"zh-TW","translated":"Skills","updated_at":"2026-07-12T00:07:58.605Z"}
{"cache_key":"593adcc26db0b9c94c1375c1c1484f107741373da831b7c190aa15249b28007c","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.uploading","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Uploading files…","text_hash":"b6abaa85b27a9246f54cfcb2da1ceeeae3713a5347312e93d48e3bd050ecd677","tgt_lang":"zh-TW","translated":"正在上傳檔案…","updated_at":"2026-07-14T10:35:46.802Z"}
{"cache_key":"593e37c0b374b4a001a6434396f4e874eb76e893f0e9059d81d26fc3927bb497","model":"gpt-5.6-sol","provider":"openai","segment_id":"connection.snapshot.uptime","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Uptime","text_hash":"d63ab4711473b0398feb4b56622605d5d2ec7ecd3b1bb5070a7dd56de96aaf88","tgt_lang":"zh-TW","translated":"運作時間","updated_at":"2026-07-12T00:07:56.964Z"}
{"cache_key":"594addbe90f4ca515ecc3cc7ab97324b39902419329a201a2f1da58375e2e1b4","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.tools.description","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Tool configurations (browser, search, etc.)","text_hash":"c6b511cba17797436a0156533fb1342a26e2540d80dc0739ce3c7a0e1086eda0","tgt_lang":"zh-TW","translated":"工具設定(瀏覽器、搜尋等)","updated_at":"2026-07-12T06:26:43.125Z"}
{"cache_key":"598cd1e23397a4703d3d8942f4c2cee907c7dbc3421bc26d695bca4c02e1f138","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.today.reviewed","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"REVIEWED","text_hash":"5796063a0ef442e00cd95cc618296d1b6f07126e9a54d58df31324f88e8bbae4","tgt_lang":"zh-TW","translated":"已審查","updated_at":"2026-07-12T06:29:23.295Z"}
@ -1733,6 +1734,7 @@
{"cache_key":"f80b32fa6344ac7f7d9bc89b31388a035bfcaa83134424a80a11f288c5e82b39","model":"claude-opus-4-8","provider":"anthropic","segment_id":"pluginsPage.connectorDescriptions.stripe","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Check payments, customers, invoices, and subscriptions in your Stripe account.","text_hash":"c7b95e41ed5cd122a64d50a1aba6d91be09b628e49cb905205098e3c23e39cbf","tgt_lang":"zh-TW","translated":"在您的 Stripe 帳戶中查看付款、客戶、發票和訂閱。","updated_at":"2026-07-12T06:28:46.807Z"}
{"cache_key":"f848f81e7ac31fe92a6c6ce14feaaafa93fd66066c83ef0767e51cccceabd0c8","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configView.rawTitle","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Edit raw JSON/JSON5 config","text_hash":"d6ecf3de8d568e401bc5e1adeb0b9e2fb2c0a12b3d222c01616a69604616b03d","tgt_lang":"zh-TW","translated":"編輯原始 JSON/JSON5 設定","updated_at":"2026-07-12T06:27:49.255Z"}
{"cache_key":"f8881cc455670b7aae035c724a7637430183088ed3077da612a6a14d52f3d798","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillWorkshop.actions.apply","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Apply","text_hash":"31e392d1c0378beca611de66c0f4c71cba29159905cc54242d9bddee5b23d851","tgt_lang":"zh-TW","translated":"套用","updated_at":"2026-07-12T06:29:06.779Z"}
{"cache_key":"f8955831e58d4df3f7b0feb8e8fb15809aa357acab15d8458efc719c6c38929d","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.dropFiles","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Drop files to add them","text_hash":"3b24f0eb074467b459379a0c9e5c28a8d7ce2094cc9528e07e7bfc4369cbd2ac","tgt_lang":"zh-TW","translated":"拖放檔案以加入","updated_at":"2026-07-14T10:35:46.802Z"}
{"cache_key":"f925df5b3d1a997ccdbb0d988731d80f07661df2cd43b25bd36be6f1a48bcd95","model":"claude-opus-4-8","provider":"anthropic","segment_id":"agents.toolCatalog.groups.automation","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Automation","text_hash":"d909750b1bbb71a39b6330ba8f81f4f8f6e889ed96d7ab366e74857909750c64","tgt_lang":"zh-TW","translated":"自動化","updated_at":"2026-06-16T14:12:59.400Z"}
{"cache_key":"f92d8c5d7be48c8e2ca2faecbddeb1b5207640c9164f842d22750898857f5265","model":"gpt-5.5","provider":"openai","segment_id":"tasksPage.recent","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Recent","text_hash":"690dbe9dc0993c4256683738fc3fd541cfa96f60d299be33343615dd58179d93","tgt_lang":"zh-TW","translated":"最近","updated_at":"2026-07-06T08:41:46.878Z"}
{"cache_key":"f934b131216e8eddea8e0e17b6513c8e7416569ff05fe70d390df764fc8469fb","model":"claude-opus-4-8","provider":"anthropic","segment_id":"mcpPage.mtls","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"mTLS","text_hash":"5947b487dfb48ee1423d1dc99240bcd3e9df712799f82eeeb6dfda02060fcad6","tgt_lang":"zh-TW","translated":"mTLS","updated_at":"2026-07-12T06:28:46.806Z"}
@ -1790,6 +1792,7 @@
{"cache_key":"ff53b006b8b59455c25bc439000347b28478b02017ca4bcc1a88913c19f94736","model":"gpt-5.6-sol","provider":"openai","segment_id":"agentTools.catalogTitle","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Tool Catalog","text_hash":"82939e474e14d367f6f4a73f9ad684a209288c5711987c03ffa8297bcbde093e","tgt_lang":"zh-TW","translated":"工具目錄","updated_at":"2026-07-13T16:00:13.734Z"}
{"cache_key":"ff5c2bc5153d6ee110428300318d53cc19b611cffd09189acec0d896436cbbd9","model":"claude-opus-4-8","provider":"anthropic","segment_id":"skillGroups.installed","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Installed Skills","text_hash":"ed416e3fcb42c129b89f4110a1da28214ff6bcffe33e965d94e9f869511e5b70","tgt_lang":"zh-TW","translated":"已安裝 Skills","updated_at":"2026-07-12T06:28:22.466Z"}
{"cache_key":"ff69fe1f27b8e4bd8341feb7c0bbb3b65df82fbbb2ca8d833135583360d4b704","model":"claude-opus-4-8","provider":"anthropic","segment_id":"chat.pullRequests.checksRunning","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Running","text_hash":"f4ccae29e1bb0c20a124570a1b43f4347ea94bba9f84ffdfddd9c7445b126128","tgt_lang":"zh-TW","translated":"執行中","updated_at":"2026-06-17T14:13:17.815Z"}
{"cache_key":"ff6fde0d6e764b26e7eddf529592ab0c47ed17c129481fb4ba0f03479f8a78f0","model":"gpt-5.6-sol","provider":"openai","segment_id":"terminal.addFiles","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Add files to terminal","text_hash":"6e3f2a4464ccdd60563830915b635c008c5d1c765a5e626e8bc946c8d64e6fe6","tgt_lang":"zh-TW","translated":"將檔案加入終端機","updated_at":"2026-07-14T10:35:46.802Z"}
{"cache_key":"ff8f574579879461440d3aa1bbd0d6a6ec53403b24f99026212504d69b5eeb6f","model":"claude-opus-4-8","provider":"anthropic","segment_id":"mcpPage.toolFilter","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"tool filter","text_hash":"582d4e652116255489fe370ee55ed30d12d28f988c625448f9eb54fa3aaf55ee","tgt_lang":"zh-TW","translated":"工具篩選器","updated_at":"2026-07-12T06:28:46.806Z"}
{"cache_key":"ffe56c34291ae35d964efcb2ce0cd59183897195b2767aee8b88b9f09bd8f171","model":"claude-opus-4-8","provider":"anthropic","segment_id":"configForm.sections.auth.label","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"Authentication","text_hash":"66880d2d8216260d201917a72eb245440ef18ba9b54c070ee39aa4c343ae126f","tgt_lang":"zh-TW","translated":"驗證","updated_at":"2026-07-12T06:26:43.125Z"}
{"cache_key":"ffef7a965dc0114fdccd8d5fe4a70d5913d0faf610cde25224bc2685335597ac","model":"gpt-5.6-sol","provider":"openai","segment_id":"nodes.inventory.summaryConnected","source_path":"ui/src/i18n/locales/zh-TW.ts","src_lang":"en","text":"{connected} of {total} connected","text_hash":"920cc846e8f27ae7f2a95f6089c382579fd774894df86b31d10fd69e4c165758","tgt_lang":"zh-TW","translated":"已連線 {connected}/{total}","updated_at":"2026-07-13T05:07:15.939Z"}

View file

@ -1579,6 +1579,9 @@ export const ar: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "إضافة ملفات إلى الطرفية",
dropFiles: "أفلِت الملفات لإضافتها",
uploading: "جارٍ رفع الملفات…",
closeSession: "Close terminal session",
sessions: "جلسات الطرفية",
refreshSessions: "تحديث",

View file

@ -1600,6 +1600,9 @@ export const de: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "Dateien zum Terminal hinzufügen",
dropFiles: "Dateien hier ablegen, um sie hinzuzufügen",
uploading: "Dateien werden hochgeladen…",
closeSession: "Close terminal session",
sessions: "Terminalsitzungen",
refreshSessions: "Aktualisieren",

View file

@ -1552,6 +1552,9 @@ export const en: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "Add files to terminal",
dropFiles: "Drop files to add them",
uploading: "Uploading files…",
closeSession: "Close terminal session",
sessions: "Terminal sessions",
refreshSessions: "Refresh",

View file

@ -1598,6 +1598,9 @@ export const es: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "Añadir archivos al terminal",
dropFiles: "Suelta los archivos para añadirlos",
uploading: "Subiendo archivos…",
closeSession: "Close terminal session",
sessions: "Sesiones de terminal",
refreshSessions: "Actualizar",

View file

@ -1588,6 +1588,9 @@ export const fa: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "افزودن فایل‌ها به ترمینال",
dropFiles: "برای افزودن، فایل‌ها را اینجا رها کنید",
uploading: "در حال بارگذاری فایل‌ها…",
closeSession: "Close terminal session",
sessions: "نشست‌های ترمینال",
refreshSessions: "تازه‌سازی",

View file

@ -1607,6 +1607,9 @@ export const fr: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "Ajouter des fichiers au terminal",
dropFiles: "Déposez des fichiers pour les ajouter",
uploading: "Téléversement des fichiers…",
closeSession: "Close terminal session",
sessions: "Sessions de terminal",
refreshSessions: "Actualiser",

View file

@ -1579,6 +1579,9 @@ export const hi: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "टर्मिनल में फ़ाइलें जोड़ें",
dropFiles: "फ़ाइलें जोड़ने के लिए उन्हें यहाँ छोड़ें",
uploading: "फ़ाइलें अपलोड की जा रही हैं…",
closeSession: "Close terminal session",
sessions: "टर्मिनल सत्र",
refreshSessions: "रिफ्रेश करें",

View file

@ -1589,6 +1589,9 @@ export const id: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "Tambahkan file ke terminal",
dropFiles: "Letakkan file untuk menambahkannya",
uploading: "Mengunggah file…",
closeSession: "Close terminal session",
sessions: "Sesi terminal",
refreshSessions: "Muat ulang",

View file

@ -1603,6 +1603,9 @@ export const it: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "Aggiungi file al terminale",
dropFiles: "Trascina qui i file per aggiungerli",
uploading: "Caricamento dei file…",
closeSession: "Close terminal session",
sessions: "Sessioni del terminale",
refreshSessions: "Aggiorna",

View file

@ -1596,6 +1596,9 @@ export const ja_JP: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "ターミナルにファイルを追加",
dropFiles: "ファイルをドロップして追加",
uploading: "ファイルをアップロード中…",
closeSession: "Close terminal session",
sessions: "ターミナルセッション",
refreshSessions: "更新",

View file

@ -1583,6 +1583,9 @@ export const ko: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "터미널에 파일 추가",
dropFiles: "파일을 추가하려면 여기에 놓으세요",
uploading: "파일을 업로드하는 중…",
closeSession: "Close terminal session",
sessions: "터미널 세션",
refreshSessions: "새로고침",

View file

@ -1596,6 +1596,9 @@ export const nl: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "Bestanden toevoegen aan terminal",
dropFiles: "Sleep bestanden hierheen om ze toe te voegen",
uploading: "Bestanden uploaden…",
closeSession: "Close terminal session",
sessions: "Terminalsessies",
refreshSessions: "Vernieuwen",

View file

@ -1596,6 +1596,9 @@ export const pl: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "Dodaj pliki do terminala",
dropFiles: "Upuść pliki, aby je dodać",
uploading: "Przesyłanie plików…",
closeSession: "Close terminal session",
sessions: "Sesje terminala",
refreshSessions: "Odśwież",

View file

@ -1591,6 +1591,9 @@ export const pt_BR: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "Adicionar arquivos ao terminal",
dropFiles: "Solte os arquivos para adicioná-los",
uploading: "Enviando arquivos…",
closeSession: "Close terminal session",
sessions: "Sessões de terminal",
refreshSessions: "Atualizar",

View file

@ -1600,6 +1600,9 @@ export const ru: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "Добавить файлы в терминал",
dropFiles: "Перетащите файлы, чтобы добавить их",
uploading: "Загрузка файлов…",
closeSession: "Close terminal session",
sessions: "Сеансы терминала",
refreshSessions: "Обновить",

View file

@ -1570,6 +1570,9 @@ export const th: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "เพิ่มไฟล์ไปยังเทอร์มินัล",
dropFiles: "วางไฟล์เพื่อเพิ่ม",
uploading: "กำลังอัปโหลดไฟล์…",
closeSession: "Close terminal session",
sessions: "เซสชันเทอร์มินัล",
refreshSessions: "รีเฟรช",

View file

@ -1595,6 +1595,9 @@ export const tr: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "Terminale dosya ekle",
dropFiles: "Eklemek için dosyaları buraya bırakın",
uploading: "Dosyalar yükleniyor…",
closeSession: "Close terminal session",
sessions: "Terminal oturumları",
refreshSessions: "Yenile",

View file

@ -1596,6 +1596,9 @@ export const uk: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "Додати файли до термінала",
dropFiles: "Перетягніть файли, щоб додати їх",
uploading: "Завантаження файлів…",
closeSession: "Close terminal session",
sessions: "Сеанси термінала",
refreshSessions: "Оновити",

View file

@ -1590,6 +1590,9 @@ export const vi: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "Thêm tệp vào terminal",
dropFiles: "Thả tệp để thêm",
uploading: "Đang tải tệp lên…",
closeSession: "Close terminal session",
sessions: "Các phiên terminal",
refreshSessions: "Làm mới",

View file

@ -1561,6 +1561,9 @@ export const zh_CN: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "将文件添加到终端",
dropFiles: "拖放文件以添加",
uploading: "正在上传文件…",
closeSession: "Close terminal session",
sessions: "终端会话",
refreshSessions: "刷新",

View file

@ -1562,6 +1562,9 @@ export const zh_TW: TranslationMap = {
hide: "Hide terminal",
resize: "Resize terminal panel",
newSession: "New terminal session",
addFiles: "將檔案加入終端機",
dropFiles: "拖放檔案以加入",
uploading: "正在上傳檔案…",
closeSession: "Close terminal session",
sessions: "終端機工作階段",
refreshSessions: "重新整理",