mirror of
https://github.com/anomalyco/opencode.git
synced 2026-09-24 17:47:34 +00:00
Compare commits
33
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6051a67bc2 | ||
|
|
ad53e39d2e | ||
|
|
3ddfc15df5 | ||
|
|
ac2426e103 | ||
|
|
0bc8b8dbeb | ||
|
|
dca73ba9e3 | ||
|
|
318a8c1aba | ||
|
|
bee5014f89 | ||
|
|
8652729fdb | ||
|
|
bfcaf1b0cd | ||
|
|
f24fdeca70 | ||
|
|
dc48655743 | ||
|
|
ab52135b4e | ||
|
|
e31f78af78 | ||
|
|
bc3669b97f | ||
|
|
7460d855ac | ||
|
|
683d470fe4 | ||
|
|
ef4938d344 | ||
|
|
b098b0e06f | ||
|
|
27dfac3d36 | ||
|
|
5253661d36 | ||
|
|
ff6b8c21e7 | ||
|
|
8e39040eed | ||
|
|
95cfca73b0 | ||
|
|
f0aff6cfe8 | ||
|
|
b7d707cd64 | ||
|
|
b486652067 | ||
|
|
7d1e212fb5 | ||
|
|
2c369a21c9 | ||
|
|
f2e73dd03f | ||
|
|
88a9688c9c | ||
|
|
8d5eb3bf9c | ||
|
|
6e0857cc0e |
@@ -32,7 +32,7 @@
|
||||
},
|
||||
"packages/ai": {
|
||||
"name": "@opencode/ai",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@aws-sdk/credential-providers": "3.1057.0",
|
||||
"@opencode/schema": "workspace:*",
|
||||
@@ -54,7 +54,7 @@
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@opencode/app",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@corvu/drawer": "catalog:",
|
||||
"@dnd-kit/abstract": "0.5.0",
|
||||
@@ -112,7 +112,7 @@
|
||||
},
|
||||
"packages/cli": {
|
||||
"name": "@opencode/cli",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode.cjs",
|
||||
"opencode2": "./bin/opencode2.cjs",
|
||||
@@ -177,7 +177,7 @@
|
||||
},
|
||||
"packages/client": {
|
||||
"name": "@opencode/client",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@opencode/protocol": "workspace:*",
|
||||
"@opencode/schema": "workspace:*",
|
||||
@@ -203,7 +203,7 @@
|
||||
},
|
||||
"packages/codemode": {
|
||||
"name": "@opencode/codemode",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"acorn": "8.15.0",
|
||||
"effect": "catalog:",
|
||||
@@ -216,7 +216,7 @@
|
||||
},
|
||||
"packages/console/app": {
|
||||
"name": "@opencode/console-app",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@ibm/plex": "6.4.1",
|
||||
@@ -252,7 +252,7 @@
|
||||
},
|
||||
"packages/console/core": {
|
||||
"name": "@opencode/console-core",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sts": "3.782.0",
|
||||
"@jsx-email/render": "1.1.1",
|
||||
@@ -279,7 +279,7 @@
|
||||
},
|
||||
"packages/console/function": {
|
||||
"name": "@opencode/console-function",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@openauthjs/openauth": "0.0.0-20250322224806",
|
||||
"@opencode/console-core": "workspace:*",
|
||||
@@ -296,7 +296,7 @@
|
||||
},
|
||||
"packages/console/mail": {
|
||||
"name": "@opencode/console-mail",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
@@ -320,7 +320,7 @@
|
||||
},
|
||||
"packages/console/support": {
|
||||
"name": "@opencode/console-support",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@opencode/console-core": "workspace:*",
|
||||
@@ -340,7 +340,7 @@
|
||||
},
|
||||
"packages/core": {
|
||||
"name": "@opencode/core",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@ai-sdk/cohere": "3.0.27",
|
||||
"@ai-sdk/gateway": "3.0.104",
|
||||
@@ -368,7 +368,7 @@
|
||||
"drizzle-orm": "catalog:",
|
||||
"effect": "catalog:",
|
||||
"fuzzysort": "3.1.0",
|
||||
"gitlab-ai-provider": "6.16.0",
|
||||
"gitlab-ai-provider": "6.18.0",
|
||||
"google-auth-library": "10.5.0",
|
||||
"gray-matter": "4.0.3",
|
||||
"htmlparser2": "8.0.2",
|
||||
@@ -408,7 +408,7 @@
|
||||
},
|
||||
"packages/desktop": {
|
||||
"name": "@opencode/desktop",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@zip.js/zip.js": "2.7.62",
|
||||
"electron-context-menu": "5.0.0",
|
||||
@@ -457,7 +457,7 @@
|
||||
},
|
||||
"packages/enterprise": {
|
||||
"name": "@opencode/enterprise",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@hono/standard-validator": "catalog:",
|
||||
"@opencode-ai/sdk": "1.18.21",
|
||||
@@ -494,7 +494,7 @@
|
||||
},
|
||||
"packages/function": {
|
||||
"name": "@opencode/function",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@octokit/auth-app": "8.0.1",
|
||||
"@octokit/rest": "catalog:",
|
||||
@@ -510,7 +510,7 @@
|
||||
},
|
||||
"packages/http-recorder": {
|
||||
"name": "@opencode/http-recorder",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@effect/platform-node-shared": "4.0.0-rc.112",
|
||||
},
|
||||
@@ -529,7 +529,7 @@
|
||||
},
|
||||
"packages/httpapi-codegen": {
|
||||
"name": "@opencode/httpapi-codegen",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"effect": "catalog:",
|
||||
"prettier": "3.6.2",
|
||||
@@ -542,7 +542,7 @@
|
||||
},
|
||||
"packages/latex": {
|
||||
"name": "@opencode/latex",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@opencode/plugin": "workspace:*",
|
||||
"@opentui/core": "catalog:",
|
||||
@@ -556,7 +556,7 @@
|
||||
},
|
||||
"packages/merman": {
|
||||
"name": "@opencode/merman",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@opencode/plugin": "workspace:*",
|
||||
"@opentui/core": "catalog:",
|
||||
@@ -571,7 +571,7 @@
|
||||
},
|
||||
"packages/plugin": {
|
||||
"name": "@opencode/plugin",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@ai-sdk/provider": "3.0.8",
|
||||
"@opencode/ai": "workspace:*",
|
||||
@@ -610,7 +610,7 @@
|
||||
},
|
||||
"packages/plugin-browser": {
|
||||
"name": "@opencode/plugin-browser",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@opencode/plugin": "workspace:*",
|
||||
"@opencode/schema": "workspace:*",
|
||||
@@ -640,7 +640,7 @@
|
||||
},
|
||||
"packages/protocol": {
|
||||
"name": "@opencode/protocol",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@opencode/schema": "workspace:*",
|
||||
"effect": "catalog:",
|
||||
@@ -655,7 +655,7 @@
|
||||
},
|
||||
"packages/schema": {
|
||||
"name": "@opencode/schema",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -679,7 +679,7 @@
|
||||
},
|
||||
"packages/sdk": {
|
||||
"name": "@opencode/sdk",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@opencode/client": "workspace:*",
|
||||
"@opencode/core": "workspace:*",
|
||||
@@ -700,7 +700,7 @@
|
||||
},
|
||||
"packages/server": {
|
||||
"name": "@opencode/server",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@effect/platform-node": "catalog:",
|
||||
"@effect/platform-node-shared": "catalog:",
|
||||
@@ -722,7 +722,7 @@
|
||||
},
|
||||
"packages/session-ui": {
|
||||
"name": "@opencode/session-ui",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode/client": "workspace:*",
|
||||
@@ -757,7 +757,7 @@
|
||||
},
|
||||
"packages/simulation": {
|
||||
"name": "@opencode/simulation",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@opencode/ai": "workspace:*",
|
||||
"@opencode/core": "workspace:*",
|
||||
@@ -777,7 +777,7 @@
|
||||
},
|
||||
"packages/stats/app": {
|
||||
"name": "@opencode/stats-app",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@ibm/plex": "6.4.1",
|
||||
"@kobalte/core": "catalog:",
|
||||
@@ -811,7 +811,7 @@
|
||||
},
|
||||
"packages/stats/core": {
|
||||
"name": "@opencode/stats-core",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-athena": "3.933.0",
|
||||
"@planetscale/database": "1.19.0",
|
||||
@@ -830,7 +830,7 @@
|
||||
},
|
||||
"packages/stats/server": {
|
||||
"name": "@opencode/stats-server",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-firehose": "3.933.0",
|
||||
"@effect/platform-node": "catalog:",
|
||||
@@ -876,7 +876,7 @@
|
||||
},
|
||||
"packages/theme": {
|
||||
"name": "@opencode/theme",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@opentui/core": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -890,7 +890,7 @@
|
||||
},
|
||||
"packages/tui": {
|
||||
"name": "@opencode/tui",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@opencode/client": "workspace:*",
|
||||
"@opencode/core": "workspace:*",
|
||||
@@ -925,7 +925,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@opencode/ui",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@pierre/diffs": "catalog:",
|
||||
@@ -960,7 +960,7 @@
|
||||
},
|
||||
"packages/util": {
|
||||
"name": "@opencode/util",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@effect/opentelemetry": "catalog:",
|
||||
"@effect/platform-node": "catalog:",
|
||||
@@ -997,7 +997,7 @@
|
||||
},
|
||||
"packages/web": {
|
||||
"name": "@opencode/web",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"@astrojs/cloudflare": "12.6.3",
|
||||
"@astrojs/markdown-remark": "6.3.1",
|
||||
@@ -1038,7 +1038,7 @@
|
||||
},
|
||||
"services/update": {
|
||||
"name": "@opencode/update",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"dependencies": {
|
||||
"jose": "6.0.11",
|
||||
"semver": "catalog:",
|
||||
@@ -4114,7 +4114,7 @@
|
||||
|
||||
"github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="],
|
||||
|
||||
"gitlab-ai-provider": ["gitlab-ai-provider@6.16.0", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.0", "@anycable/core": "^0.9.2", "graphql-request": "^6.1.0", "isomorphic-ws": "^5.0.0", "openai": "^6.16.0", "socket.io-client": "^4.8.1", "vscode-jsonrpc": "^8.2.1", "zod": "^3.25.76" }, "peerDependencies": { "@ai-sdk/provider": ">=3.0.0", "@ai-sdk/provider-utils": ">=4.0.0" } }, "sha512-HMC3sKgWYaYSsgm86Cnq2e6laHlYkhiFQ6rFD5qsVghv9//6h4Ofr7j5R2KjQx9Hl8EBercPsmzjoEjEN7dX5Q=="],
|
||||
"gitlab-ai-provider": ["gitlab-ai-provider@6.18.0", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.0", "@anycable/core": "^0.9.2", "graphql-request": "^6.1.0", "isomorphic-ws": "^5.0.0", "openai": "^6.16.0", "socket.io-client": "^4.8.1", "vscode-jsonrpc": "^8.2.1", "zod": "^3.25.76" }, "peerDependencies": { "@ai-sdk/provider": ">=3.0.0", "@ai-sdk/provider-utils": ">=4.0.0" } }, "sha512-dXTXkNt1SFCL7jGlqazHL6iUJEug21qq0tx2s+Tui7jWNUqIAHEzY9WY1+PnZlhxvB56jPPBcFAT0attpjnopg=="],
|
||||
|
||||
"glob": ["glob@13.0.5", "", { "dependencies": { "minimatch": "^10.2.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw=="],
|
||||
|
||||
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"nodeModules": {
|
||||
"x86_64-linux": "sha256-LQ1GAz1qF4R5P4j/kkgUygsQvxm7KStVlMf24nmyq44=",
|
||||
"aarch64-linux": "sha256-PsNR3VaClA1O1vSE0z/Hb3XRT1pb6PvNRXuK+giIx6s=",
|
||||
"aarch64-darwin": "sha256-7VCS+GT7tDYAMgqNCnLh1zvHAZkLTnJJ4vtfM88ruT8=",
|
||||
"x86_64-darwin": "sha256-HyxXjiFVd8vcKvSb/BuHAY5Jj3MGgdXEvuhDuglp4ss="
|
||||
"x86_64-linux": "sha256-+Clo0VPDdruHSoBNvV/wKAM8iR6HJPtB00oa8yl9ujU=",
|
||||
"aarch64-linux": "sha256-4wU5v36GTXjwyt5ls4FH+5G43Ujd+dKVSJR21w3lhbA=",
|
||||
"aarch64-darwin": "sha256-pThjoD6baddQ6biy7k1ByXwGwLAeWe/+w0tcYmt1uWs=",
|
||||
"x86_64-darwin": "sha256-bCBl63CqBiqilb+YdaOLBYYZx/yf47c1aqgDOkgdegg="
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "opencode",
|
||||
"description": "AI-powered development tool",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"packageManager": "bun@1.4.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"name": "@opencode/ai",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1034,7 +1034,6 @@ const fromRequest = Effect.fn("AnthropicMessages.fromRequest")(function* (reques
|
||||
const format = outputConfig?.format ?? undefined
|
||||
const updates = resolveEffortUpdates(request, options.effort ?? outputConfig?.effort ?? undefined)
|
||||
const generation = request.generation
|
||||
const toolSchemaCompatibility = request.model.compatibility?.toolSchema
|
||||
// Allocate the 4-breakpoint budget in invalidation order: tools → system →
|
||||
// messages. Tools live highest in the cache hierarchy, so when callers
|
||||
// over-mark we keep their tool hints and shed the message-tail ones first.
|
||||
@@ -1044,11 +1043,7 @@ const fromRequest = Effect.fn("AnthropicMessages.fromRequest")(function* (reques
|
||||
flattened.tools.length === 0
|
||||
? undefined
|
||||
: flattened.tools.map((tool) =>
|
||||
lowerTool(
|
||||
breakpoints,
|
||||
tool,
|
||||
ToolSchemaProjection.modelCompatibility(tool.inputSchema, toolSchemaCompatibility),
|
||||
),
|
||||
lowerTool(breakpoints, tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, request.model)),
|
||||
)
|
||||
// Anthropic rejects tool_choice when tools are absent; "none" is only meaningful with tools present.
|
||||
const toolChoice = tools === undefined || !request.toolChoice ? undefined : yield* lowerToolChoice(request.toolChoice)
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
type FinishReasonDetails,
|
||||
type JsonSchema,
|
||||
type LLMRequest,
|
||||
type LanguageModelToolSchemaCompatibility,
|
||||
type LanguageModel,
|
||||
type ProviderMetadata,
|
||||
type ReasoningPart,
|
||||
type ToolCallPart,
|
||||
@@ -230,13 +230,13 @@ const lowerToolSpec = (tool: ToolDefinition, inputSchema: JsonSchema): BedrockTo
|
||||
})
|
||||
|
||||
const lowerTools = (
|
||||
compatibility: LanguageModelToolSchemaCompatibility | undefined,
|
||||
model: LanguageModel,
|
||||
breakpoints: BedrockCache.Breakpoints,
|
||||
tools: ReadonlyArray<ToolDefinition>,
|
||||
): BedrockTool[] => {
|
||||
const result: BedrockTool[] = []
|
||||
for (const tool of tools) {
|
||||
result.push(lowerToolSpec(tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, compatibility)))
|
||||
result.push(lowerToolSpec(tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, model)))
|
||||
const cachePoint = BedrockCache.block(breakpoints, tool.cache)
|
||||
if (cachePoint) result.push(cachePoint)
|
||||
}
|
||||
@@ -440,7 +440,7 @@ const fromRequest = Effect.fn("BedrockConverse.fromRequest")(function* (request:
|
||||
const toolConfig = (() => {
|
||||
if (flattened.tools.length === 0) return undefined
|
||||
return {
|
||||
tools: lowerTools(request.model.compatibility?.toolSchema, breakpoints, flattened.tools),
|
||||
tools: lowerTools(request.model, breakpoints, flattened.tools),
|
||||
// Converse has no native "none". Keep definitions stable for prompt
|
||||
// caching and omit only the unsupported choice.
|
||||
toolChoice,
|
||||
|
||||
@@ -10,8 +10,8 @@ import {
|
||||
LLMEvent,
|
||||
Usage,
|
||||
type FinishReason,
|
||||
type JsonSchema,
|
||||
type LLMRequest,
|
||||
type LanguageModel,
|
||||
type MediaPart,
|
||||
type ProviderMetadata,
|
||||
type ProviderOptions,
|
||||
@@ -23,7 +23,6 @@ import { classifyProviderFailure } from "../provider-error.js"
|
||||
import { Media } from "../media.js"
|
||||
import { JsonObject, knownString, lenient, optionalArray, optionalNull, ProviderShared } from "./shared.js"
|
||||
import { GeminiGenerateContent } from "./utils/gemini-generate-content.js"
|
||||
import { GeminiToolSchema } from "./utils/gemini-tool-schema.js"
|
||||
import { Lifecycle } from "./utils/lifecycle.js"
|
||||
import { ToolSchemaProjection } from "./utils/tool-schema.js"
|
||||
|
||||
@@ -133,7 +132,7 @@ const GeminiSystemInstruction = Schema.Struct({
|
||||
const GeminiFunctionDeclaration = Schema.Struct({
|
||||
name: Schema.String,
|
||||
description: Schema.String,
|
||||
parameters: Schema.optional(JsonObject),
|
||||
parametersJsonSchema: JsonObject,
|
||||
})
|
||||
|
||||
const GeminiTool = Schema.Struct({
|
||||
@@ -266,36 +265,15 @@ interface ParserState {
|
||||
readonly seenCallIds?: ReadonlySet<string>
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Tool Schema Conversion
|
||||
// =============================================================================
|
||||
// Tool-schema conversion has two distinct concerns:
|
||||
//
|
||||
// 1. Sanitize — fix common authoring mistakes Gemini rejects: integer/number
|
||||
// enums (must be strings), `required` entries that don't match a property,
|
||||
// untyped arrays (`items` must be present), and `properties`/`required`
|
||||
// keys on non-object scalars. Mirrors OpenCode's historical Gemini rules.
|
||||
//
|
||||
// 2. Project — lossy mapping from JSON Schema to Gemini's schema dialect:
|
||||
// drop empty root parameter schemas while preserving nested empty objects,
|
||||
// expand type arrays into `anyOf`, derive `nullable: true` from null members,
|
||||
// coerce `const` to `[const]` enum, recurse properties/items, and propagate
|
||||
// only an allowlisted set of keys (description, required, format, type,
|
||||
// nullable, enum, properties, items, allOf, anyOf, oneOf, minLength).
|
||||
// Anything outside the allowlist (e.g. `additionalProperties`, `$ref`) is
|
||||
// silently dropped.
|
||||
//
|
||||
// Sanitize runs first, then project. The implementation lives in
|
||||
// `utils/gemini-tool-schema` so this protocol keeps the same shape as the other
|
||||
// provider protocols.
|
||||
|
||||
// =============================================================================
|
||||
// Request Lowering
|
||||
// =============================================================================
|
||||
const lowerTool = (tool: ToolDefinition, inputSchema: JsonSchema) => ({
|
||||
// Tool schemas go in `parametersJsonSchema`, which accepts standard JSON Schema. Gemini's schema
|
||||
// rules are this API's default, including for tuned endpoints whose IDs do not name Gemini.
|
||||
const lowerTool = (tool: ToolDefinition, model: LanguageModel) => ({
|
||||
name: tool.name,
|
||||
description: tool.description,
|
||||
parameters: GeminiToolSchema.convert(inputSchema),
|
||||
parametersJsonSchema: ToolSchemaProjection.modelCompatibility(tool.inputSchema, model, "gemini"),
|
||||
})
|
||||
|
||||
const lowerToolConfig = (toolChoice: NonNullable<LLMRequest["toolChoice"]>) =>
|
||||
@@ -465,7 +443,6 @@ const fromRequest = Effect.fn("Gemini.fromRequest")(function* (request: LLMReque
|
||||
const hasTools = flattened.tools.length > 0
|
||||
const generation = request.generation
|
||||
const options = yield* decodeOptions(request.providerOptions ?? {})
|
||||
const toolSchemaCompatibility = request.model.compatibility?.toolSchema
|
||||
const generationConfig = {
|
||||
maxOutputTokens: generation?.maxTokens,
|
||||
temperature: generation?.temperature,
|
||||
@@ -491,9 +468,7 @@ const fromRequest = Effect.fn("Gemini.fromRequest")(function* (request: LLMReque
|
||||
tools: hasTools
|
||||
? [
|
||||
{
|
||||
functionDeclarations: flattened.tools.map((tool) =>
|
||||
lowerTool(tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, toolSchemaCompatibility)),
|
||||
),
|
||||
functionDeclarations: flattened.tools.map((tool) => lowerTool(tool, request.model)),
|
||||
},
|
||||
]
|
||||
: undefined,
|
||||
|
||||
@@ -107,7 +107,7 @@ const fromRequest = Effect.fn("MetaResponses.fromRequest")(function* (request: L
|
||||
return yield* OpenResponses.lowerTool(
|
||||
NAME,
|
||||
tool,
|
||||
ToolSchemaProjection.modelCompatibility(tool.inputSchema, request.model.compatibility?.toolSchema),
|
||||
ToolSchemaProjection.modelCompatibility(tool.inputSchema, request.model),
|
||||
)
|
||||
return yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(NativeTool))(tool.native.meta)
|
||||
}),
|
||||
|
||||
@@ -818,7 +818,6 @@ export const fromRequestWithAdapter = Effect.fn("OpenResponses.fromRequestWithAd
|
||||
adapter: ProviderAdapter,
|
||||
) {
|
||||
const projected = ProviderShared.flattenToolRequest(request)
|
||||
const toolSchemaCompatibility = request.model.compatibility?.toolSchema
|
||||
return {
|
||||
...(yield* lowerConversation(projected.request, adapter)),
|
||||
...lowerGeneration(request),
|
||||
@@ -828,11 +827,7 @@ export const fromRequestWithAdapter = Effect.fn("OpenResponses.fromRequestWithAd
|
||||
: yield* Effect.forEach(projected.tools, (tool) =>
|
||||
tool.native !== undefined && adapter.nativeTool
|
||||
? adapter.nativeTool(tool.native)
|
||||
: lowerTool(
|
||||
adapter.name,
|
||||
tool,
|
||||
ToolSchemaProjection.modelCompatibility(tool.inputSchema, toolSchemaCompatibility),
|
||||
),
|
||||
: lowerTool(adapter.name, tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, request.model)),
|
||||
),
|
||||
tool_choice:
|
||||
allowedToolChoice(request) ??
|
||||
|
||||
@@ -803,7 +803,6 @@ export const fromRequest = Effect.fn("OpenAIChat.fromRequest")(function* (
|
||||
`OpenAI Chat reasoning field conflicts with reserved field ${reasoningField}`,
|
||||
)
|
||||
const generation = request.generation
|
||||
const toolSchemaCompatibility = request.model.compatibility?.toolSchema
|
||||
const flattened = ProviderShared.flattenToolRequest(request)
|
||||
const provider = String(request.model.provider)
|
||||
const baseURL = request.model.route.endpoint.baseURL
|
||||
@@ -829,7 +828,7 @@ export const fromRequest = Effect.fn("OpenAIChat.fromRequest")(function* (
|
||||
: flattened.tools.map((tool) =>
|
||||
lowerTool(
|
||||
tool,
|
||||
ToolSchemaProjection.modelCompatibility(tool.inputSchema, toolSchemaCompatibility),
|
||||
ToolSchemaProjection.modelCompatibility(tool.inputSchema, request.model),
|
||||
options,
|
||||
supportsStrictMode,
|
||||
),
|
||||
|
||||
@@ -5,7 +5,14 @@ import { Auth } from "../route/auth.js"
|
||||
import { Endpoint } from "../route/endpoint.js"
|
||||
import { Protocol } from "../route/protocol.js"
|
||||
import { HttpTransport } from "../route/transport/index.js"
|
||||
import { LLMRequest, mergeJsonRecords, type JsonSchema, type ToolDefinition, type ToolEntry } from "../schema/index.js"
|
||||
import {
|
||||
LLMRequest,
|
||||
mergeJsonRecords,
|
||||
type JsonSchema,
|
||||
type LanguageModel,
|
||||
type ToolDefinition,
|
||||
type ToolEntry,
|
||||
} from "../schema/index.js"
|
||||
import { resolveEffortUpdates } from "../effort-updates.js"
|
||||
import { OpenResponses } from "./open-responses.js"
|
||||
import { OpenResponsesOptions } from "./utils/open-responses-options.js"
|
||||
@@ -170,12 +177,9 @@ const lowerTool = Effect.fn("OpenAIResponses.lowerTool")(function* (tool: ToolDe
|
||||
|
||||
// Native namespaces hold only function tools, so deeper levels flatten into
|
||||
// the leaf names the same way non-native protocols flatten the whole tree.
|
||||
const lowerToolEntry = Effect.fn("OpenAIResponses.lowerToolEntry")(function* (
|
||||
tool: ToolEntry,
|
||||
compatibility: Parameters<typeof ToolSchemaProjection.modelCompatibility>[1],
|
||||
) {
|
||||
const lowerToolEntry = Effect.fn("OpenAIResponses.lowerToolEntry")(function* (tool: ToolEntry, model: LanguageModel) {
|
||||
if (tool.type === "tool")
|
||||
return yield* lowerTool(tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, compatibility))
|
||||
return yield* lowerTool(tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, model))
|
||||
// OpenAI requires a namespace description; fall back to a generic one so a
|
||||
// missing description never blocks the request.
|
||||
return {
|
||||
@@ -183,7 +187,7 @@ const lowerToolEntry = Effect.fn("OpenAIResponses.lowerToolEntry")(function* (
|
||||
name: tool.name,
|
||||
description: tool.description ?? `Tools in the ${tool.name} namespace.`,
|
||||
tools: yield* Effect.forEach(ProviderShared.flattenTools(tool.tools), (leaf) =>
|
||||
OpenResponses.lowerTool(NAME, leaf, ToolSchemaProjection.modelCompatibility(leaf.inputSchema, compatibility)),
|
||||
OpenResponses.lowerTool(NAME, leaf, ToolSchemaProjection.modelCompatibility(leaf.inputSchema, model)),
|
||||
),
|
||||
}
|
||||
})
|
||||
@@ -207,7 +211,6 @@ const fromRequest = Effect.fn("OpenAIResponses.fromRequest")(function* (request:
|
||||
)(request.providerOptions?.contextManagement)
|
||||
const options = OpenResponsesOptions.resolve(request)
|
||||
const updates = resolveEffortUpdates(request, options.reasoningEffort)
|
||||
const toolSchemaCompatibility = request.model.compatibility?.toolSchema
|
||||
return yield* decodeBody({
|
||||
...(yield* OpenResponses.lowerConversation(updates.request, adapter)),
|
||||
...OpenResponses.lowerGeneration(request, { ...options, reasoningEffort: updates.effort }),
|
||||
@@ -215,7 +218,7 @@ const fromRequest = Effect.fn("OpenAIResponses.fromRequest")(function* (request:
|
||||
tools:
|
||||
request.tools.length === 0
|
||||
? undefined
|
||||
: yield* Effect.forEach(request.tools, (tool) => lowerToolEntry(tool, toolSchemaCompatibility)),
|
||||
: yield* Effect.forEach(request.tools, (tool) => lowerToolEntry(tool, request.model)),
|
||||
tool_choice:
|
||||
request.tools.length === 0
|
||||
? undefined
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import type { JsonSchema } from "../../schema/index.js"
|
||||
import { isRecord } from "../../utils/record.js"
|
||||
|
||||
// Gemini's `parametersJsonSchema` accepts standard JSON Schema, but rejects a few shapes that
|
||||
// published tool schemas commonly contain. Rewrite only those and send everything else unchanged.
|
||||
const SCHEMA_MAPS = new Set([
|
||||
"properties",
|
||||
"patternProperties",
|
||||
"$defs",
|
||||
"definitions",
|
||||
"dependentSchemas",
|
||||
"dependencies",
|
||||
])
|
||||
const VALUES = new Set(["const", "default", "enum", "examples", "dependentRequired"])
|
||||
|
||||
const mapValues = (record: Record<string, unknown>, map: (value: unknown, key: string) => unknown) =>
|
||||
Object.fromEntries(Object.entries(record).map(([key, value]) => [key, map(value, key)]))
|
||||
|
||||
const normalizeNode = (schema: unknown): unknown => {
|
||||
if (Array.isArray(schema)) return schema.map(normalizeNode)
|
||||
if (!isRecord(schema)) return schema
|
||||
const properties = isRecord(schema.properties) ? schema.properties : undefined
|
||||
return Object.fromEntries(
|
||||
Object.entries(schema).flatMap(([key, value]) => {
|
||||
if (VALUES.has(key)) return [[key, value]]
|
||||
if (SCHEMA_MAPS.has(key) && isRecord(value)) return [[key, mapValues(value, normalizeNode)]]
|
||||
// `required` may only name declared properties.
|
||||
if (key === "required" && properties && Array.isArray(value))
|
||||
return [[key, value.filter((name) => typeof name === "string" && Object.hasOwn(properties, name))]]
|
||||
// Draft-04 boolean exclusive bounds become the numeric form.
|
||||
if (key === "exclusiveMinimum" && typeof value === "boolean")
|
||||
return value && typeof schema.minimum === "number" ? [[key, schema.minimum]] : []
|
||||
if (key === "exclusiveMaximum" && typeof value === "boolean")
|
||||
return value && typeof schema.maximum === "number" ? [[key, schema.maximum]] : []
|
||||
if (key === "minimum" && schema.exclusiveMinimum === true) return []
|
||||
if (key === "maximum" && schema.exclusiveMaximum === true) return []
|
||||
// Draft-07 tuples (`items` array plus `additionalItems`) are `prefixItems` plus `items` in 2020-12.
|
||||
if (key === "items" && Array.isArray(value)) return [["prefixItems", value.map(normalizeNode)]]
|
||||
if (key === "additionalItems" && Array.isArray(schema.items)) return [["items", normalizeNode(value)]]
|
||||
return [[key, normalizeNode(value)]]
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
// Gemini accepts a recursive `$ref` only when the loop passes through an optional property or
|
||||
// potentially empty array `items`. Replace other self-references with an unconstrained schema.
|
||||
const cutLoops = (schema: unknown, target: string, safe: boolean): unknown => {
|
||||
if (Array.isArray(schema)) return schema.map((item) => cutLoops(item, target, safe))
|
||||
if (!isRecord(schema)) return schema
|
||||
if (schema.$ref === target && !safe) return {}
|
||||
const required = Array.isArray(schema.required) ? schema.required : []
|
||||
return mapValues(schema, (value, key) => {
|
||||
if (VALUES.has(key)) return value
|
||||
if (key === "items") return cutLoops(value, target, safe || !(Number(schema.minItems) > 0))
|
||||
if (key === "properties" && isRecord(value))
|
||||
return mapValues(value, (child, name) => cutLoops(child, target, safe || !required.includes(name)))
|
||||
if (SCHEMA_MAPS.has(key) && isRecord(value)) return mapValues(value, (child) => cutLoops(child, target, safe))
|
||||
return cutLoops(value, target, safe)
|
||||
})
|
||||
}
|
||||
|
||||
export const normalize = (schema: JsonSchema): JsonSchema => {
|
||||
const normalized = normalizeNode(schema)
|
||||
if (!isRecord(normalized)) return {}
|
||||
const result = cutLoops(
|
||||
mapValues(normalized, (value, key) =>
|
||||
(key === "$defs" || key === "definitions") && isRecord(value)
|
||||
? mapValues(value, (def, name) => cutLoops(def, `#/${key}/${name}`, false))
|
||||
: value,
|
||||
),
|
||||
"#",
|
||||
false,
|
||||
)
|
||||
return isRecord(result) ? result : {}
|
||||
}
|
||||
|
||||
export * as GeminiJsonSchema from "./gemini-json-schema.js"
|
||||
@@ -1,119 +0,0 @@
|
||||
import { isRecord } from "../../utils/record.js"
|
||||
|
||||
// Gemini accepts a JSON Schema-like dialect for tool parameters, but rejects a
|
||||
// handful of common JSON Schema shapes. Keep this projection isolated so the
|
||||
// Gemini protocol file still reads like the other protocol modules.
|
||||
const SCHEMA_INTENT_KEYS = [
|
||||
"type",
|
||||
"properties",
|
||||
"items",
|
||||
"prefixItems",
|
||||
"enum",
|
||||
"const",
|
||||
"$ref",
|
||||
"additionalProperties",
|
||||
"patternProperties",
|
||||
"required",
|
||||
"not",
|
||||
"if",
|
||||
"then",
|
||||
"else",
|
||||
]
|
||||
|
||||
const hasCombiner = (schema: unknown) =>
|
||||
isRecord(schema) && (Array.isArray(schema.anyOf) || Array.isArray(schema.oneOf) || Array.isArray(schema.allOf))
|
||||
|
||||
const hasSchemaIntent = (schema: unknown) =>
|
||||
isRecord(schema) && (hasCombiner(schema) || SCHEMA_INTENT_KEYS.some((key) => key in schema))
|
||||
|
||||
const sanitizeNode = (schema: unknown): unknown => {
|
||||
if (!isRecord(schema)) return Array.isArray(schema) ? schema.map(sanitizeNode) : schema
|
||||
|
||||
const result: Record<string, unknown> = Object.fromEntries(
|
||||
Object.entries(schema).map(([key, value]) => [
|
||||
key,
|
||||
key === "enum" && Array.isArray(value) ? value.map(String) : sanitizeNode(value),
|
||||
]),
|
||||
)
|
||||
|
||||
if (Array.isArray(result.enum) && (result.type === "integer" || result.type === "number")) result.type = "string"
|
||||
|
||||
const properties = result.properties
|
||||
if (result.type === "object" && isRecord(properties) && Array.isArray(result.required)) {
|
||||
result.required = result.required.filter((field) => typeof field === "string" && field in properties)
|
||||
}
|
||||
|
||||
if (result.type === "array" && !hasCombiner(result)) {
|
||||
result.items = result.items ?? {}
|
||||
if (isRecord(result.items) && !hasSchemaIntent(result.items)) result.items = { ...result.items, type: "string" }
|
||||
}
|
||||
|
||||
if (typeof result.type === "string" && result.type !== "object" && !hasCombiner(result)) {
|
||||
delete result.properties
|
||||
delete result.required
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
const emptyObjectSchema = (schema: Record<string, unknown>) =>
|
||||
schema.type === "object" &&
|
||||
(!isRecord(schema.properties) || Object.keys(schema.properties).length === 0) &&
|
||||
!schema.additionalProperties
|
||||
|
||||
const projectNode = (schema: unknown, nested = false): Record<string, unknown> | undefined => {
|
||||
if (!isRecord(schema)) return undefined
|
||||
if (!nested && emptyObjectSchema(schema)) return undefined
|
||||
const types = Array.isArray(schema.type) ? schema.type.filter((type) => type !== "null") : undefined
|
||||
const anyOf = Array.isArray(schema.anyOf) ? schema.anyOf : undefined
|
||||
const hasNullAnyOf = anyOf?.some((item) => isRecord(item) && item.type === "null") ?? false
|
||||
const anyOfTypes = hasNullAnyOf ? anyOf?.filter((item) => !isRecord(item) || item.type !== "null") : anyOf
|
||||
const flattenedAnyOf = hasNullAnyOf && anyOfTypes?.length === 1 ? projectNode(anyOfTypes[0], true) : undefined
|
||||
const result = Object.fromEntries(
|
||||
[
|
||||
["description", schema.description],
|
||||
["required", schema.required],
|
||||
["format", schema.format],
|
||||
["type", types ? (types.length === 0 ? "null" : undefined) : schema.type],
|
||||
[
|
||||
"nullable",
|
||||
(Array.isArray(schema.type) && schema.type.includes("null") && types && types.length > 0) || hasNullAnyOf
|
||||
? true
|
||||
: undefined,
|
||||
],
|
||||
["enum", schema.const !== undefined ? [schema.const] : schema.enum],
|
||||
[
|
||||
"properties",
|
||||
isRecord(schema.properties)
|
||||
? Object.fromEntries(Object.entries(schema.properties).map(([key, value]) => [key, projectNode(value, true)]))
|
||||
: undefined,
|
||||
],
|
||||
[
|
||||
"items",
|
||||
Array.isArray(schema.items)
|
||||
? schema.items.map((item) => projectNode(item, true))
|
||||
: schema.items === undefined
|
||||
? undefined
|
||||
: projectNode(schema.items, true),
|
||||
],
|
||||
["allOf", Array.isArray(schema.allOf) ? schema.allOf.map((item) => projectNode(item, true)) : undefined],
|
||||
[
|
||||
"anyOf",
|
||||
anyOfTypes
|
||||
? hasNullAnyOf && anyOfTypes.length === 1
|
||||
? undefined
|
||||
: anyOfTypes.map((item) => projectNode(item, true))
|
||||
: types && types.length > 0
|
||||
? types.map((type) => ({ type }))
|
||||
: undefined,
|
||||
],
|
||||
["oneOf", Array.isArray(schema.oneOf) ? schema.oneOf.map((item) => projectNode(item, true)) : undefined],
|
||||
["minLength", schema.minLength],
|
||||
].filter((entry) => entry[1] !== undefined),
|
||||
)
|
||||
return flattenedAnyOf ? { ...result, ...flattenedAnyOf } : result
|
||||
}
|
||||
|
||||
export const convert = (schema: unknown) => projectNode(sanitizeNode(schema))
|
||||
|
||||
export * as GeminiToolSchema from "./gemini-tool-schema.js"
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { JsonSchema, LanguageModelToolSchemaCompatibility } from "../../schema/index.js"
|
||||
import type { JsonSchema, LanguageModel, LanguageModelSanitizerCompatibility } from "../../schema/index.js"
|
||||
import { isRecord } from "../../utils/record.js"
|
||||
import { GeminiToolSchema } from "./gemini-tool-schema.js"
|
||||
import { GeminiJsonSchema } from "./gemini-json-schema.js"
|
||||
|
||||
const tupleItemsSchema = (items: ReadonlyArray<unknown>) => {
|
||||
const projected = items.map(moonshotNode)
|
||||
@@ -46,18 +46,29 @@ const moonshot = (schema: JsonSchema): JsonSchema => {
|
||||
const openAI = (schema: JsonSchema): JsonSchema => schema
|
||||
const responses = openAI
|
||||
|
||||
const gemini = (schema: JsonSchema): JsonSchema => GeminiToolSchema.convert(schema) ?? {}
|
||||
const gemini = GeminiJsonSchema.normalize
|
||||
|
||||
const MODEL_NAMES = [
|
||||
[/gemini/i, "gemini"],
|
||||
[/kimi/i, "moonshot"],
|
||||
] as const
|
||||
|
||||
// An explicit `sanitizer` wins, and `none` opts out. Otherwise the protocol's own default
|
||||
// applies (the Gemini API always uses Gemini's rules), then the model name selects the family's rules
|
||||
// so models reached through gateways and OpenAI-compatible endpoints get the same handling.
|
||||
const modelCompatibility = (
|
||||
schema: JsonSchema,
|
||||
compatibility: LanguageModelToolSchemaCompatibility | undefined,
|
||||
model: LanguageModel,
|
||||
protocolDefault?: LanguageModelSanitizerCompatibility,
|
||||
): JsonSchema => {
|
||||
if (compatibility === undefined) return schema
|
||||
switch (compatibility) {
|
||||
switch (model.compatibility?.sanitizer ?? protocolDefault ?? MODEL_NAMES.find(([name]) => name.test(model.id))?.[1]) {
|
||||
case "gemini":
|
||||
return gemini(schema)
|
||||
case "moonshot":
|
||||
return moonshot(schema)
|
||||
case "none":
|
||||
case undefined:
|
||||
return schema
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -113,19 +113,19 @@ export const configure = (input: Config = {}) => {
|
||||
supportsStore: false,
|
||||
supportsStrictMode: false,
|
||||
supportsPromptCacheKey: true,
|
||||
toolSchema: "moonshot",
|
||||
sanitizer: "moonshot",
|
||||
reasoningField: "reasoning_content",
|
||||
},
|
||||
})
|
||||
const messages = (modelID: string | ModelID) =>
|
||||
messagesRoute.with(defaults).model<MessagesOptionsInput>({
|
||||
id: modelID,
|
||||
compatibility: { requireSignature: false, toolSchema: "moonshot" },
|
||||
compatibility: { requireSignature: false, sanitizer: "moonshot" },
|
||||
})
|
||||
const responses = (modelID: string | ModelID) =>
|
||||
responsesRoute
|
||||
.with(defaults)
|
||||
.model<ResponsesOptionsInput>({ id: modelID, compatibility: { toolSchema: "moonshot" } })
|
||||
.model<ResponsesOptionsInput>({ id: modelID, compatibility: { sanitizer: "moonshot" } })
|
||||
return { id, model: chat, chat, messages, responses, configure }
|
||||
}
|
||||
|
||||
|
||||
@@ -152,8 +152,9 @@ export const ReasoningEffort = Schema.declare<ReasoningEffort>(
|
||||
{ title: "ReasoningEffort" },
|
||||
)
|
||||
|
||||
export const LanguageModelToolSchemaCompatibility = Schema.Literals(["gemini", "moonshot"])
|
||||
export type LanguageModelToolSchemaCompatibility = Schema.Schema.Type<typeof LanguageModelToolSchemaCompatibility>
|
||||
/** Tool schema sanitizer for a model family. `none` opts out of the protocol and model-name defaults. */
|
||||
export const LanguageModelSanitizerCompatibility = Schema.Literals(["gemini", "moonshot", "none"])
|
||||
export type LanguageModelSanitizerCompatibility = Schema.Schema.Type<typeof LanguageModelSanitizerCompatibility>
|
||||
|
||||
export const LanguageModelMaxTokensFieldCompatibility = Schema.Literals(["max_completion_tokens", "max_tokens"])
|
||||
export type LanguageModelMaxTokensFieldCompatibility = Schema.Schema.Type<
|
||||
@@ -163,7 +164,7 @@ export type LanguageModelMaxTokensFieldCompatibility = Schema.Schema.Type<
|
||||
export class LanguageModelCompatibility extends Schema.Class<LanguageModelCompatibility>(
|
||||
"LLM.LanguageModelCompatibility",
|
||||
)({
|
||||
toolSchema: Schema.optional(LanguageModelToolSchemaCompatibility),
|
||||
sanitizer: Schema.optional(LanguageModelSanitizerCompatibility),
|
||||
reasoningField: Schema.optional(Schema.String),
|
||||
/** Require every assistant message to include its reasoning field, even when empty. */
|
||||
requireReasoning: Schema.optional(Schema.Boolean),
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"name": "gemini/streams-text",
|
||||
"recordedAt": "2026-04-28T21:18:47.483Z",
|
||||
"tags": ["prefix:gemini", "provider:google", "protocol:gemini"]
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"contents\":[{\"role\":\"user\",\"parts\":[{\"text\":\"Reply with exactly: Hello!\"}]}],\"systemInstruction\":{\"parts\":[{\"text\":\"You are concise.\"}]},\"generationConfig\":{\"maxOutputTokens\":80,\"temperature\":0}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream"
|
||||
},
|
||||
"body": "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"Hello!\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 11,\"candidatesTokenCount\": 2,\"totalTokenCount\": 29,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 11}],\"thoughtsTokenCount\": 16},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": \"NyTxaczMAZ-b_uMP6u--iQg\"}\r\n\r\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"name": "gemini/streams-tool-call",
|
||||
"recordedAt": "2026-04-28T21:18:48.285Z",
|
||||
"tags": ["prefix:gemini", "provider:google", "protocol:gemini", "tool"]
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"transport": "http",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"contents\":[{\"role\":\"user\",\"parts\":[{\"text\":\"Call get_weather with city exactly Paris.\"}]}],\"systemInstruction\":{\"parts\":[{\"text\":\"Call tools exactly as requested.\"}]},\"tools\":[{\"functionDeclarations\":[{\"name\":\"get_weather\",\"description\":\"Get current weather for a city.\",\"parameters\":{\"required\":[\"city\"],\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}}}}]}],\"toolConfig\":{\"functionCallingConfig\":{\"mode\":\"ANY\",\"allowedFunctionNames\":[\"get_weather\"]}},\"generationConfig\":{\"maxOutputTokens\":80,\"temperature\":0}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream"
|
||||
},
|
||||
"body": "data: {\"candidates\": [{\"content\": {\"parts\": [{\"functionCall\": {\"name\": \"get_weather\",\"args\": {\"city\": \"Paris\"}},\"thoughtSignature\": \"CiQBDDnWx5RcSsS1UMbykQ5HWlrMu6wrxXGUhmZ0uRKLaMhDZaEKXwEMOdbHVoJAlfbOQyKB378pDZ/gkjWr3HP+dWw1us1kMG22g4G3oJvuTq/SrWS+7KYtSlvOxCKhW2l/2/TczpyGyGmANmsusDcxF1SKOYA5/8Hg0nI24MAlT3+91V/MCoUBAQw51seClFLy3E71v2H44F1kpmjgz8FeTRZofrjbaazfrT+w8Yxgdr3UgGagLMY4OadZemQTWckq9IAqRum78hrBg6NGtQvn15SbtfTNqI4PcxX/+qPo4/g4/ZT5kVORDhVqO8BVP/RA5GQ3ce3sRK8hSkvQlXSoXIPpHh6x7hBezIGXzw==\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0,\"finishMessage\": \"Model generated function call(s).\"}],\"usageMetadata\": {\"promptTokenCount\": 55,\"candidatesTokenCount\": 15,\"totalTokenCount\": 115,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 55}],\"thoughtsTokenCount\": 45},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": \"NyTxaYuTJ_OW_uMPgIPKgAg\"}\r\n\r\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
"protocol:gemini"
|
||||
],
|
||||
"name": "google-vertex/calls-a-tool",
|
||||
"recordedAt": "2026-09-22T03:46:29.725Z"
|
||||
"recordedAt": "2026-09-24T01:06:19.246Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
@@ -18,14 +18,14 @@
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"contents\":[{\"role\":\"user\",\"parts\":[{\"text\":\"What is the weather in Paris? Use the lookup_weather tool.\"}]}],\"tools\":[{\"functionDeclarations\":[{\"name\":\"lookup_weather\",\"description\":\"Look up the current weather for a city\",\"parameters\":{\"required\":[\"city\"],\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}}}}]}]}"
|
||||
"body": "{\"contents\":[{\"role\":\"user\",\"parts\":[{\"text\":\"What is the weather in Paris? Use the lookup_weather tool.\"}]}],\"tools\":[{\"functionDeclarations\":[{\"name\":\"lookup_weather\",\"description\":\"Look up the current weather for a city\",\"parametersJsonSchema\":{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}},\"required\":[\"city\"]}}]}]}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream"
|
||||
},
|
||||
"body": "data: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\": [{\"functionCall\": {\"name\": \"lookup_weather\",\"args\": {\"city\": \"Paris\"},\"id\": \"call_28936\"},\"thoughtSignature\": \"AY89a1/MVeBxtwu9l/96clFobOrrd7Q5MTf5o8/A22fc++1EsFYVeCFx9WCGmJ+D3yW3FWlRXKtJECYfprSoxixCSOYBNiV9g8/IkejbAxF26k1vxTsHkoqts0O2s8GqqBSRAavJfKQ/taTRbPuIq+b+RKZ8SDJFoWDnFjXpdS5S164uJTjmgs4ALd8oB1oQRycMsTbAY51TmkcNUnhARpjKQfqiizz4KfSRFjx7xDnza0v4jj73m2GV86eLDhVT7trIT+Dl5DsJt6RBLOE2Amse54mcpIbsYaANlY1YDU6FKuUBqnuwpl0OfhMXwWuYMogv1tH/0rTXsqNwmHyt/b9ZZXqYCdFXpMGt8udmoZ0d\"}]}}],\"usageMetadata\": {\"trafficType\": \"ON_DEMAND\"},\"modelVersion\": \"gemini-3.5-flash\",\"createTime\": \"2026-09-22T03:46:28.953809Z\",\"responseId\": \"FPqxatGbOsSorb8PtY2z8Q4\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \"\"}]},\"finishReason\": \"STOP\"}],\"usageMetadata\": {\"promptTokenCount\": 39,\"candidatesTokenCount\": 16,\"totalTokenCount\": 93,\"trafficType\": \"ON_DEMAND\",\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 39}],\"candidatesTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 16}],\"thoughtsTokenCount\": 38},\"modelVersion\": \"gemini-3.5-flash\",\"createTime\": \"2026-09-22T03:46:28.953809Z\",\"responseId\": \"FPqxatGbOsSorb8PtY2z8Q4\"}\r\n\r\n"
|
||||
"body": "data: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\": [{\"functionCall\": {\"name\": \"lookup_weather\",\"args\": {\"city\": \"Paris\"},\"id\": \"call_554608\"},\"thoughtSignature\": \"AY89a19hRAmVFgUw7vo3hvQF7VpSnCGYSRXo34+yjCySmgHtvL/4LEf6V2F12glreaWUixVINDFWR+DLprZZxayR8gb+wZMWssV0Cbv1fDPYV6qxggRiLEKnG6A7UY+vmhXUO5IAtL06Ud24IYd+3QI0T05gzSnwqy7Uotw9J5B8LSr76MvbDncgyeWcBhZSpxxi2XPJxZqR6N/7gwxRSW3KMBp0CKHnU4MF+t0fN1oQ2uSWCxQAYW0nq8TQL6nYYgShN35VeGJ5+UvJ8OIYC0COQ1u/VNdqmJs2uRs3dHGzXzDSWdb/lIcqtzyKRLsIa7RWYmF1xZhEQZkXGGf9yco8e1OOovYhR/cEwE2+aw1scl3Deg2+D2R1PiFwwoZuMV+lIj3IwNexjLd56ZO/7QpzaX2K97b11duH4mBjgfG0x7c3+r9raD17quokhgW1ffoPiXiaemvD6mA84kkDIc4jxSnwNwuVxTgUkEwswub1C1lrlnzzeLHjnMvdopdHIViDsdcfRnXkhIwGyvr+QBSuz7yF1V/Vw+9MxYVVNM/7eQPpMxjJHpHTBMWqtzkC9zE6wK2iWr49AJm8ZpMS8a9uhW0OAksUslv5gvWKDEecaufO/66w+xltgnvDh2NVJuthULuG+nWnxGRq4ZbX00s3p0/J1vqQZcLsi37RpAs75g==\"}]}}],\"usageMetadata\": {\"trafficType\": \"ON_DEMAND\"},\"modelVersion\": \"gemini-3.5-flash\",\"createTime\": \"2026-09-24T01:06:18.093130Z\",\"responseId\": \"ine0asrXBbui3dAPpNDS8QE\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \"\"}]},\"finishReason\": \"STOP\"}],\"usageMetadata\": {\"promptTokenCount\": 39,\"candidatesTokenCount\": 16,\"totalTokenCount\": 156,\"trafficType\": \"ON_DEMAND\",\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 39}],\"candidatesTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 16}],\"thoughtsTokenCount\": 101},\"modelVersion\": \"gemini-3.5-flash\",\"createTime\": \"2026-09-24T01:06:18.093130Z\",\"responseId\": \"ine0asrXBbui3dAPpNDS8QE\"}\r\n\r\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
+3
-3
@@ -7,7 +7,7 @@
|
||||
"protocol:gemini"
|
||||
],
|
||||
"name": "google-vertex/continues-after-a-tool-result",
|
||||
"recordedAt": "2026-09-22T03:46:30.691Z"
|
||||
"recordedAt": "2026-09-24T01:06:20.321Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
@@ -18,14 +18,14 @@
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"contents\":[{\"role\":\"user\",\"parts\":[{\"text\":\"What is the weather in Paris?\"}]},{\"role\":\"model\",\"parts\":[{\"functionCall\":{\"id\":\"call_paris_1\",\"name\":\"lookup_weather\",\"args\":{\"city\":\"Paris\"}},\"thoughtSignature\":\"skip_thought_signature_validator\"}]},{\"role\":\"user\",\"parts\":[{\"functionResponse\":{\"id\":\"call_paris_1\",\"name\":\"lookup_weather\",\"response\":{\"name\":\"lookup_weather\",\"content\":\"18C, light rain\"}}}]}],\"tools\":[{\"functionDeclarations\":[{\"name\":\"lookup_weather\",\"description\":\"Look up the current weather for a city\",\"parameters\":{\"required\":[\"city\"],\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}}}}]}]}"
|
||||
"body": "{\"contents\":[{\"role\":\"user\",\"parts\":[{\"text\":\"What is the weather in Paris?\"}]},{\"role\":\"model\",\"parts\":[{\"functionCall\":{\"id\":\"call_paris_1\",\"name\":\"lookup_weather\",\"args\":{\"city\":\"Paris\"}},\"thoughtSignature\":\"skip_thought_signature_validator\"}]},{\"role\":\"user\",\"parts\":[{\"functionResponse\":{\"id\":\"call_paris_1\",\"name\":\"lookup_weather\",\"response\":{\"name\":\"lookup_weather\",\"content\":\"18C, light rain\"}}}]}],\"tools\":[{\"functionDeclarations\":[{\"name\":\"lookup_weather\",\"description\":\"Look up the current weather for a city\",\"parametersJsonSchema\":{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}},\"required\":[\"city\"]}}]}]}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream"
|
||||
},
|
||||
"body": "data: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \"The weather\"}]}}],\"usageMetadata\": {\"trafficType\": \"ON_DEMAND\"},\"modelVersion\": \"gemini-3.5-flash\",\"createTime\": \"2026-09-22T03:46:29.830958Z\",\"responseId\": \"Ffqxau7bMoCOrb8P_Iu5sA0\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \" in Paris is currently 18°C with light rain.\"}]}}],\"usageMetadata\": {\"trafficType\": \"ON_DEMAND\"},\"modelVersion\": \"gemini-3.5-flash\",\"createTime\": \"2026-09-22T03:46:29.830958Z\",\"responseId\": \"Ffqxau7bMoCOrb8P_Iu5sA0\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \"\",\"thoughtSignature\": \"AY89a18aVI8Uxr2VaOI822u0DyuQdy4B00uhLnjqYb5Qb6Mkscccm018knLtYThB5UX8dRv1VFsORSQ0Qo6Gx9RCng2AK9EPce7p\"}]},\"finishReason\": \"STOP\"}],\"usageMetadata\": {\"promptTokenCount\": 59,\"candidatesTokenCount\": 15,\"totalTokenCount\": 74,\"trafficType\": \"ON_DEMAND\",\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 59}],\"candidatesTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 15}]},\"modelVersion\": \"gemini-3.5-flash\",\"createTime\": \"2026-09-22T03:46:29.830958Z\",\"responseId\": \"Ffqxau7bMoCOrb8P_Iu5sA0\"}\r\n\r\n"
|
||||
"body": "data: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \"The weather\"}]}}],\"usageMetadata\": {\"trafficType\": \"ON_DEMAND\"},\"modelVersion\": \"gemini-3.5-flash\",\"createTime\": \"2026-09-24T01:06:19.664329Z\",\"responseId\": \"i3e0aonGKPCnrb8Pm97yiQs\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \" in Paris is currently 18°C with light rain.\"}]}}],\"usageMetadata\": {\"trafficType\": \"ON_DEMAND\"},\"modelVersion\": \"gemini-3.5-flash\",\"createTime\": \"2026-09-24T01:06:19.664329Z\",\"responseId\": \"i3e0aonGKPCnrb8Pm97yiQs\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \"\",\"thoughtSignature\": \"AY89a19mRwbMV0dQccZShfDptLQ20vI7Rg/LSyPDwW1Wt62fQvRT/2nUWW13cMmgYbd2VGGtrZIbnj+hxHMZt1NK2RyJIkg/FB13\"}]},\"finishReason\": \"STOP\"}],\"usageMetadata\": {\"promptTokenCount\": 59,\"candidatesTokenCount\": 15,\"totalTokenCount\": 74,\"trafficType\": \"ON_DEMAND\",\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 59}],\"candidatesTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 15}]},\"modelVersion\": \"gemini-3.5-flash\",\"createTime\": \"2026-09-24T01:06:19.664329Z\",\"responseId\": \"i3e0aonGKPCnrb8Pm97yiQs\"}\r\n\r\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
{
|
||||
"version": 1,
|
||||
"metadata": {
|
||||
"tags": ["prefix:pdf", "pdf", "provider:google", "protocol:gemini", "tool", "tool-result"],
|
||||
"tags": [
|
||||
"prefix:pdf",
|
||||
"pdf",
|
||||
"provider:google",
|
||||
"protocol:gemini",
|
||||
"tool",
|
||||
"tool-result"
|
||||
],
|
||||
"name": "pdf/gemini-tool-result",
|
||||
"recordedAt": "2026-07-22T18:21:59.606Z"
|
||||
"recordedAt": "2026-09-24T01:06:23.498Z"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
@@ -14,14 +21,14 @@
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"contents\":[{\"role\":\"user\",\"parts\":[{\"text\":\"Use read_pdf with path verification.pdf and return the verification code.\"}]}],\"systemInstruction\":{\"parts\":[{\"text\":\"Call read_pdf exactly once with path verification.pdf, then reply only with the verification code from its PDF.\"}]},\"tools\":[{\"functionDeclarations\":[{\"name\":\"read_pdf\",\"description\":\"Read the attached PDF.\",\"parameters\":{\"required\":[\"path\"],\"type\":\"object\",\"properties\":{\"path\":{\"type\":\"string\"}}}}]}],\"generationConfig\":{\"maxOutputTokens\":256,\"temperature\":0}}"
|
||||
"body": "{\"contents\":[{\"role\":\"user\",\"parts\":[{\"text\":\"Use read_pdf with path verification.pdf and return the verification code.\"}]}],\"systemInstruction\":{\"parts\":[{\"text\":\"Call read_pdf exactly once with path verification.pdf, then reply only with the verification code from its PDF.\"}]},\"tools\":[{\"functionDeclarations\":[{\"name\":\"read_pdf\",\"description\":\"Read the attached PDF.\",\"parametersJsonSchema\":{\"type\":\"object\",\"properties\":{\"path\":{\"type\":\"string\"}},\"required\":[\"path\"],\"additionalProperties\":false}}]}],\"generationConfig\":{\"maxOutputTokens\":256,\"temperature\":0}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream"
|
||||
},
|
||||
"body": "data: {\"candidates\": [{\"content\": {\"parts\": [{\"functionCall\": {\"name\": \"read_pdf\",\"args\": {\"path\": \"verification.pdf\"},\"id\": \"58shgmez\"},\"thoughtSignature\": \"EqkCCqYCARFNMg/JrCTv5i3zYENFBVpZNFL3pbzJmi5Eu387ncF703xFMB4pwyaP7a1gi49EqBhCI2hWOpesU5nZQOLAhGgExKGa2GM+HzpEB5g62r0NFblm/BGkVZaImTuHR7bytfRC5jHQlHKo4OS27OLUVjvkMkBIYsvjhDErY7niERbXJVpyxTVqUf1GgZMSu8kC9/5WDlMs9xVKNT/6KMW4PhhSR9nXg4KZUa+bC03/ydhsWWgBa5aLCgvTq7WPj217xIsmUkSiRedIffPsUSNjYdMHUvWi8bOlvM1veEEP6GIfv5h9gXXzjnHbEHfQxV8PZuBAyY7iM6nqyfkJNdkZ1HdB7DXMBsMsRN6SgrIrFoXX2WaGrkoEI5tdZx1t/gdwF1jEVT6k\"}],\"role\": \"model\"},\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 81,\"candidatesTokenCount\": 18,\"totalTokenCount\": 151,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 81}],\"thoughtsTokenCount\": 52,\"serviceTier\": \"standard\"},\"modelVersion\": \"gemini-3.5-flash\",\"responseId\": \"RAphaui3OaSHz7IPy8Kb4Ak\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 81,\"candidatesTokenCount\": 18,\"totalTokenCount\": 151,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 81}],\"thoughtsTokenCount\": 52,\"serviceTier\": \"standard\"},\"modelVersion\": \"gemini-3.5-flash\",\"responseId\": \"RAphaui3OaSHz7IPy8Kb4Ak\"}\r\n\r\n"
|
||||
"body": "data: {\"candidates\": [{\"content\": {\"parts\": [{\"functionCall\": {\"name\": \"read_pdf\",\"args\": {\"path\": \"verification.pdf\"},\"id\": \"call_475949\"},\"thoughtSignature\": \"Et4CCtsCAWkUfRPfQWeGIEQ/AhexY97IZoK8aNLr2EbW3nufnAXpa1y74z7qH1Tdk20j5EC57BSBbdy5u6xFHNomzZhGFVmdVlhgZFXGSO8F8K4t8rqQWUJZSDH4dFaC95KpUTfp5CAMepbOuc/dGLgXfVsSV0e/HvUcdWKoEz8Jlsgk59nexqSsdl/kGzuuIeW6zS5r8JHus+PfRzvSgua4B9OpDU9WWPCJZu93NLbXJELbZ330h7CP+uxXoo1Puu0KSrvLman8Geoc0nagMx895L0gO3CsbB+PpijQ6Pt6YAaiv1V2MeOCUKCYUpk+77MjC6RnsTFTRaJYJ5PPkniuRKedp/DF1aMj7nGxQ6BpHOMq9mjw2zlH3I2kJi1wqm+amVz30vTHa31xTH88w+IUc1yNdLAzdVJV+/+0mqw8bLweSjSHFxZN0NIv6aczAIS5stoGobNDO4bRGDETH3Q=\"}],\"role\": \"model\"},\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 81,\"candidatesTokenCount\": 18,\"totalTokenCount\": 152,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 81}],\"thoughtsTokenCount\": 53,\"serviceTier\": \"standard\"},\"modelVersion\": \"gemini-3.5-flash\",\"responseId\": \"jHe0apWcM92aqtsP8t2LyAg\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 81,\"candidatesTokenCount\": 18,\"totalTokenCount\": 152,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 81}],\"thoughtsTokenCount\": 53,\"serviceTier\": \"standard\"},\"modelVersion\": \"gemini-3.5-flash\",\"responseId\": \"jHe0apWcM92aqtsP8t2LyAg\"}\r\n\r\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -32,14 +39,14 @@
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": "{\"contents\":[{\"role\":\"user\",\"parts\":[{\"text\":\"Use read_pdf with path verification.pdf and return the verification code.\"}]},{\"role\":\"model\",\"parts\":[{\"functionCall\":{\"id\":\"58shgmez\",\"name\":\"read_pdf\",\"args\":{\"path\":\"verification.pdf\"}},\"thoughtSignature\":\"EqkCCqYCARFNMg/JrCTv5i3zYENFBVpZNFL3pbzJmi5Eu387ncF703xFMB4pwyaP7a1gi49EqBhCI2hWOpesU5nZQOLAhGgExKGa2GM+HzpEB5g62r0NFblm/BGkVZaImTuHR7bytfRC5jHQlHKo4OS27OLUVjvkMkBIYsvjhDErY7niERbXJVpyxTVqUf1GgZMSu8kC9/5WDlMs9xVKNT/6KMW4PhhSR9nXg4KZUa+bC03/ydhsWWgBa5aLCgvTq7WPj217xIsmUkSiRedIffPsUSNjYdMHUvWi8bOlvM1veEEP6GIfv5h9gXXzjnHbEHfQxV8PZuBAyY7iM6nqyfkJNdkZ1HdB7DXMBsMsRN6SgrIrFoXX2WaGrkoEI5tdZx1t/gdwF1jEVT6k\"}]},{\"role\":\"user\",\"parts\":[{\"functionResponse\":{\"id\":\"58shgmez\",\"name\":\"read_pdf\",\"response\":{\"name\":\"read_pdf\",\"content\":\"PDF read successfully\"},\"parts\":[{\"inlineData\":{\"mimeType\":\"application/pdf\",\"data\":\"JVBERi0xLjQKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZyAvUGFnZXMgMiAwIFIgPj4KZW5kb2JqCjIgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9LaWRzIFszIDAgUl0gL0NvdW50IDEgPj4KZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1BhZ2UgL1BhcmVudCAyIDAgUiAvTWVkaWFCb3ggWzAgMCA2MTIgNzkyXSAvUmVzb3VyY2VzIDw8IC9Gb250IDw8IC9GMSA1IDAgUiA+PiA+PiAvQ29udGVudHMgNCAwIFIgPj4KZW5kb2JqCjQgMCBvYmoKPDwgL0xlbmd0aCA3NSA+PgpzdHJlYW0KQlQKL0YxIDE4IFRmCjcyIDcyMCBUZAooUERGIGNhc3NldHRlIHZlcmlmaWNhdGlvbiBjb2RlOiBPUkNISUQtNzM5MSkgVGoKRVQKZW5kc3RyZWFtCmVuZG9iago1IDAgb2JqCjw8IC9UeXBlIC9Gb250IC9TdWJ0eXBlIC9UeXBlMSAvQmFzZUZvbnQgL0hlbHZldGljYSA+PgplbmRvYmoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDA5IDAwMDAwIG4gCjAwMDAwMDAwNTggMDAwMDAgbiAKMDAwMDAwMDExNSAwMDAwMCBuIAowMDAwMDAwMjQxIDAwMDAwIG4gCjAwMDAwMDAzNjUgMDAwMDAgbiAKdHJhaWxlcgo8PCAvU2l6ZSA2IC9Sb290IDEgMCBSID4+CnN0YXJ0eHJlZgo0MzUKJSVFT0YK\"}}]}}]}],\"systemInstruction\":{\"parts\":[{\"text\":\"Call read_pdf exactly once with path verification.pdf, then reply only with the verification code from its PDF.\"}]},\"tools\":[{\"functionDeclarations\":[{\"name\":\"read_pdf\",\"description\":\"Read the attached PDF.\",\"parameters\":{\"required\":[\"path\"],\"type\":\"object\",\"properties\":{\"path\":{\"type\":\"string\"}}}}]}],\"generationConfig\":{\"maxOutputTokens\":256,\"temperature\":0}}"
|
||||
"body": "{\"contents\":[{\"role\":\"user\",\"parts\":[{\"text\":\"Use read_pdf with path verification.pdf and return the verification code.\"}]},{\"role\":\"model\",\"parts\":[{\"functionCall\":{\"id\":\"call_475949\",\"name\":\"read_pdf\",\"args\":{\"path\":\"verification.pdf\"}},\"thoughtSignature\":\"Et4CCtsCAWkUfRPfQWeGIEQ/AhexY97IZoK8aNLr2EbW3nufnAXpa1y74z7qH1Tdk20j5EC57BSBbdy5u6xFHNomzZhGFVmdVlhgZFXGSO8F8K4t8rqQWUJZSDH4dFaC95KpUTfp5CAMepbOuc/dGLgXfVsSV0e/HvUcdWKoEz8Jlsgk59nexqSsdl/kGzuuIeW6zS5r8JHus+PfRzvSgua4B9OpDU9WWPCJZu93NLbXJELbZ330h7CP+uxXoo1Puu0KSrvLman8Geoc0nagMx895L0gO3CsbB+PpijQ6Pt6YAaiv1V2MeOCUKCYUpk+77MjC6RnsTFTRaJYJ5PPkniuRKedp/DF1aMj7nGxQ6BpHOMq9mjw2zlH3I2kJi1wqm+amVz30vTHa31xTH88w+IUc1yNdLAzdVJV+/+0mqw8bLweSjSHFxZN0NIv6aczAIS5stoGobNDO4bRGDETH3Q=\"}]},{\"role\":\"user\",\"parts\":[{\"functionResponse\":{\"id\":\"call_475949\",\"name\":\"read_pdf\",\"response\":{\"name\":\"read_pdf\",\"content\":\"PDF read successfully\"},\"parts\":[{\"inlineData\":{\"mimeType\":\"application/pdf\",\"data\":\"JVBERi0xLjQKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZyAvUGFnZXMgMiAwIFIgPj4KZW5kb2JqCjIgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9LaWRzIFszIDAgUl0gL0NvdW50IDEgPj4KZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1BhZ2UgL1BhcmVudCAyIDAgUiAvTWVkaWFCb3ggWzAgMCA2MTIgNzkyXSAvUmVzb3VyY2VzIDw8IC9Gb250IDw8IC9GMSA1IDAgUiA+PiA+PiAvQ29udGVudHMgNCAwIFIgPj4KZW5kb2JqCjQgMCBvYmoKPDwgL0xlbmd0aCA3NSA+PgpzdHJlYW0KQlQKL0YxIDE4IFRmCjcyIDcyMCBUZAooUERGIGNhc3NldHRlIHZlcmlmaWNhdGlvbiBjb2RlOiBPUkNISUQtNzM5MSkgVGoKRVQKZW5kc3RyZWFtCmVuZG9iago1IDAgb2JqCjw8IC9UeXBlIC9Gb250IC9TdWJ0eXBlIC9UeXBlMSAvQmFzZUZvbnQgL0hlbHZldGljYSA+PgplbmRvYmoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDA5IDAwMDAwIG4gCjAwMDAwMDAwNTggMDAwMDAgbiAKMDAwMDAwMDExNSAwMDAwMCBuIAowMDAwMDAwMjQxIDAwMDAwIG4gCjAwMDAwMDAzNjUgMDAwMDAgbiAKdHJhaWxlcgo8PCAvU2l6ZSA2IC9Sb290IDEgMCBSID4+CnN0YXJ0eHJlZgo0MzUKJSVFT0YK\"}}]}}]}],\"systemInstruction\":{\"parts\":[{\"text\":\"Call read_pdf exactly once with path verification.pdf, then reply only with the verification code from its PDF.\"}]},\"tools\":[{\"functionDeclarations\":[{\"name\":\"read_pdf\",\"description\":\"Read the attached PDF.\",\"parametersJsonSchema\":{\"type\":\"object\",\"properties\":{\"path\":{\"type\":\"string\"}},\"required\":[\"path\"],\"additionalProperties\":false}}]}],\"generationConfig\":{\"maxOutputTokens\":256,\"temperature\":0}}"
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"content-type": "text/event-stream"
|
||||
},
|
||||
"body": "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"ORCHID-7391\"}],\"role\": \"model\"},\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 123,\"candidatesTokenCount\": 8,\"totalTokenCount\": 184,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 123}],\"thoughtsTokenCount\": 53,\"serviceTier\": \"standard\"},\"modelVersion\": \"gemini-3.5-flash\",\"responseId\": \"RgphaoL6CMjQz7IPjOnEmQI\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"\",\"thoughtSignature\": \"EqECCp4CARFNMg9obBl8O6iU9lawUIWiE+1vztZm9NtaT9FuyJz343hd9ruz+xPco4Q1DY1GF81ZiSI2ElBkt8Wfwsqtix9LNGSMvbZhhk/ZnB54t05M/Dft1kujcMvEdZUWUI/jWaJ349tO1bKVH9MacG5+gl0n4y8DwyQZSV3xIcet547drSkcA/TM03RB+yj1/dcLHsvUjmv9EnO897vZgO2Dk4tbZ2NyCtOeQ3JKVhUTLg2pjkGk+POCNiOdESWiUzxdQKw9LiV6nnzi071tXNiMeVimq6d7xAzRVNapI2uXynvn9Uk3eyn85purOFa8cKriK9oD6vcyGMqgd9+gu2m3to0IHqd7o+2YSr1m5qV1xT1R2/WRQEtb1b1AuOAU6w==\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 1277,\"candidatesTokenCount\": 8,\"totalTokenCount\": 1338,\"promptTokensDetails\": [{\"modality\": \"IMAGE\",\"tokenCount\": 1102},{\"modality\": \"TEXT\",\"tokenCount\": 175}],\"thoughtsTokenCount\": 53,\"serviceTier\": \"standard\"},\"modelVersion\": \"gemini-3.5-flash\",\"responseId\": \"RgphaoL6CMjQz7IPjOnEmQI\"}\r\n\r\n"
|
||||
"body": "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"ORCHID-7391\"}],\"role\": \"model\"},\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 123,\"candidatesTokenCount\": 8,\"totalTokenCount\": 184,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 123}],\"thoughtsTokenCount\": 53,\"serviceTier\": \"standard\"},\"modelVersion\": \"gemini-3.5-flash\",\"responseId\": \"jXe0ar7CNdjBqtsPqMm2oAs\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"\",\"thoughtSignature\": \"EtcCCtQCAWkUfRM3dQjvavztF1qActLo1mpXoGlWdQ+qUpKf1DdrmgWIT1nm70cm+yGf4pj6UU9fhKU+/y+ScUv1IJrb3c3yU5X2/CGzcN/DeRhxuvuXRaGxtWi4GIu2nFr3oJrAOnJnh/kosgiqixwQ3EK6/0jdE2HOqxu7jImvozaVcR9OiVGgAHRwmDYtB6K+6/jMVjORBKB4nZp8MTb3IWaiN6soO+FiWRgl3etnnJhkJb6eBHhHmLW8qxyOmVwRII3Gtm5jJbxGND/aZSpxlBvfBpGfbJQJIfNQDs+sXeQpuZh8SZUVRgVAZyOrqbVS1vRq8kODaBvDHKuTr0Qo9RpGGGo0npaYooP663omHDhm7Uu5plFwAVYR5G4z11my6efbHE1WvbcCgg6deqMFf6BX0SzzgPovB3p+giuHVwjD7gyYS3sdw/txxYPkY3+H/gWchf0FGw==\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 696,\"candidatesTokenCount\": 8,\"totalTokenCount\": 757,\"promptTokensDetails\": [{\"modality\": \"IMAGE\",\"tokenCount\": 520},{\"modality\": \"TEXT\",\"tokenCount\": 176}],\"thoughtsTokenCount\": 53,\"serviceTier\": \"standard\"},\"modelVersion\": \"gemini-3.5-flash\",\"responseId\": \"jXe0ar7CNdjBqtsPqMm2oAs\"}\r\n\r\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -149,7 +149,7 @@ describe("llm constructors", () => {
|
||||
const updated = LanguageModel.update(base, {
|
||||
route: responsesRoute,
|
||||
defaults: { generation: { maxTokens: 20 } },
|
||||
compatibility: { toolSchema: "gemini", requireFinishReason: false },
|
||||
compatibility: { sanitizer: "gemini", requireFinishReason: false },
|
||||
})
|
||||
const updatedInput = LanguageModel.input(updated)
|
||||
|
||||
@@ -157,7 +157,7 @@ describe("llm constructors", () => {
|
||||
expect(String(updated.id)).toBe("fake-model")
|
||||
expect(updated.route).toBe(responsesRoute)
|
||||
expect(updated.defaults?.generation).toEqual({ maxTokens: 20 })
|
||||
expect(updated.compatibility).toEqual({ toolSchema: "gemini", requireFinishReason: false })
|
||||
expect(updated.compatibility).toEqual({ sanitizer: "gemini", requireFinishReason: false })
|
||||
expect(updatedInput.defaults).toBe(updated.defaults)
|
||||
expect(updatedInput.compatibility).toBe(updated.compatibility)
|
||||
expect(String(updatedInput.provider)).toBe("fake")
|
||||
@@ -172,14 +172,14 @@ describe("llm constructors", () => {
|
||||
providerOptions: { parallelToolCalls: false },
|
||||
http: { body: { extra_body: true } },
|
||||
},
|
||||
compatibility: { toolSchema: "moonshot" },
|
||||
compatibility: { sanitizer: "moonshot" },
|
||||
})
|
||||
const request = LLM.request({ model, prompt: "Say hello." })
|
||||
|
||||
expect(request.model.defaults?.generation).toEqual({ maxTokens: 1_024, stop: ["END"] })
|
||||
expect(request.model.defaults?.providerOptions).toEqual({ parallelToolCalls: false })
|
||||
expect(request.model.defaults?.http).toEqual({ body: { extra_body: true } })
|
||||
expect(request.model.compatibility).toEqual({ toolSchema: "moonshot" })
|
||||
expect(request.model.compatibility).toEqual({ sanitizer: "moonshot" })
|
||||
expect(request.generation).toBeUndefined()
|
||||
expect(request.providerOptions).toBeUndefined()
|
||||
expect(request.http).toBeUndefined()
|
||||
|
||||
@@ -381,7 +381,7 @@ describe("Gemini route", () => {
|
||||
{
|
||||
name: "lookup",
|
||||
description: "Lookup data",
|
||||
parameters: { type: "object", properties: { query: { type: "string" } } },
|
||||
parametersJsonSchema: { type: "object", properties: { query: { type: "string" } } },
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -676,7 +676,7 @@ describe("Gemini route", () => {
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("sanitizes integer enums, dangling required, untyped arrays, and scalar object keys", () =>
|
||||
it.effect("normalizes the JSON Schema shapes Gemini rejects", () =>
|
||||
Effect.gen(function* () {
|
||||
const prepared = yield* compileRequest(
|
||||
LLM.request({
|
||||
@@ -689,11 +689,32 @@ describe("Gemini route", () => {
|
||||
description: "Lookup data",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
required: ["status", "missing"],
|
||||
required: ["ttl", "items", "parent", "missing"],
|
||||
properties: {
|
||||
status: { type: "integer", enum: [1, 2] },
|
||||
tags: { type: "array" },
|
||||
name: { type: "string", properties: { ignored: { type: "string" } }, required: ["ignored"] },
|
||||
ttl: { type: "number", minimum: 0, exclusiveMinimum: true, maximum: 60, exclusiveMaximum: false },
|
||||
pair: { type: "array", items: [{ type: "string" }, { type: "integer" }], additionalItems: false },
|
||||
items: { type: "array", items: { type: "string" } },
|
||||
required: { type: "boolean" },
|
||||
params: { $ref: "#/$defs/Json" },
|
||||
tree: { $ref: "#/$defs/Node" },
|
||||
chain: { $ref: "#/$defs/Link" },
|
||||
batch: { $ref: "#/$defs/Batch" },
|
||||
self: { $ref: "#" },
|
||||
parent: { $ref: "#" },
|
||||
cart: { type: "object", default: { items: ["a"] } },
|
||||
},
|
||||
dependentRequired: { items: ["ttl"] },
|
||||
$defs: {
|
||||
Json: {
|
||||
anyOf: [
|
||||
{ type: "string" },
|
||||
{ type: "array", items: { $ref: "#/$defs/Json" } },
|
||||
{ type: "object", additionalProperties: { $ref: "#/$defs/Json" } },
|
||||
],
|
||||
},
|
||||
Node: { type: "object", properties: { child: { $ref: "#/$defs/Node" } } },
|
||||
Link: { type: "object", required: ["next"], properties: { next: { $ref: "#/$defs/Link" } } },
|
||||
Batch: { type: "array", minItems: 1, items: { $ref: "#/$defs/Batch" } },
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -701,24 +722,35 @@ describe("Gemini route", () => {
|
||||
}),
|
||||
)
|
||||
|
||||
expect(prepared.body).toMatchObject({
|
||||
tools: [
|
||||
{
|
||||
functionDeclarations: [
|
||||
{
|
||||
parameters: {
|
||||
type: "object",
|
||||
required: ["status"],
|
||||
properties: {
|
||||
status: { type: "string", enum: ["1", "2"] },
|
||||
tags: { type: "array", items: { type: "string" } },
|
||||
name: { type: "string" },
|
||||
},
|
||||
},
|
||||
},
|
||||
expect(prepared.body.tools?.[0]?.functionDeclarations[0]?.parametersJsonSchema).toEqual({
|
||||
type: "object",
|
||||
required: ["ttl", "items", "parent"],
|
||||
properties: {
|
||||
ttl: { type: "number", exclusiveMinimum: 0, maximum: 60 },
|
||||
pair: { type: "array", prefixItems: [{ type: "string" }, { type: "integer" }], items: false },
|
||||
items: { type: "array", items: { type: "string" } },
|
||||
required: { type: "boolean" },
|
||||
params: { $ref: "#/$defs/Json" },
|
||||
tree: { $ref: "#/$defs/Node" },
|
||||
chain: { $ref: "#/$defs/Link" },
|
||||
batch: { $ref: "#/$defs/Batch" },
|
||||
self: { $ref: "#" },
|
||||
parent: {},
|
||||
cart: { type: "object", default: { items: ["a"] } },
|
||||
},
|
||||
dependentRequired: { items: ["ttl"] },
|
||||
$defs: {
|
||||
Json: {
|
||||
anyOf: [
|
||||
{ type: "string" },
|
||||
{ type: "array", items: { $ref: "#/$defs/Json" } },
|
||||
{ type: "object", additionalProperties: {} },
|
||||
],
|
||||
},
|
||||
],
|
||||
Node: { type: "object", properties: { child: { $ref: "#/$defs/Node" } } },
|
||||
Link: { type: "object", required: ["next"], properties: { next: {} } },
|
||||
Batch: { type: "array", minItems: 1, items: {} },
|
||||
},
|
||||
})
|
||||
}),
|
||||
)
|
||||
@@ -751,7 +783,7 @@ describe("Gemini route", () => {
|
||||
{
|
||||
name: "configure",
|
||||
description: "Configure the operation",
|
||||
parameters: {
|
||||
parametersJsonSchema: {
|
||||
type: "object",
|
||||
required: ["options"],
|
||||
properties: {
|
||||
@@ -765,55 +797,38 @@ describe("Gemini route", () => {
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("projects Gemini type arrays without narrowing their allowed values", () =>
|
||||
it.effect("sends standard JSON Schema tool parameters unchanged", () =>
|
||||
Effect.gen(function* () {
|
||||
const inputSchema = {
|
||||
type: "object",
|
||||
required: ["level"],
|
||||
properties: {
|
||||
level: { type: "integer", enum: [1, 2, 3] },
|
||||
status: { type: ["number", "string"], description: "Status filter" },
|
||||
maybe: { anyOf: [{ type: "string" }, { type: "null" }] },
|
||||
kind: { const: "fixed" },
|
||||
mode: { enum: ["fast", "safe"] },
|
||||
tags: { type: "array" },
|
||||
env: { type: "object", additionalProperties: { type: "string" } },
|
||||
action: {
|
||||
oneOf: [
|
||||
{ type: "object", properties: { type: { const: "move" }, to: { type: "string" } } },
|
||||
{ type: "object", properties: { type: { const: "delete" } } },
|
||||
],
|
||||
},
|
||||
item: { $ref: "#/$defs/Item" },
|
||||
},
|
||||
$defs: { Item: { type: "object", properties: { id: { type: "string" } }, required: ["id"] } },
|
||||
}
|
||||
const prepared = yield* compileRequest(
|
||||
LLM.request({
|
||||
model,
|
||||
prompt: "Use the tool.",
|
||||
tools: [
|
||||
{
|
||||
name: "filter",
|
||||
description: "Filter values",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
status: { type: ["number", "string"], description: "Status filter" },
|
||||
maybe: { type: ["string", "null"] },
|
||||
nothing: { type: ["null"] },
|
||||
explicit: { anyOf: [{ type: "string" }, { type: "null" }] },
|
||||
choice: { anyOf: [{ type: "string" }, { type: "number" }, { type: "null" }] },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
tools: [{ name: "filter", description: "Filter values", inputSchema }],
|
||||
}),
|
||||
)
|
||||
|
||||
expect(prepared.body.tools?.[0]?.functionDeclarations[0]?.parameters).toEqual({
|
||||
type: "object",
|
||||
properties: {
|
||||
status: {
|
||||
description: "Status filter",
|
||||
anyOf: [{ type: "number" }, { type: "string" }],
|
||||
},
|
||||
maybe: {
|
||||
nullable: true,
|
||||
anyOf: [{ type: "string" }],
|
||||
},
|
||||
nothing: {
|
||||
type: "null",
|
||||
},
|
||||
explicit: {
|
||||
type: "string",
|
||||
nullable: true,
|
||||
},
|
||||
choice: {
|
||||
anyOf: [{ type: "string" }, { type: "number" }],
|
||||
nullable: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(prepared.body.tools?.[0]?.functionDeclarations[0]?.parametersJsonSchema).toEqual(inputSchema)
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { HttpClientRequest } from "effect/unstable/http"
|
||||
import { LLM, Message, ToolCallPart } from "../../src/index.js"
|
||||
import { LanguageModel, LLM, Message, ToolCallPart } from "../../src/index.js"
|
||||
import { GoogleVertex, GoogleVertexChat, GoogleVertexMessages, GoogleVertexResponses } from "../../src/providers.js"
|
||||
import { LLMClient } from "../../src/route.js"
|
||||
import { compileRequest } from "../../src/route/client.js"
|
||||
@@ -414,6 +414,37 @@ describe("Google Vertex providers", () => {
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("applies Gemini schema rules to the Gemini API and Gemini models unless opted out", () =>
|
||||
Effect.gen(function* () {
|
||||
const vertex = { accessToken: "vertex-token", location: "us-central1", project: "vertex-project" }
|
||||
const inputSchema = { type: "object", required: ["query", "missing"], properties: { query: { type: "string" } } }
|
||||
const request = (model: Parameters<typeof LLM.request>[0]["model"]) =>
|
||||
compileRequest(
|
||||
LLM.request({
|
||||
model,
|
||||
prompt: "Use the tool.",
|
||||
tools: [{ name: "lookup", description: "Lookup.", inputSchema }],
|
||||
}),
|
||||
)
|
||||
|
||||
const normalized = { ...inputSchema, required: ["query"] }
|
||||
const tunedModel = GoogleVertex.configure(vertex).model("endpoints/1234567890")
|
||||
const tuned = yield* request(tunedModel)
|
||||
expect(tuned.body.tools?.[0]?.functionDeclarations[0]?.parametersJsonSchema).toEqual(normalized)
|
||||
const optedOut = yield* request(LanguageModel.update(tunedModel, { compatibility: { sanitizer: "none" } }))
|
||||
expect(optedOut.body.tools?.[0]?.functionDeclarations[0]?.parametersJsonSchema).toEqual(inputSchema)
|
||||
const geminiChat = yield* request(GoogleVertexChat.configure(vertex).model("google/gemini-3.8-flash"))
|
||||
expect(geminiChat.body.tools?.[0]?.function.parameters).toEqual(normalized)
|
||||
|
||||
const chat = yield* request(GoogleVertexChat.configure(vertex).model("deepseek-ai/deepseek-v3.2-maas"))
|
||||
expect(chat.body.tools?.[0]?.function.parameters).toEqual(inputSchema)
|
||||
const responses = yield* request(GoogleVertexResponses.configure(vertex).model("xai/grok-4.20-reasoning"))
|
||||
expect(responses.body.tools?.[0]).toMatchObject({ parameters: inputSchema })
|
||||
const messages = yield* request(GoogleVertexMessages.configure(vertex).model("claude-sonnet-4-6"))
|
||||
expect(messages.body.tools?.[0]).toMatchObject({ input_schema: inputSchema })
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("routes tuned Gemini models through their deployed endpoint", () =>
|
||||
Effect.gen(function* () {
|
||||
const response = yield* LLMClient.generate(
|
||||
|
||||
@@ -60,33 +60,51 @@ describe("tool schema projections", () => {
|
||||
})
|
||||
})
|
||||
|
||||
test("gemini handles numeric enums, dangling required fields, untyped arrays, and scalar object keys", () => {
|
||||
expect(
|
||||
ToolSchemaProjection.gemini({
|
||||
it.effect("selects tool schema handling from the model name unless compatibility is explicit", () =>
|
||||
Effect.gen(function* () {
|
||||
const route = OpenAIChat.route.with({
|
||||
endpoint: { baseURL: "https://api.openai.test/v1/" },
|
||||
auth: Auth.bearer("test"),
|
||||
})
|
||||
const original = {
|
||||
type: "object",
|
||||
required: ["status", "missing"],
|
||||
properties: {
|
||||
status: { type: "integer", enum: [1, 2] },
|
||||
tags: { type: "array" },
|
||||
name: { type: "string", properties: { ignored: { type: "string" } }, required: ["ignored"] },
|
||||
},
|
||||
}),
|
||||
).toEqual({
|
||||
type: "object",
|
||||
required: ["status"],
|
||||
properties: {
|
||||
status: { type: "string", enum: ["1", "2"] },
|
||||
tags: { type: "array", items: { type: "string" } },
|
||||
name: { type: "string" },
|
||||
},
|
||||
})
|
||||
})
|
||||
required: ["mode", "missing"],
|
||||
properties: { mode: { enum: ["fast", "safe"] } },
|
||||
}
|
||||
const parameters = (model: ReturnType<typeof route.model>) =>
|
||||
compileRequest(
|
||||
LLM.request({
|
||||
model,
|
||||
prompt: "Use the tool.",
|
||||
tools: [{ name: "lookup", description: "Lookup data.", inputSchema: original }],
|
||||
}),
|
||||
).pipe(Effect.map((prepared) => prepared.body.tools?.[0]?.function.parameters))
|
||||
const gemini = { ...original, required: ["mode"] }
|
||||
const moonshot = { ...original, properties: { mode: { type: "string", enum: ["fast", "safe"] } } }
|
||||
|
||||
expect(yield* parameters(route.model({ id: "google/Gemini-3.8-Flash" }))).toEqual(gemini)
|
||||
expect(
|
||||
yield* parameters(route.model({ id: "my-tuned-endpoint", compatibility: { sanitizer: "gemini" } })),
|
||||
).toEqual(gemini)
|
||||
expect(
|
||||
yield* parameters(route.model({ id: "google/gemini-3.8-flash", compatibility: { sanitizer: "moonshot" } })),
|
||||
).toEqual(moonshot)
|
||||
expect(yield* parameters(route.model({ id: "moonshotai/Kimi-K3" }))).toEqual(moonshot)
|
||||
expect(
|
||||
yield* parameters(route.model({ id: "google/gemini-3.8-flash", compatibility: { sanitizer: "none" } })),
|
||||
).toEqual(original)
|
||||
expect(
|
||||
yield* parameters(route.model({ id: "moonshotai/Kimi-K3", compatibility: { sanitizer: "none" } })),
|
||||
).toEqual(original)
|
||||
expect(yield* parameters(route.model({ id: "gpt-6-luna" }))).toEqual(original)
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("applies model compatibility without changing schema semantics", () =>
|
||||
Effect.gen(function* () {
|
||||
const model = OpenAIChat.route
|
||||
.with({ endpoint: { baseURL: "https://api.openai.test/v1/" }, auth: Auth.bearer("test") })
|
||||
.model({ id: "kimi-k2", compatibility: { toolSchema: "moonshot" } })
|
||||
.model({ id: "kimi-k2", compatibility: { sanitizer: "moonshot" } })
|
||||
const prepared = yield* compileRequest(
|
||||
LLM.request({
|
||||
model,
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
- When migrating existing copy to i18n, preserve the English text byte-for-byte unless the task explicitly requests a copy change.
|
||||
- NEVER change existing English text or English keys to facilitate translation. English is intentional, designer-written source copy; adapt locale-specific translations and i18n mechanics around it.
|
||||
- Keep locale complexity behind the shared typed i18n APIs. Feature and component code should use `language.t(...)` for ordinary copy and `language.plural(baseKey, count, params)` for count-sensitive copy. It must not inspect the locale, call `Intl.PluralRules`, construct or select plural-category keys such as `.one` or `.other`, or branch on locale-specific grammar.
|
||||
- Do not compose translated count phrases or sentence fragments in feature components. Add a focused language-context operation that owns plural selection and composition when one UI concept needs coordinated keys.
|
||||
- Prefer complete translated phrases. Do not concatenate grammatical fragments or make call sites assemble sentences. Keep placeholders to irreducible dynamic values such as names, paths, and counts.
|
||||
- If a translation cannot be expressed by the current API, deepen the shared language/UI i18n module so one typed call owns locale selection, plural resolution, fallback, and interpolation. Do not leak that machinery into product code.
|
||||
- Do not translate from model knowledge alone. Verify terminology and grammar with Unicode CLDR locale/plural data, Microsoft Localization Style Guides and terminology, Apple localization/style guidance and localized platform UI, Mozilla localization style guides, Mozilla Pontoon, and the Firefox localization corpus at `github.com/mozilla-l10n/firefox-l10n`.
|
||||
|
||||
@@ -122,6 +122,40 @@ story("does not mask or pad controls when they fit", async ({ mount }) => {
|
||||
await expect(controls).toHaveCSS("padding-inline-end", "0px")
|
||||
})
|
||||
|
||||
story("grows suggestions while preserving visible timeline context", async ({ mount }) => {
|
||||
const component = await mount("opencode-composer-flow--constrained-command-suggestions")
|
||||
const boundary = component.locator('[data-slot="composer-suggestion-boundary-story"]')
|
||||
const suggestions = component.locator('[data-component="composer-suggestions"]')
|
||||
|
||||
await expect(suggestions).toHaveCSS("max-height", "166px")
|
||||
await expect(suggestions).toHaveCSS("scroll-padding-bottom", "18px")
|
||||
await expect.poll(() => suggestions.evaluate((element) => element.scrollHeight > element.clientHeight)).toBe(true)
|
||||
await expect
|
||||
.poll(async () => {
|
||||
const menu = await suggestions.boundingBox()
|
||||
const items = await suggestions.locator("[data-suggestion-id]").evaluateAll((elements) =>
|
||||
elements.map((element) => {
|
||||
const rect = element.getBoundingClientRect()
|
||||
return { top: rect.top, bottom: rect.bottom }
|
||||
}),
|
||||
)
|
||||
if (!menu) return false
|
||||
const bottom = menu.y + menu.height
|
||||
return items.some((item) => item.top < bottom && item.bottom > bottom)
|
||||
})
|
||||
.toBe(true)
|
||||
|
||||
await boundary.evaluate((element) => {
|
||||
element.style.height = "400px"
|
||||
})
|
||||
await expect(suggestions).toHaveCSS("max-height", "306px")
|
||||
})
|
||||
|
||||
story("ignores a detached suggestion boundary", async ({ mount }) => {
|
||||
const component = await mount("opencode-composer-flow--detached-command-suggestion-boundary")
|
||||
await expect(component.locator('[data-component="composer-suggestions"]')).toHaveCSS("max-height", "306px")
|
||||
})
|
||||
|
||||
// ThemeProvider writes resolved token values into a <style> block, so toggling data-color-scheme by hand
|
||||
// leaves every --v2-* variable at its previous value. Switch themes through the Storybook global instead.
|
||||
for (const [theme, background] of [
|
||||
@@ -180,6 +214,23 @@ for (const draft of ["empty-draft", "multiline-draft", "mixed-attachments"]) {
|
||||
})
|
||||
}
|
||||
|
||||
story.describe("touch attachments", () => {
|
||||
story.use({ hasTouch: true, isMobile: true, viewport: { width: 390, height: 844 } })
|
||||
|
||||
story("keeps attachment remove buttons visible without hover", async ({ mount, page }) => {
|
||||
const component = await mount("opencode-composer-flow--mixed-attachments")
|
||||
expect(await page.evaluate(() => matchMedia("(hover: none)").matches)).toBe(true)
|
||||
|
||||
const remove = component.getByRole("button", { name: "Remove attachment", exact: true })
|
||||
await expect(remove).not.toHaveCount(0)
|
||||
for (const button of await remove.all()) await expect(button).toHaveCSS("opacity", "1")
|
||||
|
||||
const count = await remove.count()
|
||||
await remove.first().tap()
|
||||
await expect(remove).toHaveCount(count - 1)
|
||||
})
|
||||
})
|
||||
|
||||
story("renders a draft once and supports editing, caret restoration, and failure recovery", async ({ mount, page }) => {
|
||||
await page.addInitScript(() => {
|
||||
const replace = Element.prototype.replaceChildren
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { expect, story } from "../../storybook/playwright/story"
|
||||
|
||||
story("shows question navigation shortcuts", async ({ mount, page }) => {
|
||||
const component = await mount("app-current-session-surface--question-request")
|
||||
const shortcut = await page.evaluate(() => (/Mac|iPhone|iPad|iPod/.test(navigator.platform) ? "⌘⏎" : "Ctrl+⏎"))
|
||||
const next = component.getByRole("button", { name: "Next", exact: true })
|
||||
await expect(next.locator('[data-slot="question-submit-shortcut"]')).toHaveText(shortcut)
|
||||
await next.click()
|
||||
await expect(component.getByRole("button", { name: "Submit", exact: true })).toContainText(shortcut)
|
||||
const back = component.getByRole("button", { name: "Back", exact: true })
|
||||
const backShortcut = await page.evaluate(() => (/Mac|iPhone|iPad|iPod/.test(navigator.platform) ? "⌘[" : "Alt+←"))
|
||||
await expect(back).toHaveText("Back")
|
||||
await back.hover()
|
||||
await expect(page.getByRole("tooltip")).toContainText(backShortcut)
|
||||
await page.keyboard.press(
|
||||
await page.evaluate(() => (/Mac|iPhone|iPad|iPod/.test(navigator.platform) ? "Meta+[" : "Alt+ArrowLeft")),
|
||||
)
|
||||
await expect(next).toBeVisible()
|
||||
})
|
||||
@@ -158,6 +158,10 @@ for (const direction of ["ltr", "rtl"]) {
|
||||
story(`fits narrow and wide layouts in ${direction}, ${theme}`, async ({ mount, page }, testInfo) => {
|
||||
await page.setViewportSize({ width: 900, height: 900 })
|
||||
const component = await mount("settings-timeline-detail--interactive", { globals: { direction, theme } })
|
||||
await expect(component.locator('[data-slot="timeline-detail-scale"]')).toHaveCSS("margin-top", "16px")
|
||||
const advanced = component.locator('[data-slot="timeline-detail-advanced"]')
|
||||
await expect(advanced).toHaveCSS("margin-top", "0px")
|
||||
await expect(advanced).toHaveCSS("padding-top", "8px")
|
||||
await expect(component.locator('[data-slot="timeline-detail-summary"]')).toHaveCSS(
|
||||
"color",
|
||||
await component
|
||||
@@ -177,28 +181,46 @@ for (const direction of ["ltr", "rtl"]) {
|
||||
),
|
||||
)
|
||||
if (theme === "light") {
|
||||
await expect(track.locator("span").first()).toHaveCSS("background-image", "none")
|
||||
await expect(track.locator("span").last()).toHaveCSS("background-image", "none")
|
||||
await expect(track).toHaveCSS(
|
||||
"--timeline-detail-marker-background",
|
||||
await track.evaluate((element) => getComputedStyle(element).getPropertyValue("--v2-grey-500").trim()),
|
||||
)
|
||||
}
|
||||
if (theme === "dark") {
|
||||
await expect(track.locator("span").first()).not.toHaveCSS("background-image", "none")
|
||||
await expect(track.locator("span").last()).not.toHaveCSS("background-image", "none")
|
||||
}
|
||||
await page.screenshot({ path: testInfo.outputPath(`timeline-${theme}-${direction}.png`) })
|
||||
const list = component.locator('[data-slot="timeline-detail-list"]')
|
||||
const columns = component.locator('[data-slot="timeline-detail-columns"]')
|
||||
await expect(component.locator('[data-slot="timeline-detail-categories"]')).toHaveCSS("margin-top", "0px")
|
||||
const advancedTrigger = component.getByRole("button", { name: "Advanced", exact: true })
|
||||
expect(
|
||||
await advancedTrigger.evaluate((element) => {
|
||||
const trigger = element.getBoundingClientRect()
|
||||
const heading = document
|
||||
.querySelector('[data-slot="timeline-detail-columns"] > :nth-child(2)')!
|
||||
.getBoundingClientRect()
|
||||
return Math.abs(trigger.y + trigger.height / 2 - (heading.y + heading.height / 2))
|
||||
}),
|
||||
).toBeLessThan(1)
|
||||
expect(
|
||||
await list.evaluate((element) => {
|
||||
const list = element.getBoundingClientRect()
|
||||
const trigger = document
|
||||
.querySelector('[data-slot="timeline-detail-advanced"] > [data-slot="collapsible-trigger"]')!
|
||||
.getBoundingClientRect()
|
||||
return list.y - trigger.bottom
|
||||
}),
|
||||
).toBe(8)
|
||||
for (const [column, field] of [
|
||||
[2, "placement"],
|
||||
[3, "details"],
|
||||
] as const) {
|
||||
const heading = await component
|
||||
.locator(`[data-slot="timeline-detail-columns"] > :nth-child(${column})`)
|
||||
.evaluate((element) => {
|
||||
const rect = element.getBoundingClientRect()
|
||||
return rect.x + rect.width / 2
|
||||
})
|
||||
const heading = await columns.locator(`> :nth-child(${column})`).evaluate((element) => {
|
||||
const rect = element.getBoundingClientRect()
|
||||
return rect.x + rect.width / 2
|
||||
})
|
||||
const toggle = await component
|
||||
.locator(`[data-category="shell"][data-field="${field}"] [data-slot="switch-control"]`)
|
||||
.evaluate((element) => {
|
||||
@@ -207,7 +229,7 @@ for (const direction of ["ltr", "rtl"]) {
|
||||
})
|
||||
expect(Math.abs(heading - toggle)).toBeLessThan(1)
|
||||
}
|
||||
await expect(component.locator('[data-slot="timeline-detail-activity"]').first()).toHaveCSS("gap", "12px")
|
||||
await expect(component.locator('[data-slot="timeline-detail-activity"]').first()).toHaveCSS("gap", "8px")
|
||||
for (const width of [900, 320]) {
|
||||
await page.setViewportSize({ width, height: 900 })
|
||||
await expect(component.getByRole("switch", { name: "Shell grouped", exact: true })).toBeVisible()
|
||||
@@ -227,6 +249,7 @@ for (const direction of ["ltr", "rtl"]) {
|
||||
|
||||
const slider = component.getByRole("slider", { name: "Timeline detail" })
|
||||
const track = component.locator('[data-slot="timeline-detail-track"]')
|
||||
await expect(slider).not.toHaveCSS("cursor", "pointer")
|
||||
expect(await track.evaluate((element) => element.getBoundingClientRect().width)).toBe(
|
||||
await component
|
||||
.locator('[data-slot="timeline-detail-scale"]')
|
||||
@@ -237,6 +260,11 @@ for (const direction of ["ltr", "rtl"]) {
|
||||
for (const position of [0, 1, 2, 3, 4]) {
|
||||
if (position > 0) await slider.press("ArrowUp")
|
||||
await expect(track).toHaveCSS("--timeline-detail-progress", `${position * 25}%`)
|
||||
await expect(track.locator("span[data-selected]")).toHaveCount(position + 1)
|
||||
await expect(track.locator("span").nth(position)).toHaveCSS(
|
||||
"background-color",
|
||||
await track.evaluate((element) => getComputedStyle(element, "::before").backgroundColor),
|
||||
)
|
||||
const fill = await track.evaluate((element) => {
|
||||
const style = getComputedStyle(element, "::before")
|
||||
return {
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import type { SessionMessageInfo } from "@opencode/client/promise"
|
||||
import { base64Encode } from "@opencode/util/encode"
|
||||
import { expect, test } from "@playwright/test"
|
||||
import { mockOpenCodeServer } from "../utils/mock-server"
|
||||
import { expectSessionTitle } from "../utils/waits"
|
||||
|
||||
const directory = "C:/OpenCode/ArtifactReopen"
|
||||
const projectID = "proj_artifact_reopen"
|
||||
const sessionID = "ses_artifact_reopen"
|
||||
const title = "Artifact reopen"
|
||||
const server = `http://${process.env.PLAYWRIGHT_SERVER_HOST ?? "127.0.0.1"}:${process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"}`
|
||||
const messages = [
|
||||
{ id: "msg_prompt", type: "user", text: "Write the shopping list", time: { created: 1 } },
|
||||
{
|
||||
id: "msg_reply",
|
||||
type: "assistant",
|
||||
agent: "build",
|
||||
model: { id: "test", providerID: "opencode" },
|
||||
content: [{ type: "text", text: "Updated [shopping.txt](shopping.txt)." }],
|
||||
time: { created: 2, completed: 3 },
|
||||
},
|
||||
] satisfies SessionMessageInfo[]
|
||||
|
||||
test.use({ viewport: { width: 1440, height: 900 } })
|
||||
|
||||
test("rereads a file each time an artifact link opens it", async ({ page }) => {
|
||||
const file = { content: "first draft" }
|
||||
await mockOpenCodeServer(page, {
|
||||
directory,
|
||||
project: {
|
||||
id: projectID,
|
||||
worktree: directory,
|
||||
canonical: directory,
|
||||
vcs: "git",
|
||||
name: "artifact-reopen",
|
||||
time: { created: 1, updated: 1 },
|
||||
sandboxes: [],
|
||||
},
|
||||
provider: {
|
||||
all: [
|
||||
{
|
||||
id: "opencode",
|
||||
name: "OpenCode",
|
||||
models: { test: { id: "test", name: "Test", variants: {}, limit: { context: 200_000 } } },
|
||||
},
|
||||
],
|
||||
connected: ["opencode"],
|
||||
default: { providerID: "opencode", modelID: "test" },
|
||||
},
|
||||
sessions: [
|
||||
{
|
||||
id: sessionID,
|
||||
slug: "artifact-reopen",
|
||||
projectID,
|
||||
directory,
|
||||
title,
|
||||
agent: "build",
|
||||
model: { id: "test", providerID: "opencode" },
|
||||
version: "dev",
|
||||
time: { created: 1, updated: 3 },
|
||||
},
|
||||
],
|
||||
fileList: () => [],
|
||||
fileContent: (path) => (path === "shopping.txt" ? file : ""),
|
||||
pageMessages: () => ({ items: messages }),
|
||||
})
|
||||
|
||||
await page.goto(`/server/${base64Encode(server)}/session/${sessionID}`)
|
||||
await expectSessionTitle(page, title)
|
||||
|
||||
const link = page.getByRole("link", { name: "shopping.txt", exact: true })
|
||||
const panel = page.locator("#review-panel")
|
||||
const tab = panel.getByRole("tab", { name: "shopping.txt" })
|
||||
|
||||
await link.click()
|
||||
await expect(tab).toHaveAttribute("aria-selected", "true")
|
||||
await expect(panel.getByText("first draft", { exact: true })).toBeVisible()
|
||||
|
||||
file.content = "second draft"
|
||||
await tab.locator("..").getByRole("button", { name: "Close tab" }).click()
|
||||
await expect(tab).toHaveCount(0)
|
||||
|
||||
await link.click()
|
||||
await expect(tab).toHaveAttribute("aria-selected", "true")
|
||||
await expect(panel.getByText("second draft", { exact: true })).toBeVisible()
|
||||
await expect(panel.getByText("first draft", { exact: true })).toHaveCount(0)
|
||||
})
|
||||
@@ -1,337 +1,22 @@
|
||||
import { expect, test, type Page } from "@playwright/test"
|
||||
import { mockOpenCodeServer, currentSession } from "../utils/mock-server"
|
||||
import { openWithDirection } from "../utils/direction"
|
||||
import { expect, test } from "@playwright/test"
|
||||
import { mockOpenCodeServer } from "../utils/mock-server"
|
||||
import { expectAppVisible } from "../utils/waits"
|
||||
|
||||
const directory = "/workspace/summary-project"
|
||||
const workspace = "/workspace/existing-worktree"
|
||||
const createdWorkspace = "/workspace/created-worktree"
|
||||
const draftID = "draft_summary"
|
||||
const secondDraftID = "draft_summary_other"
|
||||
const directory = "/workspace/summary-project"
|
||||
const server = `http://${process.env.PLAYWRIGHT_SERVER_HOST ?? "127.0.0.1"}:${process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"}`
|
||||
const draftPath = `/new-session?draftId=${draftID}`
|
||||
|
||||
for (const rtl of [false, true]) {
|
||||
test(`new session summary shows project extensions and follows workspace selection in ${rtl ? "rtl" : "ltr"}`, async ({
|
||||
page,
|
||||
}, testInfo) => {
|
||||
const mock = await openDraft(page, "main", { direction: rtl ? "rtl" : "ltr" })
|
||||
await expect(page.locator("html")).toHaveAttribute("dir", rtl ? "rtl" : "ltr")
|
||||
await expect(page.locator("html")).toHaveAttribute("lang", "en")
|
||||
const trigger = page.getByRole("button", { name: "Session details", exact: true })
|
||||
await expect
|
||||
.poll(async () => {
|
||||
const button = await trigger.boundingBox()
|
||||
const view = await page.locator('[data-component="new-session"]').boundingBox()
|
||||
if (!button || !view) return false
|
||||
const gap = rtl ? button.x - view.x : view.x + view.width - button.x - button.width
|
||||
return Math.abs(gap - 12) <= 1 && Math.abs(button.y + button.height / 2 - view.y - 24) <= 1
|
||||
})
|
||||
.toBe(true)
|
||||
await trigger.click()
|
||||
const summary = page.getByRole("dialog", { name: "Session details", exact: true })
|
||||
await expect(summary.getByRole("button", { name: "summary-project", exact: true })).toHaveAttribute(
|
||||
"aria-expanded",
|
||||
"true",
|
||||
)
|
||||
await expect(summary.getByRole("button", { name: "Extensions", exact: true })).toHaveAttribute(
|
||||
"aria-expanded",
|
||||
"true",
|
||||
)
|
||||
await expect
|
||||
.poll(async () => {
|
||||
const button = await trigger.boundingBox()
|
||||
const project = await summary.locator('[data-section="project"]').boundingBox()
|
||||
const server = await summary.locator('[data-section="server"]').boundingBox()
|
||||
if (!button || !project || !server) return
|
||||
return {
|
||||
top: project.y - button.y - button.height,
|
||||
cards: server.y - project.y - project.height,
|
||||
}
|
||||
})
|
||||
.toEqual({ top: 12, cards: 8 })
|
||||
await testInfo.attach(`new-session-summary-${rtl ? "rtl" : "ltr"}`, {
|
||||
body: await page.screenshot(),
|
||||
contentType: "image/png",
|
||||
})
|
||||
for (const [name, item] of [
|
||||
["MCP", "summary-mcp"],
|
||||
["Plugins", "project-plugin"],
|
||||
["Skills", "summary-skill"],
|
||||
["LSP", "typescript"],
|
||||
]) {
|
||||
await summary.getByRole("button", { name, exact: true }).click()
|
||||
await expect(page.getByRole("dialog", { name, exact: true }).getByText(item, { exact: true })).toBeVisible()
|
||||
}
|
||||
await page.keyboard.press("Escape")
|
||||
await summary.getByRole("button", { name: "Local repository", exact: true }).click()
|
||||
const worktreeMenu = page.getByRole("menu", { name: "Local repository", exact: true })
|
||||
await expect
|
||||
.poll(async () => {
|
||||
const menu = await worktreeMenu.boundingBox()
|
||||
const panel = await summary.locator('[data-component="session-summary-panel"]').boundingBox()
|
||||
if (!menu || !panel) return false
|
||||
return rtl ? menu.x >= panel.x + panel.width : menu.x + menu.width <= panel.x
|
||||
})
|
||||
.toBe(true)
|
||||
await expect(page.getByRole("menuitem", { name: "existing-worktree", exact: true })).toBeHidden()
|
||||
await worktreeMenu.getByRole("menuitem", { name: "Worktree", exact: true }).press(rtl ? "ArrowLeft" : "ArrowRight")
|
||||
await expect(page.getByRole("menu", { name: "Worktree", exact: true })).toBeVisible()
|
||||
await page.keyboard.press("Enter")
|
||||
await expect(summary.getByRole("button", { name: "existing-worktree", exact: true })).toBeVisible()
|
||||
await summary.getByRole("button", { name: "MCP", exact: true }).click()
|
||||
const mcp = page.getByRole("dialog", { name: "MCP", exact: true })
|
||||
const toggle = mcp.getByRole("switch", { name: "summary-mcp", exact: true })
|
||||
await expect(toggle).not.toBeChecked()
|
||||
await expect(toggle).toBeEnabled()
|
||||
await mcp.getByText("summary-mcp", { exact: true }).click()
|
||||
await expect(toggle).toBeChecked()
|
||||
await expect(toggle).toBeEnabled()
|
||||
expect(mock.calls).toEqual([{ type: "mcp", directory: workspace, enabled: true }])
|
||||
expect(mock.status.get(directory)).toBe("connected")
|
||||
await summary.getByRole("button", { name: "Plugins", exact: true }).click()
|
||||
await expect(
|
||||
page.getByRole("dialog", { name: "Plugins", exact: true }).getByText("workspace-plugin", { exact: true }),
|
||||
).toBeVisible()
|
||||
})
|
||||
}
|
||||
|
||||
test("non-Git folders show their status without offering worktree actions", async ({ page }) => {
|
||||
await openDraft(page, "main", { git: false })
|
||||
await page.getByRole("button", { name: "Session details", exact: true }).click()
|
||||
const summary = page.getByRole("dialog", { name: "Session details", exact: true })
|
||||
await expect(summary.getByText("No Git", { exact: true })).toBeVisible()
|
||||
await expect(summary.getByRole("button", { name: "Local repository", exact: true })).toHaveCount(0)
|
||||
await expect(summary.getByRole("button", { name: "New worktree", exact: true })).toHaveCount(0)
|
||||
await summary.getByRole("button", { name: "MCP", exact: true }).click()
|
||||
await expect(
|
||||
page.getByRole("dialog", { name: "MCP", exact: true }).getByRole("switch", { name: "summary-mcp", exact: true }),
|
||||
).toBeEnabled()
|
||||
})
|
||||
|
||||
test("submits locally after changing a new worktree draft to Local", async ({ page }) => {
|
||||
const mock = await openDraft(page, "create", { currentDirectory: workspace })
|
||||
await page.getByRole("button", { name: "New worktree", exact: true }).click()
|
||||
await page.getByRole("menuitem", { name: "Local repository", exact: true }).click()
|
||||
await page.locator('[data-component="composer-editor"]').fill("Run locally")
|
||||
await page.locator('[data-action="composer-submit"]').click()
|
||||
await expect.poll(() => mock.calls.find((call) => call.type === "session")?.directory).toBe(directory)
|
||||
})
|
||||
|
||||
test("new worktree MCP choices persist per draft and apply before the first prompt", async ({ page }, testInfo) => {
|
||||
const mock = await openDraft(page, "create")
|
||||
await page.locator('[data-component="composer-editor"]').fill("Use my selected MCPs")
|
||||
await page.getByRole("button", { name: "Session details", exact: true }).click()
|
||||
await page.getByRole("button", { name: "MCP", exact: true }).click()
|
||||
const menu = page.getByRole("dialog", { name: "MCP", exact: true })
|
||||
await expect(menu.locator('[data-slot="mcp-preview-hint"]')).toHaveText("Applies when the worktree is created")
|
||||
await expect(menu).toHaveCSS("opacity", "1")
|
||||
await testInfo.attach("new-worktree-mcp-preview", { body: await page.screenshot(), contentType: "image/png" })
|
||||
const toggle = menu.getByRole("switch", { name: "summary-mcp", exact: true })
|
||||
await expect(toggle).toBeChecked()
|
||||
await menu.getByText("summary-mcp", { exact: true }).click()
|
||||
await expect(toggle).not.toBeChecked()
|
||||
expect(mock.calls).toEqual([])
|
||||
await expect
|
||||
.poll(() =>
|
||||
page.evaluate(
|
||||
() =>
|
||||
JSON.parse(localStorage.getItem("opencode.window.browser.dat:tabs") ?? "[]").find(
|
||||
(tab: { draftID?: string }) => tab.draftID === "draft_summary",
|
||||
)?.mcp?.states,
|
||||
),
|
||||
)
|
||||
.toEqual({ "summary-mcp": false })
|
||||
|
||||
await page.goto(`/new-session?draftId=${secondDraftID}`)
|
||||
await page.getByRole("button", { name: "Session details", exact: true }).click()
|
||||
await page.getByRole("button", { name: "MCP", exact: true }).click()
|
||||
await expect(toggle).toBeChecked()
|
||||
await page.goto(draftPath)
|
||||
await page.getByRole("button", { name: "Session details", exact: true }).click()
|
||||
await page.getByRole("button", { name: "MCP", exact: true }).click()
|
||||
await expect(toggle).not.toBeChecked()
|
||||
expect(mock.calls).toEqual([])
|
||||
await page.keyboard.press("Escape")
|
||||
await page.keyboard.press("Escape")
|
||||
await expect(page.locator('[data-component="composer-editor"]')).toHaveText("Use my selected MCPs")
|
||||
await page.locator('[data-action="composer-submit"]').click()
|
||||
await expect.poll(() => mock.prompts.length).toBe(1)
|
||||
expect(mock.calls).toEqual([
|
||||
{ type: "worktree", directory },
|
||||
{ type: "mcp", directory: createdWorkspace, enabled: false },
|
||||
{ type: "session", directory: createdWorkspace },
|
||||
{ type: "prompt", directory: createdWorkspace },
|
||||
])
|
||||
expect(mock.prompts[0].body.text).toBe("Use my selected MCPs")
|
||||
expect(mock.status.get(directory)).toBe("connected")
|
||||
})
|
||||
|
||||
test("the first prompt waits for a live MCP toggle", async ({ page }) => {
|
||||
const mock = await openDraft(page)
|
||||
const release = Promise.withResolvers<void>()
|
||||
mock.state.hold = release.promise
|
||||
await page.locator('[data-component="composer-editor"]').fill("Wait for the MCP update")
|
||||
await page.getByRole("button", { name: "Session details", exact: true }).click()
|
||||
await page.getByRole("button", { name: "MCP", exact: true }).click()
|
||||
const menu = page.getByRole("dialog", { name: "MCP", exact: true })
|
||||
await expect(menu.getByRole("switch", { name: "summary-mcp", exact: true })).toBeEnabled()
|
||||
try {
|
||||
await menu.getByText("summary-mcp", { exact: true }).click()
|
||||
await expect.poll(() => mock.calls.length).toBe(1)
|
||||
await page.keyboard.press("Escape")
|
||||
await page.keyboard.press("Escape")
|
||||
await page.locator('[data-action="composer-submit"]').click()
|
||||
await expect(page).toHaveURL(draftPath)
|
||||
expect(mock.calls).toEqual([{ type: "mcp", directory, enabled: false }])
|
||||
expect(mock.prompts).toEqual([])
|
||||
} finally {
|
||||
release.resolve()
|
||||
}
|
||||
await expect.poll(() => mock.prompts.length).toBe(1)
|
||||
expect(mock.calls).toEqual([
|
||||
{ type: "mcp", directory, enabled: false },
|
||||
{ type: "session", directory },
|
||||
{ type: "prompt", directory },
|
||||
])
|
||||
})
|
||||
|
||||
test("changing worktrees does not wait for another directory's pending MCP update", async ({ page }) => {
|
||||
const mock = await openDraft(page)
|
||||
const release = Promise.withResolvers<void>()
|
||||
mock.state.hold = release.promise
|
||||
mock.state.holdDirectory = directory
|
||||
await page.locator('[data-component="composer-editor"]').fill("Run in the selected worktree")
|
||||
await page.getByRole("button", { name: "Session details", exact: true }).click()
|
||||
const summary = page.getByRole("dialog", { name: "Session details", exact: true })
|
||||
await summary.getByRole("button", { name: "MCP", exact: true }).click()
|
||||
const menu = page.getByRole("dialog", { name: "MCP", exact: true })
|
||||
try {
|
||||
await expect(menu.getByRole("switch", { name: "summary-mcp", exact: true })).toBeEnabled()
|
||||
await menu.getByText("summary-mcp", { exact: true }).click()
|
||||
await expect.poll(() => mock.calls.length).toBe(1)
|
||||
await page.keyboard.press("Escape")
|
||||
await summary.getByRole("button", { name: "Local repository", exact: true }).click()
|
||||
await page.getByRole("menuitem", { name: "Worktree", exact: true }).click()
|
||||
await page.getByRole("menuitem", { name: "existing-worktree", exact: true }).click()
|
||||
await summary.getByRole("button", { name: "MCP", exact: true }).click()
|
||||
const toggle = menu.getByRole("switch", { name: "summary-mcp", exact: true })
|
||||
await expect(toggle).toBeEnabled()
|
||||
await expect(toggle).not.toBeChecked()
|
||||
await menu.getByText("summary-mcp", { exact: true }).click()
|
||||
await expect(toggle).toBeChecked()
|
||||
await expect(toggle).toBeEnabled()
|
||||
await page.keyboard.press("Escape")
|
||||
await page.keyboard.press("Escape")
|
||||
await page.locator('[data-action="composer-submit"]').click()
|
||||
await expect.poll(() => mock.prompts.length).toBe(1)
|
||||
expect(mock.calls.find((call) => call.type === "session")?.directory).toBe(workspace)
|
||||
expect(mock.status.get(directory)).toBe("connected")
|
||||
} finally {
|
||||
release.resolve()
|
||||
}
|
||||
})
|
||||
|
||||
test("failed MCP preparation restores the draft and reuses the created worktree", async ({ page }) => {
|
||||
const mock = await openDraft(page, "create")
|
||||
mock.state.fail = true
|
||||
await page.locator('[data-component="composer-editor"]').fill("Keep this prompt on failure")
|
||||
await page.getByRole("button", { name: "Session details", exact: true }).click()
|
||||
await page.getByRole("button", { name: "MCP", exact: true }).click()
|
||||
await page.getByRole("dialog", { name: "MCP", exact: true }).getByText("summary-mcp", { exact: true }).click()
|
||||
await page.keyboard.press("Escape")
|
||||
await page.keyboard.press("Escape")
|
||||
await page.locator('[data-action="composer-submit"]').click()
|
||||
await expect(page.getByText("Request failed", { exact: true })).toBeVisible()
|
||||
await expect(page).toHaveURL(draftPath)
|
||||
await expect(page.locator('[data-component="composer-editor"]')).toHaveText("Keep this prompt on failure")
|
||||
await expect(page.getByRole("button", { name: "created-worktree", exact: true })).toBeVisible()
|
||||
expect(mock.prompts).toEqual([])
|
||||
expect(mock.calls.map((call) => call.type)).toEqual(["worktree", "mcp"])
|
||||
mock.state.fail = false
|
||||
await expect(page.locator('[data-action="composer-submit"]')).toBeEnabled()
|
||||
await page.locator('[data-action="composer-submit"]').click()
|
||||
await expect.poll(() => mock.prompts.length).toBe(1)
|
||||
expect(mock.calls.filter((call) => call.type === "worktree")).toHaveLength(1)
|
||||
expect(mock.status.get(createdWorkspace)).toBe("disabled")
|
||||
expect(mock.prompts[0].body.text).toBe("Keep this prompt on failure")
|
||||
})
|
||||
|
||||
test("new worktree sign-in completes before the draft can send", async ({ page, context }) => {
|
||||
const mock = await openDraft(page, "create")
|
||||
mock.status.set(createdWorkspace, "needs_auth")
|
||||
const attempts: string[] = []
|
||||
await context.route("https://auth.example.test/**", (route) => route.fulfill({ body: "Sign in" }))
|
||||
await page.route("**/api/integration/**", (route) => {
|
||||
if (route.request().method() === "OPTIONS") return route.fallback()
|
||||
if (route.request().method() === "POST") {
|
||||
attempts.push(new URL(route.request().url()).searchParams.get("location[directory]") ?? "")
|
||||
return route.fulfill({
|
||||
json: { location: { directory: createdWorkspace }, data: { url: "https://auth.example.test/authorize" } },
|
||||
})
|
||||
}
|
||||
return route.fulfill({
|
||||
json: {
|
||||
location: { directory: createdWorkspace },
|
||||
data: {
|
||||
id: "summary-oauth",
|
||||
methods: [{ id: "oauth", type: "oauth" }],
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
await page.locator('[data-component="composer-editor"]').fill("Wait for my sign-in")
|
||||
await page.getByRole("button", { name: "Session details", exact: true }).click()
|
||||
await page.getByRole("button", { name: "MCP", exact: true }).click()
|
||||
const menu = page.getByRole("dialog", { name: "MCP", exact: true })
|
||||
const toggle = menu.getByRole("switch", { name: "summary-mcp", exact: true })
|
||||
await expect(toggle).toBeChecked()
|
||||
await menu.getByText("summary-mcp", { exact: true }).click()
|
||||
await expect(toggle).not.toBeChecked()
|
||||
await menu.getByText("summary-mcp", { exact: true }).click()
|
||||
await expect(toggle).toBeChecked()
|
||||
await page.keyboard.press("Escape")
|
||||
await page.keyboard.press("Escape")
|
||||
const popup = page.waitForEvent("popup")
|
||||
await page.locator('[data-action="composer-submit"]').click()
|
||||
await expect(await popup).toHaveURL("https://auth.example.test/authorize")
|
||||
await expect(page).toHaveURL(draftPath)
|
||||
await expect(page.locator('[data-component="composer-editor"]')).toHaveText("Wait for my sign-in")
|
||||
expect(attempts).toEqual([createdWorkspace])
|
||||
expect(mock.prompts).toEqual([])
|
||||
mock.status.set(createdWorkspace, "connected")
|
||||
await page.locator('[data-action="composer-submit"]').click()
|
||||
await expect.poll(() => mock.prompts.length).toBe(1)
|
||||
expect(mock.calls.filter((call) => call.type === "worktree")).toHaveLength(1)
|
||||
expect(attempts).toHaveLength(1)
|
||||
})
|
||||
|
||||
async function openDraft(
|
||||
page: Page,
|
||||
worktree = "main",
|
||||
options: { git?: boolean; direction?: "ltr" | "rtl"; currentDirectory?: string } = {},
|
||||
) {
|
||||
const currentDirectory = options.currentDirectory ?? directory
|
||||
const project = {
|
||||
id: "proj_new_summary",
|
||||
worktree: directory,
|
||||
name: "summary-project",
|
||||
vcs: options.git === false ? undefined : "git",
|
||||
time: { created: 1, updated: 1 },
|
||||
sandboxes: [workspace],
|
||||
}
|
||||
const sessions: ReturnType<typeof currentSession>[] = []
|
||||
const status = new Map<string, string>([
|
||||
[directory, "connected"],
|
||||
[workspace, "disabled"],
|
||||
[createdWorkspace, "connected"],
|
||||
])
|
||||
const calls: { type: string; directory: string; enabled?: boolean }[] = []
|
||||
const prompts: { sessionID: string; body: Record<string, unknown> }[] = []
|
||||
const state: { fail: boolean; hold?: Promise<void>; holdDirectory?: string } = { fail: false }
|
||||
test("does not show session details on the new session screen", async ({ page }, testInfo) => {
|
||||
await mockOpenCodeServer(page, {
|
||||
directory: currentDirectory,
|
||||
project,
|
||||
sessions,
|
||||
directory,
|
||||
project: {
|
||||
id: "proj_new_summary",
|
||||
worktree: directory,
|
||||
vcs: "git",
|
||||
name: "summary-project",
|
||||
time: { created: 1, updated: 1 },
|
||||
sandboxes: [],
|
||||
},
|
||||
provider: {
|
||||
all: [
|
||||
{
|
||||
@@ -343,148 +28,28 @@ async function openDraft(
|
||||
connected: ["opencode"],
|
||||
default: { providerID: "opencode", modelID: "summary-model" },
|
||||
},
|
||||
sessions: [],
|
||||
pageMessages: () => ({ items: [] }),
|
||||
onPrompt(input) {
|
||||
const session = sessions.find((session) => session.id === input.sessionID)
|
||||
if (!session?.location.directory) throw new Error("Prompt arrived before session creation")
|
||||
calls.push({ type: "prompt", directory: session.location.directory })
|
||||
prompts.push(input)
|
||||
},
|
||||
})
|
||||
if (options.git === false) {
|
||||
await page.route(
|
||||
(url) => url.pathname === "/api/vcs",
|
||||
(route) => route.fulfill({ json: { location: { directory }, data: { branch: {} } } }),
|
||||
)
|
||||
}
|
||||
await page.route(/\/api\/(?:experimental\/)?mcp(?:[/?]|$)/, async (route) => {
|
||||
if (route.request().method() === "OPTIONS") return route.fallback()
|
||||
const url = new URL(route.request().url())
|
||||
const target = url.searchParams.get("location[directory]") ?? directory
|
||||
if (route.request().method() === "POST") {
|
||||
const enabled = url.pathname.endsWith("/connect")
|
||||
calls.push({ type: "mcp", directory: target, enabled })
|
||||
if (!state.holdDirectory || state.holdDirectory === target) await state.hold
|
||||
if (state.fail) return route.fulfill({ status: 500, json: { message: "MCP fixture failed" } })
|
||||
status.set(target, enabled ? "connected" : "disabled")
|
||||
return route.fulfill({ status: 204 })
|
||||
}
|
||||
return route.fulfill({
|
||||
json: {
|
||||
location: { directory: target },
|
||||
data:
|
||||
url.pathname === "/api/mcp/resource"
|
||||
? { resources: [], templates: [] }
|
||||
: [
|
||||
{
|
||||
name: "summary-mcp",
|
||||
integrationID: "summary-oauth",
|
||||
status: { status: status.get(target) ?? "connected" },
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
})
|
||||
await page.route(
|
||||
(url) => url.pathname === "/api/location",
|
||||
(route) =>
|
||||
route.fulfill({
|
||||
json: {
|
||||
directory: new URL(route.request().url()).searchParams.get("location[directory]") ?? directory,
|
||||
project: { id: project.id, directory, canonical: directory },
|
||||
},
|
||||
}),
|
||||
)
|
||||
await page.route(
|
||||
(url) => url.pathname === "/api/plugin",
|
||||
(route) => {
|
||||
const target = new URL(route.request().url()).searchParams.get("location[directory]") ?? directory
|
||||
const id = target === directory ? "project-plugin" : "workspace-plugin"
|
||||
return route.fulfill({
|
||||
json: {
|
||||
location: { directory: target },
|
||||
data: [{ id, source: { type: "package", target: id }, features: {}, state: { status: "active" } }],
|
||||
},
|
||||
})
|
||||
},
|
||||
)
|
||||
await page.route(
|
||||
(url) => url.pathname === "/api/skill",
|
||||
(route) =>
|
||||
route.fulfill({
|
||||
json: {
|
||||
location: { directory: new URL(route.request().url()).searchParams.get("location[directory]") ?? directory },
|
||||
data: [
|
||||
{
|
||||
id: "summary-skill",
|
||||
name: "summary-skill",
|
||||
path: "/skills/summary/SKILL.md",
|
||||
content: "Summary skill",
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
)
|
||||
await page.route(
|
||||
(url) => url.pathname === "/api/config",
|
||||
(route) =>
|
||||
route.fulfill({
|
||||
json: [{ type: "document", info: { lsp: { typescript: { command: ["typescript-language-server"] } } } }],
|
||||
}),
|
||||
)
|
||||
await page.route(
|
||||
(url) => url.pathname === "/api/worktree",
|
||||
(route) => {
|
||||
if (route.request().method() !== "POST") return route.fallback()
|
||||
calls.push({ type: "worktree", directory })
|
||||
project.sandboxes.push(createdWorkspace)
|
||||
return route.fulfill({ json: { directory: createdWorkspace } })
|
||||
},
|
||||
)
|
||||
await page.route(
|
||||
(url) => url.pathname === "/api/session",
|
||||
(route) => {
|
||||
if (route.request().method() !== "POST") return route.fallback()
|
||||
const body: { id: string; location: { directory: string } } = route.request().postDataJSON()
|
||||
calls.push({ type: "session", directory: body.location.directory })
|
||||
const session = currentSession(
|
||||
{ ...body, projectID: project.id, title: "Created summary session" },
|
||||
body.location.directory,
|
||||
)
|
||||
sessions.push(session)
|
||||
return route.fulfill({ json: { data: session } })
|
||||
},
|
||||
)
|
||||
await page.addInitScript(
|
||||
({ directory, currentDirectory, server, draftID, secondDraftID, worktree }) => {
|
||||
if (!localStorage.getItem("opencode.global.dat:server"))
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:server",
|
||||
JSON.stringify({
|
||||
projects: { local: [{ worktree: directory, expanded: true }] },
|
||||
lastProject: { local: directory },
|
||||
}),
|
||||
)
|
||||
if (!localStorage.getItem("opencode.window.browser.dat:tabs"))
|
||||
localStorage.setItem(
|
||||
"opencode.window.browser.dat:tabs",
|
||||
JSON.stringify([
|
||||
{ type: "draft", draftID, server, directory: currentDirectory, worktree },
|
||||
{ type: "draft", draftID: secondDraftID, server, directory: currentDirectory, worktree },
|
||||
]),
|
||||
)
|
||||
({ directory, draftID, server }) => {
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:server",
|
||||
JSON.stringify({
|
||||
projects: { local: [{ worktree: directory, expanded: true }] },
|
||||
lastProject: { local: directory },
|
||||
}),
|
||||
)
|
||||
localStorage.setItem(
|
||||
"opencode.window.browser.dat:tabs",
|
||||
JSON.stringify([{ type: "draft", draftID, server, directory }]),
|
||||
)
|
||||
},
|
||||
{ directory, currentDirectory, server, draftID, secondDraftID, worktree },
|
||||
{ directory, draftID, server },
|
||||
)
|
||||
if (options.direction) await openWithDirection(page, draftPath, options.direction)
|
||||
if (!options.direction) await page.goto(draftPath)
|
||||
await expect(page.locator('[data-component="composer-editor"]')).toBeEditable()
|
||||
await expect(page.locator('[data-action="composer-model"]')).toContainText("Summary Model")
|
||||
if (options.git === false) await expect(page.getByText("No Git", { exact: true })).toBeVisible()
|
||||
if (options.git !== false) {
|
||||
await expect(
|
||||
page.getByRole("button", { name: worktree === "create" ? "New worktree" : "Local", exact: true }),
|
||||
).toBeVisible()
|
||||
}
|
||||
return { calls, prompts, status, state }
|
||||
}
|
||||
|
||||
await page.goto(`/new-session?draftId=${draftID}`)
|
||||
await expectAppVisible(page.locator('[data-component="composer-editor"]'))
|
||||
await expect(page.getByRole("button", { name: "Session details", exact: true })).toHaveCount(0)
|
||||
await testInfo.attach("new-session-without-summary", { body: await page.screenshot(), contentType: "image/png" })
|
||||
})
|
||||
|
||||
@@ -96,7 +96,7 @@ for (const field of [
|
||||
expect(patches).toEqual(field.patches)
|
||||
|
||||
await settings.getByRole("tab", { name: "Worktrees", exact: true }).click()
|
||||
await settings.getByRole("tab", { name: project.name, exact: true }).click()
|
||||
await settings.getByRole("tab", { name: "General", exact: true }).click()
|
||||
if (field.name === "color") {
|
||||
await expect(settings.getByRole("button", { name: "Select orange color", exact: true })).toHaveAttribute(
|
||||
"aria-pressed",
|
||||
|
||||
@@ -37,11 +37,6 @@ for (const direction of ["ltr", "rtl"] as const) {
|
||||
"opencode.global.dat:language",
|
||||
JSON.stringify({ locale: direction === "rtl" ? "ar" : "en" }),
|
||||
)
|
||||
const settings = JSON.parse(localStorage.getItem("settings.v3") ?? "{}")
|
||||
localStorage.setItem(
|
||||
"settings.v3",
|
||||
JSON.stringify({ ...settings, general: { ...settings.general, showProjectIcon: false } }),
|
||||
)
|
||||
}, direction)
|
||||
await page.setViewportSize({ width: workspace ? 900 : 1440, height: 900 })
|
||||
await page.goto(stressSessionHref(fixture.targetID))
|
||||
@@ -64,7 +59,7 @@ for (const direction of ["ltr", "rtl"] as const) {
|
||||
await trigger.click()
|
||||
|
||||
const menu = page.getByRole("menu", { name: project.name, exact: true })
|
||||
const settings = menu.getByRole("menuitem", { name: "Edit project", exact: true })
|
||||
const settings = menu.getByRole("menuitem", { name: copy["project.settings.title"], exact: true })
|
||||
const projectItem = menu.getByRole("menuitem", { name: project.name, exact: true })
|
||||
await expect(trigger).toHaveAttribute("aria-expanded", "true")
|
||||
await expect(page.getByRole("tooltip")).toBeHidden()
|
||||
@@ -74,7 +69,7 @@ for (const direction of ["ltr", "rtl"] as const) {
|
||||
await expect(menu.getByText(directory, { exact: true })).toHaveAttribute("dir", "ltr")
|
||||
await expect(menu.locator('use[href="#opencode-v2-icon-folder"]')).toHaveCount(1)
|
||||
await expect(menu).toHaveCSS("direction", direction)
|
||||
await expect(menu.getByRole("menuitem")).toHaveText([project.name, directory, "Edit project"])
|
||||
await expect(menu.getByRole("menuitem")).toHaveText([project.name, directory, copy["project.settings.title"]])
|
||||
await expect(menu.getByRole("menuitem", { name: directory, exact: true })).toBeDisabled()
|
||||
await expect(settings).toBeEnabled()
|
||||
await expect
|
||||
@@ -203,11 +198,11 @@ for (const direction of ["ltr", "rtl"] as const) {
|
||||
const settingsScreen = page.getByTestId("settings-screen")
|
||||
await expect(settingsScreen.getByRole("heading", { name: project.name, exact: true })).toBeVisible()
|
||||
await expect(
|
||||
settingsScreen.getByRole("textbox", { name: en["project.settings.name.title"], exact: true }),
|
||||
settingsScreen.getByRole("textbox", { name: copy["project.settings.name.title"], exact: true }),
|
||||
).toHaveValue(project.name)
|
||||
await expect(menu).toBeHidden()
|
||||
await settingsScreen.getByRole("button", { name: en["settings.backToProjects"], exact: true }).click()
|
||||
await settingsScreen.getByRole("button", { name: en["settings.backToApp"], exact: true }).click()
|
||||
await settingsScreen.getByRole("button", { name: copy["settings.backToProjects"], exact: true }).click()
|
||||
await settingsScreen.getByRole("button", { name: copy["settings.backToApp"], exact: true }).click()
|
||||
await expect(settingsScreen).toBeHidden()
|
||||
await expect(header.getByRole("heading")).toHaveText(fixture.expected.targetTitle)
|
||||
|
||||
|
||||
@@ -284,7 +284,13 @@ for (const delivery of ["steer", "queue"] as const) {
|
||||
await expect(thinking).toHaveCount(0)
|
||||
|
||||
// The next assistant step still belongs to U1: U2 has been admitted, not delivered.
|
||||
mock.emit("session.step.started", { sessionID, assistantMessageID: assistantID, agent: "build", model, started: Date.now() })
|
||||
mock.emit("session.step.started", {
|
||||
sessionID,
|
||||
assistantMessageID: assistantID,
|
||||
agent: "build",
|
||||
model,
|
||||
started: Date.now(),
|
||||
})
|
||||
for (const tool of [
|
||||
{ id: "tool_queue_read", name: "read", input: { path: "src/queue.ts" } },
|
||||
{ id: "tool_queue_grep", name: "grep", input: { pattern: "retry", path: "src" } },
|
||||
@@ -309,7 +315,10 @@ for (const delivery of ["steer", "queue"] as const) {
|
||||
const tools = page.locator('[data-timeline-part-ids="tool_queue_read,tool_queue_grep"]')
|
||||
await expect(tools).toBeVisible()
|
||||
await expect(tools).toHaveText(/^Used\s*2\s*Read, Grep$/)
|
||||
await expect(tools.locator('[data-slot="basic-tool-tool-title"]')).toHaveText("Read, Grep")
|
||||
await expect(tools.locator('[data-component="context-tool-group-trigger"]')).toHaveAttribute(
|
||||
"aria-label",
|
||||
"Used 2 Read, Grep",
|
||||
)
|
||||
await expect(thinking).toHaveCount(0)
|
||||
await expect(pending).toBeVisible()
|
||||
expect(mock.rows.map((row) => ({ id: row.id, delivery: row.delivery }))).toEqual([
|
||||
|
||||
@@ -4,8 +4,7 @@ import { mockStressTimeline, stressSessionHref } from "../performance/timeline/t
|
||||
import { openWithDirection } from "../utils/direction"
|
||||
|
||||
for (const direction of ["ltr", "rtl"] as const) {
|
||||
test(`summary slides the conversation into spare space and back in ${direction}`, async ({ page }, testInfo) => {
|
||||
await page.clock.install({ time: new Date("2026-09-10T12:00:00Z") })
|
||||
test(`summary overlays the conversation without shifting it in ${direction}`, async ({ page }, testInfo) => {
|
||||
await page.setViewportSize({ width: 1440, height: 900 })
|
||||
await mockStressTimeline(page)
|
||||
await openWithDirection(page, stressSessionHref(fixture.targetID), direction)
|
||||
@@ -18,7 +17,6 @@ for (const direction of ["ltr", "rtl"] as const) {
|
||||
)
|
||||
const content = page.locator("[data-timeline-virtual-content]")
|
||||
const composer = page.locator('[data-component="session-composer-dock"] > div')
|
||||
const panel = page.locator('[data-slot="session-chat-panel"]')
|
||||
const summary = page.getByRole("dialog", { name: "Session details", exact: true })
|
||||
await expect(row).toBeInViewport()
|
||||
await expect(row).toHaveCSS("width", "1000px")
|
||||
@@ -26,103 +24,43 @@ for (const direction of ["ltr", "rtl"] as const) {
|
||||
const dock = await composer.boundingBox()
|
||||
expect(before).not.toBeNull()
|
||||
expect(dock).not.toBeNull()
|
||||
await content.evaluate((element) => {
|
||||
element.setAttribute("data-summary-motion", "")
|
||||
for (const type of ["transitionrun", "transitionend"]) {
|
||||
element.addEventListener(type, (event) => {
|
||||
if (event.target !== element || (event as TransitionEvent).propertyName !== "translate") return
|
||||
element.setAttribute("data-summary-motion", `${element.getAttribute("data-summary-motion")}${type},`)
|
||||
})
|
||||
}
|
||||
})
|
||||
await expect(content).toHaveCSS("translate", "none")
|
||||
await expect(composer).toHaveCSS("translate", "none")
|
||||
await testInfo.attach(`summary-${direction}-centered`, { body: await page.screenshot(), contentType: "image/png" })
|
||||
await trigger.click()
|
||||
await expect(content).toHaveAttribute("data-summary-motion", "transitionrun,transitionend,")
|
||||
await expect(summary).toBeVisible()
|
||||
await expect
|
||||
.poll(async () => {
|
||||
const message = await row.boundingBox()
|
||||
const details = await summary.boundingBox()
|
||||
const chat = await panel.boundingBox()
|
||||
if (!message || !details || !chat) return false
|
||||
return (
|
||||
message.x >= chat.x &&
|
||||
message.x + message.width <= chat.x + chat.width &&
|
||||
(direction === "ltr" ? message.x + message.width < details.x : message.x > details.x + details.width)
|
||||
)
|
||||
if (!message || !details) return 0
|
||||
return Math.min(message.x + message.width, details.x + details.width) - Math.max(message.x, details.x)
|
||||
})
|
||||
.toBe(true)
|
||||
.toBeGreaterThan(0)
|
||||
await expect(row).toHaveCSS("width", "1000px")
|
||||
await expect
|
||||
.poll(async () => {
|
||||
const message = await row.boundingBox()
|
||||
const input = await composer.boundingBox()
|
||||
if (!message || !input || !before || !dock) return Infinity
|
||||
return Math.abs(message.x - before.x - (input.x - dock.x))
|
||||
return Math.max(Math.abs(message.x - before.x), Math.abs(input.x - dock.x))
|
||||
})
|
||||
.toBeLessThan(1)
|
||||
await expect
|
||||
.poll(() =>
|
||||
content.evaluate((element) => element.parentElement!.scrollWidth - element.parentElement!.clientWidth),
|
||||
)
|
||||
.toBe(0)
|
||||
await testInfo.attach(`summary-${direction}-shifted`, { body: await page.screenshot(), contentType: "image/png" })
|
||||
await expect(content).toHaveCSS("translate", "none")
|
||||
await expect(composer).toHaveCSS("translate", "none")
|
||||
await testInfo.attach(`summary-${direction}-overlay`, { body: await page.screenshot(), contentType: "image/png" })
|
||||
|
||||
await page.clock.pauseAt(new Date("2026-09-10T12:01:00Z"))
|
||||
const shifted = await content.evaluate((element) => getComputedStyle(element).translate)
|
||||
await content.evaluate((element) => element.setAttribute("data-summary-motion", ""))
|
||||
// Keep issuing resize events before the idle timer expires, including crossing the width cutoff.
|
||||
for (const width of [1520, 1280, 1800]) {
|
||||
await page.setViewportSize({ width, height: 900 })
|
||||
await expect(panel).toHaveAttribute("data-summary-resizing", "true")
|
||||
await page.clock.runFor(100)
|
||||
await expect(content).toHaveCSS("translate", shifted)
|
||||
await expect(composer).toHaveCSS("translate", shifted)
|
||||
await expect(content).toHaveAttribute("data-summary-motion", "")
|
||||
}
|
||||
await page.clock.resume()
|
||||
await expect(panel).toHaveAttribute("data-summary-resizing", "false")
|
||||
await expect(content).toHaveAttribute("data-summary-motion", "transitionrun,transitionend,")
|
||||
await expect(content).not.toHaveCSS("translate", shifted)
|
||||
await page.setViewportSize({ width: 1440, height: 900 })
|
||||
await expect(panel).toHaveAttribute("data-summary-resizing", "false")
|
||||
await expect(content).toHaveCSS("translate", shifted)
|
||||
|
||||
await content.evaluate((element) => element.setAttribute("data-summary-motion", ""))
|
||||
await page.keyboard.press("Escape")
|
||||
await expect(summary).toBeHidden()
|
||||
await expect(content).toHaveAttribute("data-summary-motion", "transitionrun,transitionend,")
|
||||
await expect.poll(async () => Math.abs((await row.boundingBox())!.x - before!.x)).toBeLessThan(1)
|
||||
await expect(trigger).toBeFocused()
|
||||
|
||||
await trigger.click()
|
||||
await expect(summary.getByRole("button", { name: "Extensions", exact: true })).toBeVisible()
|
||||
// Cross the actual chat-panel breakpoint, including any surrounding shell width.
|
||||
const shell = 1440 - (await panel.boundingBox())!.width
|
||||
await page.setViewportSize({ width: 1320 + shell, height: 900 })
|
||||
await expect.poll(async () => (await panel.boundingBox())!.width).toBe(1320)
|
||||
await expect
|
||||
.poll(async () => {
|
||||
const message = (await row.boundingBox())!
|
||||
const details = (await summary.boundingBox())!
|
||||
return direction === "ltr" ? details.x - message.x - message.width : message.x - details.x - details.width
|
||||
})
|
||||
.toBeGreaterThan(0)
|
||||
await page.setViewportSize({ width: 1319 + shell, height: 900 })
|
||||
await expect(content).toHaveCSS("translate", "none")
|
||||
await expect(row).toHaveCSS("width", "1000px")
|
||||
await expect(summary).toBeVisible()
|
||||
|
||||
await page.setViewportSize({ width: 1800, height: 900 })
|
||||
await expect(panel).toHaveAttribute("data-summary-resizing", "false")
|
||||
await expect(content).toHaveCSS("translate", "none")
|
||||
await expect(composer).toHaveCSS("translate", "none")
|
||||
await expect(summary).toBeVisible()
|
||||
|
||||
await page.emulateMedia({ reducedMotion: "reduce" })
|
||||
await page.setViewportSize({ width: 1440, height: 900 })
|
||||
await expect(content).toHaveCSS("transition-duration", "0s")
|
||||
await page.keyboard.press("Escape")
|
||||
await expect(content).toHaveCSS("translate", "none")
|
||||
await expect.poll(async () => Math.abs((await row.boundingBox())!.x - before!.x)).toBeLessThan(1)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,10 @@ test.describe("regression: session timeline local row state", () => {
|
||||
const id = `prt_patch_${count}`
|
||||
events.push(...toolEvents({ ...part, id, callID: id }))
|
||||
await expect(summary).toHaveAccessibleName(`Used ${count} Patch`)
|
||||
await expect(summary.locator('[data-slot="basic-tool-tool-title"]')).toHaveText("Patch")
|
||||
await expect(summary.locator('[data-component="context-tool-group-trigger"]')).toHaveAttribute(
|
||||
"aria-label",
|
||||
`Used ${count} Patch`,
|
||||
)
|
||||
await expect(group).toHaveAttribute("data-timeline-part-ids", new RegExp(`${id}$`))
|
||||
await expect(trigger).toHaveAttribute("aria-expanded", String(count === 2))
|
||||
await expect(summary).toHaveAttribute("aria-expanded", "true")
|
||||
|
||||
@@ -16,9 +16,9 @@ for (const locale of ["de", "ar"] as const) {
|
||||
})
|
||||
|
||||
const group = page.locator(`[data-timeline-part-ids="${ids.join(",")}"]`)
|
||||
const names = locale === "de" ? "Lesen, Glob" : "\u0642\u0631\u0627\u0621\u0629, Glob"
|
||||
await expect(group.getByRole("button")).toHaveAccessibleName(`Used 2 ${names}`)
|
||||
await expect(group.locator('[data-slot="basic-tool-tool-title"]')).toHaveText(names)
|
||||
const label = locale === "de" ? "2 Lesen und Glob verwendet" : "استُخدمت 2 أداتان: \u2068قراءة وGlob\u2069"
|
||||
await expect(group.getByRole("button")).toHaveAccessibleName(label)
|
||||
await expect(group.locator('[data-component="context-tool-group-trigger"]')).toHaveAttribute("aria-label", label)
|
||||
await expect(page.locator("html")).toHaveAttribute("lang", locale)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -48,7 +48,10 @@ test("expands a mixed collapsed tool stack without expanding its individual call
|
||||
const summary = group.getByRole("button", { name: "Used 4 Shell, Agent, Patch", exact: true })
|
||||
await expect(summary).toHaveAttribute("aria-expanded", "false")
|
||||
await expect(summary).toHaveCSS("height", "28px")
|
||||
await expect(summary.locator('[data-slot="basic-tool-tool-title"]')).toHaveText("Shell, Agent, Patch")
|
||||
await expect(summary.locator('[data-component="context-tool-group-trigger"]')).toHaveAttribute(
|
||||
"aria-label",
|
||||
"Used 4 Shell, Agent, Patch",
|
||||
)
|
||||
await expect(summary.locator('[data-component="tag"]')).toHaveCount(0)
|
||||
await summary.click()
|
||||
await expect(summary).toHaveAttribute("aria-expanded", "true")
|
||||
@@ -76,7 +79,10 @@ test("leaves tools expanded by settings outside the collapsed stack", async ({ p
|
||||
await expect(page.locator('[data-timeline-part-id="prt_expanded_shell"]')).toBeVisible()
|
||||
const group = page.locator('[data-timeline-part-ids="prt_collapsed_patch,prt_collapsed_read"]')
|
||||
await expect(group.getByRole("button", { name: "Used 2 Patch, Read", exact: true })).toBeVisible()
|
||||
await expect(group.locator('[data-slot="basic-tool-tool-title"]')).toHaveText("Patch, Read")
|
||||
await expect(group.locator('[data-component="context-tool-group-trigger"]')).toHaveAttribute(
|
||||
"aria-label",
|
||||
"Used 2 Patch, Read",
|
||||
)
|
||||
await expect(page.locator('[data-timeline-spacing="tool"]')).toHaveCSS("padding-top", "8px")
|
||||
})
|
||||
|
||||
|
||||
@@ -67,8 +67,7 @@ test("an inventory event updates the open all-project worktree list", async ({ p
|
||||
await settings.getByRole("tab", { name: "Worktrees", exact: true }).click()
|
||||
await expect(settings.getByText(sandboxes[0], { exact: true })).toBeVisible()
|
||||
const listed = page.waitForResponse(
|
||||
(response) =>
|
||||
new URL(response.url()).pathname === "/api/worktree" && response.request().method() === "GET",
|
||||
(response) => new URL(response.url()).pathname === "/api/worktree" && response.request().method() === "GET",
|
||||
)
|
||||
inventory.push({ directory: discovered, strategy: "git" })
|
||||
events.push({
|
||||
@@ -99,6 +98,51 @@ test("settings has its own route and returns through app history", async ({ page
|
||||
await expect(home).toHaveAttribute("aria-pressed", "true")
|
||||
})
|
||||
|
||||
test("settings page survives refresh", async ({ page }) => {
|
||||
const settings = page.getByTestId("settings-screen")
|
||||
const appearance = settings.getByRole("tab", { name: "Appearance", exact: true })
|
||||
|
||||
await appearance.click()
|
||||
await expect(page).toHaveURL("/settings?tab=appearance")
|
||||
await expect(appearance).toHaveAttribute("aria-selected", "true")
|
||||
|
||||
await page.reload()
|
||||
|
||||
await expect(settings).toBeVisible()
|
||||
await expect(appearance).toHaveAttribute("aria-selected", "true")
|
||||
await expect(page).toHaveURL("/settings?tab=appearance")
|
||||
})
|
||||
|
||||
test("another server's settings page survives refresh", async ({ page }) => {
|
||||
const remote = "http://127.0.0.1:4097"
|
||||
await page.addInitScript(
|
||||
(input) => {
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:server",
|
||||
JSON.stringify({
|
||||
list: [{ type: "http", http: { url: input.remote } }],
|
||||
projects: { local: [{ worktree: input.directory, expanded: true }] },
|
||||
}),
|
||||
)
|
||||
},
|
||||
{ directory, remote },
|
||||
)
|
||||
const settings = page.getByTestId("settings-screen")
|
||||
const url = (value: URL) =>
|
||||
value.pathname === "/settings" &&
|
||||
value.searchParams.get("server") === remote &&
|
||||
value.searchParams.get("tab") === "providers"
|
||||
|
||||
await page.goto(`/settings?server=${encodeURIComponent(remote)}&tab=providers`)
|
||||
await expect(settings.getByRole("heading", { name: "Providers", exact: true })).toBeVisible()
|
||||
await expect(page).toHaveURL(url)
|
||||
|
||||
await page.reload()
|
||||
|
||||
await expect(settings.getByRole("heading", { name: "Providers", exact: true })).toBeVisible()
|
||||
await expect(page).toHaveURL(url)
|
||||
})
|
||||
|
||||
test("single-server settings expose scoped pages without a server picker", async ({ page }) => {
|
||||
const settings = page.getByTestId("settings-screen")
|
||||
await expect(settings.getByRole("tab", { name: "Server", exact: true })).toBeVisible()
|
||||
@@ -134,10 +178,53 @@ test("project settings open as a nested autosaving view", async ({ page }) => {
|
||||
await settings.getByRole("button", { name: "Settings demo", exact: true }).click()
|
||||
|
||||
await expect(settings.getByRole("button", { name: "Back to projects", exact: true })).toBeVisible()
|
||||
await expect(settings.getByRole("tab", { name: "Settings demo", exact: true })).toBeVisible()
|
||||
await expect(settings.getByRole("tab", { name: "General", exact: true })).toBeVisible()
|
||||
await expect(settings.getByRole("tab", { name: "Worktrees", exact: true })).toBeVisible()
|
||||
await expect(settings.getByRole("tab", { name: "Extensions", exact: true })).toBeVisible()
|
||||
await expect(settings.getByRole("tab", { name: "Scripts", exact: true })).toHaveCount(0)
|
||||
await expect(settings.getByTitle(directory)).toHaveCount(0)
|
||||
const projectIcon = settings.locator('.settings-tab-header [data-component="project-avatar-v2"]')
|
||||
await expect(projectIcon).toHaveCSS("width", "32px")
|
||||
const projectOptions = settings
|
||||
.locator(".settings-tab-header")
|
||||
.getByRole("button", { name: "More options", exact: true })
|
||||
await expect(projectOptions).toHaveCSS("width", "28px")
|
||||
await expect
|
||||
.poll(
|
||||
async () =>
|
||||
new Set(
|
||||
await Promise.all(
|
||||
[
|
||||
settings.getByRole("button", { name: "Back to projects", exact: true }),
|
||||
settings.getByRole("heading", { name: "Settings demo", exact: true }),
|
||||
projectIcon,
|
||||
projectOptions,
|
||||
].map((item) =>
|
||||
item.evaluate((element) => {
|
||||
const bounds = element.getBoundingClientRect()
|
||||
return Math.round(bounds.top + bounds.height / 2)
|
||||
}),
|
||||
),
|
||||
),
|
||||
).size,
|
||||
)
|
||||
.toBe(1)
|
||||
await expect
|
||||
.poll(async () => {
|
||||
const back = await settings
|
||||
.getByRole("button", { name: "Back to projects", exact: true })
|
||||
.evaluate((element) => element.getBoundingClientRect().top)
|
||||
const general = await settings
|
||||
.getByRole("tab", { name: "General", exact: true })
|
||||
.evaluate((element) => element.getBoundingClientRect().top)
|
||||
return Math.round(general - back)
|
||||
})
|
||||
.toBe(72)
|
||||
await projectOptions.click()
|
||||
const projectMenu = page.getByRole("menu")
|
||||
await expect(projectMenu.getByRole("menuitem")).toHaveText(["Clear notifications", "Close"])
|
||||
await page.keyboard.press("Escape")
|
||||
await expect(projectMenu).toBeHidden()
|
||||
|
||||
const name = settings.getByRole("textbox", { name: "Project name", exact: true })
|
||||
const saved = page.waitForRequest(
|
||||
@@ -146,7 +233,8 @@ test("project settings open as a nested autosaving view", async ({ page }) => {
|
||||
await name.fill("Renamed project")
|
||||
await name.blur()
|
||||
expect((await saved).postDataJSON()).toEqual({ name: "Renamed project" })
|
||||
await expect(settings.getByRole("tab", { name: "Renamed project", exact: true })).toBeVisible()
|
||||
await expect(settings.getByRole("tab", { name: "General", exact: true })).toBeVisible()
|
||||
await expect(settings.getByRole("heading", { name: "Renamed project", exact: true })).toBeVisible()
|
||||
|
||||
const startup = settings.getByRole("textbox", { name: "Worktree startup script", exact: true })
|
||||
const scriptSaved = page.waitForRequest(
|
||||
@@ -156,7 +244,19 @@ test("project settings open as a nested autosaving view", async ({ page }) => {
|
||||
await startup.blur()
|
||||
expect((await scriptSaved).postDataJSON()).toEqual({ commands: { start: "bun install" } })
|
||||
|
||||
const server = `http://${process.env.PLAYWRIGHT_SERVER_HOST ?? "127.0.0.1"}:${process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"}`
|
||||
await settings.getByRole("tab", { name: "Worktrees", exact: true }).click()
|
||||
await expect(settings.getByRole("heading", { name: "Worktrees", exact: true })).toBeVisible()
|
||||
await expect(page).toHaveURL(
|
||||
(url) =>
|
||||
url.pathname === "/settings" &&
|
||||
url.searchParams.get("server") === server &&
|
||||
url.searchParams.get("project") === directory &&
|
||||
url.searchParams.get("tab") === "workspaces",
|
||||
)
|
||||
|
||||
await page.reload()
|
||||
|
||||
await expect(settings.getByRole("heading", { name: "Worktrees", exact: true })).toBeVisible()
|
||||
await page.keyboard.press("Escape")
|
||||
await expect(settings.getByRole("heading", { name: "Projects", exact: true })).toBeVisible()
|
||||
@@ -226,7 +326,7 @@ test("recording a new session shortcut stays in settings until recording finishe
|
||||
await page.keyboard.press("Control+t")
|
||||
|
||||
await expect(binding).toHaveText("Ctrl+T")
|
||||
await expect(page).toHaveURL("/settings")
|
||||
await expect(page).toHaveURL("/settings?tab=shortcuts")
|
||||
await expect(page.locator("[data-titlebar-tab]")).toHaveCount(0)
|
||||
await page.keyboard.press("Control+t")
|
||||
await expect(page).toHaveURL(/\/new-session\?draftId=.+$/)
|
||||
|
||||
@@ -56,7 +56,6 @@ for (const viewport of [
|
||||
"Models",
|
||||
"Extensions",
|
||||
"Server",
|
||||
"Experimental",
|
||||
"About",
|
||||
]) {
|
||||
if (viewport.width >= 816) await settings.getByRole("tab", { name, exact: true }).click()
|
||||
|
||||
@@ -5,7 +5,7 @@ for (const colorScheme of ["light", "dark"] as const) {
|
||||
test.describe(colorScheme, () => {
|
||||
test.use({ colorScheme, contextOptions: { reducedMotion: "reduce" } })
|
||||
|
||||
test("project card edges stay inside the settings scrollport", async ({ page }, info) => {
|
||||
test("project list actions and edges stay inside the settings scrollport", async ({ page }, info) => {
|
||||
const projects = ["rebase", "dinocms", "opencode", "Playground"].map((name, index) => ({
|
||||
id: `project-${index}`,
|
||||
name,
|
||||
@@ -20,10 +20,18 @@ for (const colorScheme of ["light", "dark"] as const) {
|
||||
sessions: [],
|
||||
pageMessages: () => ({ items: [] }),
|
||||
provider: { all: [], connected: [], default: {} },
|
||||
fileList: () => [],
|
||||
})
|
||||
await page.route("**/api/project", (route) =>
|
||||
route.fulfill({ json: projects, headers: { "access-control-allow-origin": "*" } }),
|
||||
)
|
||||
await page.route("**/api/project/project-0", async (route) => {
|
||||
const update = route.request().postDataJSON()
|
||||
await route.fulfill({
|
||||
json: { ...projects[0], ...update },
|
||||
headers: { "access-control-allow-origin": "*" },
|
||||
})
|
||||
})
|
||||
await page.addInitScript((projects) => {
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:server",
|
||||
@@ -40,18 +48,76 @@ for (const colorScheme of ["light", "dark"] as const) {
|
||||
const panel = settings.getByRole("tabpanel")
|
||||
await expect(panel.getByText("rebase", { exact: true })).toBeVisible()
|
||||
await expect(panel.getByText("Playground", { exact: true })).toBeVisible()
|
||||
await expect(panel.getByRole("button", { name: "Add project", exact: true })).toBeVisible()
|
||||
const list = panel.getByRole("list")
|
||||
await expect(list.getByRole("listitem")).toHaveCount(4)
|
||||
const projectButton = panel.getByRole("button", { name: "rebase", exact: true })
|
||||
const projectCard = list.getByRole("listitem").filter({ hasText: "rebase" })
|
||||
const projectName = projectButton.getByText("rebase", { exact: true })
|
||||
await expect(projectName).toHaveCSS("font-weight", "530")
|
||||
await expect(projectName).toHaveCSS("line-height", "20px")
|
||||
await expect(projectButton.getByText("/projects/rebase", { exact: true })).toHaveCount(0)
|
||||
await expect
|
||||
.poll(() =>
|
||||
list.evaluate((group) => {
|
||||
const icons = Array.from(group.querySelectorAll('[data-component="project-avatar-v2"]'))
|
||||
const first = icons.at(0)?.getBoundingClientRect()
|
||||
const last = icons.at(-1)?.getBoundingClientRect()
|
||||
const bounds = group.getBoundingClientRect()
|
||||
if (!first || !last) return []
|
||||
return [first.top - bounds.top, bounds.bottom - last.bottom, first.left - bounds.left]
|
||||
}),
|
||||
)
|
||||
.toEqual([16, 16, 16])
|
||||
await expect
|
||||
.poll(() =>
|
||||
list
|
||||
.locator(".settings-project-row-shell")
|
||||
.filter({ hasText: "rebase" })
|
||||
.evaluate((row) => {
|
||||
const group = row.parentElement
|
||||
if (!group) return 0
|
||||
return (
|
||||
row.getBoundingClientRect().left -
|
||||
group.getBoundingClientRect().left +
|
||||
Number.parseFloat(getComputedStyle(row, "::after").insetInlineStart)
|
||||
)
|
||||
}),
|
||||
)
|
||||
.toBe(16)
|
||||
const chevron = projectButton.locator('svg:has(use[href="#opencode-v2-icon-chevron-right"])')
|
||||
await expect(chevron).toHaveCount(0)
|
||||
const hoverColor = await projectCard.evaluate((element) => {
|
||||
const probe = document.createElement("div")
|
||||
probe.style.backgroundColor = "var(--v2-background-bg-layer-02)"
|
||||
element.append(probe)
|
||||
const color = getComputedStyle(probe).backgroundColor
|
||||
probe.remove()
|
||||
return color
|
||||
})
|
||||
await projectCard.hover()
|
||||
await expect(projectCard).toHaveCSS("background-color", hoverColor)
|
||||
const more = projectCard.getByRole("button", { name: "More options", exact: true })
|
||||
await more.click()
|
||||
const menu = page.getByRole("menu")
|
||||
await expect(menu.getByRole("menuitem")).toHaveText(["Edit", "Rename", "Clear notifications", "Close"])
|
||||
await menu.getByRole("menuitem", { name: "Close", exact: true }).hover()
|
||||
await expect(projectCard).toHaveCSS("background-color", hoverColor)
|
||||
await expect(menu.getByRole("separator")).toHaveCount(1)
|
||||
await menu.getByRole("menuitem", { name: "Edit", exact: true }).click()
|
||||
await expect(panel.getByRole("heading", { name: "rebase", exact: true })).toBeVisible()
|
||||
await settings.getByRole("button", { name: "Back to projects", exact: true }).click()
|
||||
await expect(panel.getByRole("heading", { name: "Projects", exact: true })).toBeVisible()
|
||||
await page.evaluate(() => document.fonts.ready)
|
||||
|
||||
for (const width of [1280, 1050, 960, 720, 600]) {
|
||||
await page.setViewportSize({ width, height: 720 })
|
||||
await page.mouse.move(0, 0)
|
||||
await page.screenshot({ path: info.outputPath(`projects-${width}.png`), animations: "disabled" })
|
||||
// Raised cards paint a half-pixel border outside their box. The scrollport
|
||||
// must leave room for that border and the soft shadow on both sides.
|
||||
// Each project card stays fully inside every horizontal clip ancestor.
|
||||
await expect
|
||||
.poll(() =>
|
||||
panel.getByText("rebase", { exact: true }).evaluate((label) => {
|
||||
const row = label.parentElement!.parentElement!
|
||||
projectCard.evaluate((row) => {
|
||||
const bounds = row.getBoundingClientRect()
|
||||
const clips = []
|
||||
for (let parent = row.parentElement; parent; parent = parent.parentElement) {
|
||||
@@ -73,11 +139,45 @@ for (const colorScheme of ["light", "dark"] as const) {
|
||||
await settings.getByRole("button", { name: "Back to projects", exact: true }).click()
|
||||
await expect(panel.getByText("rebase", { exact: true })).toBeVisible()
|
||||
|
||||
const secondProject = panel.getByRole("button", { name: "dinocms", exact: true })
|
||||
await list
|
||||
.getByRole("listitem")
|
||||
.filter({ hasText: "dinocms" })
|
||||
.getByRole("button", { name: "More options", exact: true })
|
||||
.click()
|
||||
await page.getByRole("menuitem", { name: "Close", exact: true }).click()
|
||||
await expect(secondProject).toHaveCount(0)
|
||||
|
||||
await page.setViewportSize({ width: 1280, height: 260 })
|
||||
await panel.getByText("rebase", { exact: true }).hover()
|
||||
await page.mouse.wheel(0, 400)
|
||||
await expect(panel.getByText("Playground", { exact: true })).toBeInViewport({ ratio: 1 })
|
||||
await expect(panel.getByRole("heading", { name: "Projects", exact: true })).toBeInViewport({ ratio: 1 })
|
||||
|
||||
await page.setViewportSize({ width: 1280, height: 720 })
|
||||
await more.click()
|
||||
await menu.getByRole("menuitem", { name: "Rename", exact: true }).click()
|
||||
const rename = panel.getByRole("textbox", { name: "Rename", exact: true })
|
||||
await expect(rename).toBeFocused()
|
||||
await expect(rename).toHaveValue("rebase")
|
||||
await expect(rename).toHaveCSS("border-radius", "0px")
|
||||
await rename.fill("Renamed project")
|
||||
const renamed = page.waitForRequest(
|
||||
(request) => request.method() === "PATCH" && new URL(request.url()).pathname === "/api/project/project-0",
|
||||
)
|
||||
await rename.press("Enter")
|
||||
expect((await renamed).postDataJSON()).toEqual({ name: "Renamed project" })
|
||||
await expect(panel.getByRole("button", { name: "Renamed project", exact: true })).toBeVisible()
|
||||
|
||||
await panel.getByRole("button", { name: "Add project", exact: true }).click()
|
||||
const picker = page.getByRole("dialog", { name: "Open project", exact: true })
|
||||
await picker.getByRole("combobox").fill("/projects/added")
|
||||
await picker.getByRole("combobox").press("Enter")
|
||||
const selectFolder = picker.getByRole("button", { name: "Select folder", exact: true })
|
||||
await expect(selectFolder).toBeEnabled()
|
||||
await selectFolder.click()
|
||||
await expect(picker).toBeHidden()
|
||||
await expect(panel.getByRole("heading", { name: "added", exact: true })).toBeVisible()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -30,6 +30,19 @@ function projectList(count: number) {
|
||||
}))
|
||||
}
|
||||
|
||||
async function persistProjects(page: Page, projects: ReturnType<typeof projectList>) {
|
||||
await page.evaluate((projects) => {
|
||||
const value = JSON.parse(localStorage.getItem("opencode.global.dat:server") ?? "{}")
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:server",
|
||||
JSON.stringify({
|
||||
...value,
|
||||
projects: { ...value.projects, local: projects.map((project) => ({ worktree: project.canonical })) },
|
||||
}),
|
||||
)
|
||||
}, projects)
|
||||
}
|
||||
|
||||
function ui(page: Page) {
|
||||
const settings = page.getByTestId("settings-screen")
|
||||
return {
|
||||
@@ -50,6 +63,14 @@ test.use({ viewport: { width: 1280, height: 900 } })
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await mockOpenCodeServer(page, config)
|
||||
await page.route("https://api.github.com/**", (route) => route.fulfill({ json: [] }))
|
||||
await page.addInitScript((directory) => {
|
||||
const value = JSON.parse(localStorage.getItem("opencode.global.dat:server") ?? "{}")
|
||||
if (value.projects?.local) return
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:server",
|
||||
JSON.stringify({ ...value, projects: { ...value.projects, local: [{ worktree: directory, expanded: true }] } }),
|
||||
)
|
||||
}, directory)
|
||||
await page.goto("/")
|
||||
if ((page.viewportSize()?.width ?? 1280) < 800) await page.getByRole("button", { name: "Tabs", exact: true }).click()
|
||||
await page.getByRole("button", { name: "Settings", exact: true }).click()
|
||||
@@ -156,7 +177,7 @@ test("empty queries keep the closing quote beside the ellipsis while typing and
|
||||
await expect(status).toHaveText('No results for "zzzzzzzzzzx"')
|
||||
})
|
||||
|
||||
test("Models and Shortcuts autofocus their filters on normal navigation", async ({ page }) => {
|
||||
test("Models and Shortcuts leave focus on navigation", async ({ page }) => {
|
||||
const view = ui(page)
|
||||
for (const entry of [
|
||||
{ tab: "Models", search: "Search models" },
|
||||
@@ -164,7 +185,7 @@ test("Models and Shortcuts autofocus their filters on normal navigation", async
|
||||
{ tab: "Models", search: "Search models" },
|
||||
]) {
|
||||
await view.settings.getByRole("tab", { name: entry.tab, exact: true }).click()
|
||||
await expect(view.settings.getByRole("searchbox", { name: entry.search, exact: true })).toBeFocused()
|
||||
await expect(view.settings.getByRole("searchbox", { name: entry.search, exact: true })).not.toBeFocused()
|
||||
}
|
||||
await view.search.fill("shortcuts")
|
||||
const result = view.results.getByRole("option", { name: "Keyboard shortcuts", exact: true })
|
||||
@@ -172,6 +193,172 @@ test("Models and Shortcuts autofocus their filters on normal navigation", async
|
||||
await expect(result).toBeFocused()
|
||||
})
|
||||
|
||||
test("Shortcuts search keeps focus while filtering", async ({ page }) => {
|
||||
const view = ui(page)
|
||||
await view.settings.getByRole("tab", { name: "Shortcuts", exact: true }).click()
|
||||
const search = view.settings.getByRole("searchbox", { name: "Search shortcuts", exact: true })
|
||||
await search.press("p")
|
||||
await expect(search).toBeFocused()
|
||||
await page.keyboard.type("alette")
|
||||
await expect(search).toHaveValue("palette")
|
||||
await expect(view.settings.getByText("Command palette", { exact: true })).toBeVisible()
|
||||
})
|
||||
|
||||
test("section searches share controls and hierarchical Escape behavior", async ({ page }) => {
|
||||
const projects = projectList(8)
|
||||
await page.route("**/api/project", (route) => route.fulfill({ json: projects }))
|
||||
await persistProjects(page, projects)
|
||||
await page.reload()
|
||||
const view = ui(page)
|
||||
|
||||
for (const [index, entry] of [
|
||||
{ tab: "Projects", label: "Search projects", query: "missing-project" },
|
||||
{ tab: "Shortcuts", label: "Search shortcuts", query: "missing-shortcut" },
|
||||
{ tab: "Models", label: "Search models", query: "missing-model" },
|
||||
].entries()) {
|
||||
if (index > 0) {
|
||||
await page.getByRole("button", { name: "Settings", exact: true }).click()
|
||||
await expect(view.settings).toBeVisible()
|
||||
}
|
||||
await view.settings.getByRole("tab", { name: entry.tab, exact: true }).click()
|
||||
const field = view.settings.locator('[data-component="settings-filter-search"]')
|
||||
const search = field.getByRole("searchbox", { name: entry.label, exact: true })
|
||||
await expect(field).toHaveCount(1)
|
||||
await expect(field.locator('[data-slot="text-input-v2-leading-icon"]')).toBeVisible()
|
||||
await expect(search).not.toBeFocused()
|
||||
|
||||
await page.keyboard.type(entry.query)
|
||||
await expect(search).toBeFocused()
|
||||
await expect(search).toHaveValue(entry.query)
|
||||
await expect(view.settings.getByText(`No results for "${entry.query}"`, { exact: true })).toBeVisible()
|
||||
const clear = field.getByRole("button", { name: "Clear", exact: true })
|
||||
await expect(clear).toHaveAttribute("data-variant", "clear")
|
||||
await clear.click()
|
||||
await expect(search).toHaveValue("")
|
||||
await expect(search).toBeFocused()
|
||||
|
||||
await search.fill(`${entry.query} `.repeat(20))
|
||||
await search.press("End")
|
||||
await expect(search).toHaveAttribute("data-overflow-start", "true")
|
||||
await search.press("Home")
|
||||
await expect(search).toHaveAttribute("data-overflow-start", "false")
|
||||
await expect(search).toHaveAttribute("data-overflow-end", "true")
|
||||
await search.press("Escape")
|
||||
await expect(search).toHaveValue("")
|
||||
await expect(search).toBeFocused()
|
||||
await expect(view.settings).toBeVisible()
|
||||
|
||||
await search.press("Escape")
|
||||
await expect(search).not.toBeFocused()
|
||||
await expect(view.settings).toBeFocused()
|
||||
await expect(view.settings).toBeVisible()
|
||||
|
||||
await page.keyboard.press("Escape")
|
||||
await expect(view.settings).toBeHidden()
|
||||
await expect(page).toHaveURL("/")
|
||||
}
|
||||
})
|
||||
|
||||
for (const count of [7, 8]) {
|
||||
test(`Projects search uses the full list threshold with ${count} projects`, async ({ page }) => {
|
||||
const inventory = projectList(count)
|
||||
await page.route("**/api/project", (route) => route.fulfill({ json: inventory }))
|
||||
await persistProjects(page, inventory)
|
||||
await page.reload()
|
||||
const view = ui(page)
|
||||
await view.search.fill("OpenCode")
|
||||
await expect(view.results.getByRole("option")).toHaveCount(count)
|
||||
await view.search.clear()
|
||||
await view.settings.getByRole("tab", { name: "Projects", exact: true }).click()
|
||||
const search = view.settings.getByRole("searchbox", { name: "Search projects", exact: true })
|
||||
const projects = view.settings.getByRole("button", { name: /^OpenCode / })
|
||||
await expect(projects).toHaveCount(count)
|
||||
if (count === 7) {
|
||||
await expect(search).toHaveCount(0)
|
||||
return
|
||||
}
|
||||
await expect(search).not.toBeFocused()
|
||||
await search.fill(" CODE 06 ")
|
||||
await expect(projects).toHaveCount(1)
|
||||
await expect(projects).toHaveAccessibleName("OpenCode 06")
|
||||
await expect(search).toBeVisible()
|
||||
await search.fill("missing-project")
|
||||
await expect(projects).toHaveCount(0)
|
||||
await expect(view.settings.getByText('No results for "missing-project"', { exact: true })).toBeVisible()
|
||||
await view.settings.getByRole("button", { name: "Clear", exact: true }).click()
|
||||
await expect(search).toBeFocused()
|
||||
await expect(projects).toHaveCount(count)
|
||||
await view.settings.getByRole("tab", { name: "Models", exact: true }).click()
|
||||
await view.settings.getByRole("tab", { name: "Projects", exact: true }).click()
|
||||
await expect(search).not.toBeFocused()
|
||||
await search.fill("OpenCode 06")
|
||||
await projects.click()
|
||||
await expect(view.settings.getByRole("heading", { name: "OpenCode 06", exact: true })).toBeVisible()
|
||||
})
|
||||
}
|
||||
|
||||
test("Projects shows an add action in its empty state", async ({ page }) => {
|
||||
await page.route("**/api/project", (route) => route.fulfill({ json: [] }))
|
||||
await persistProjects(page, [])
|
||||
await page.reload()
|
||||
const view = ui(page)
|
||||
await view.settings.getByRole("tab", { name: "Projects", exact: true }).click()
|
||||
await expect(view.settings.getByText("No projects yet", { exact: true })).toBeVisible()
|
||||
await expect(view.settings.getByText("Add a project to get started", { exact: true })).toBeVisible()
|
||||
const emptyCard = view.settings.locator('[data-component="settings-project-empty-card"]')
|
||||
await expect(emptyCard).toHaveCSS("border-radius", "8px")
|
||||
await expect(emptyCard).toHaveCSS("padding-top", "96px")
|
||||
await expect(emptyCard).toHaveCSS("padding-bottom", "96px")
|
||||
const emptyBackground = await emptyCard.evaluate((element) => {
|
||||
const probe = document.createElement("div")
|
||||
probe.style.background =
|
||||
"color-mix(in oklab, var(--v2-background-bg-base) 50%, var(--v2-background-bg-layer-01))"
|
||||
element.append(probe)
|
||||
const color = getComputedStyle(probe).backgroundColor
|
||||
probe.remove()
|
||||
return color
|
||||
})
|
||||
await expect(emptyCard).toHaveCSS("background-color", emptyBackground)
|
||||
const add = view.settings.getByRole("button", { name: "Add project", exact: true })
|
||||
await expect(add).toHaveCount(1)
|
||||
await add.click()
|
||||
const picker = page.getByRole("dialog", { name: "Open project", exact: true })
|
||||
await expect(picker).toBeVisible()
|
||||
await picker.getByRole("button", { name: "Cancel", exact: true }).click()
|
||||
await expect(picker).toBeHidden()
|
||||
})
|
||||
|
||||
test("a single project uses the full grouped hover surface", async ({ page }) => {
|
||||
const view = ui(page)
|
||||
await view.settings.getByRole("tab", { name: "Projects", exact: true }).click()
|
||||
const list = view.settings.getByRole("list")
|
||||
const project = list.getByRole("listitem")
|
||||
await expect(project).toHaveCount(1)
|
||||
await expect
|
||||
.poll(() =>
|
||||
project.evaluate((item) => {
|
||||
const row = item.getBoundingClientRect()
|
||||
const group = item.parentElement?.parentElement?.getBoundingClientRect()
|
||||
if (!group) return []
|
||||
return [row.top - group.top, row.left - group.left, group.right - row.right, group.bottom - row.bottom]
|
||||
}),
|
||||
)
|
||||
.toEqual([0, 0, 0, 0])
|
||||
})
|
||||
|
||||
test("Projects search renders with a qualifying persisted inventory", async ({ page }) => {
|
||||
const projects = projectList(8)
|
||||
await page.route("**/api/project", (route) => route.fulfill({ json: projects }))
|
||||
await persistProjects(page, projects)
|
||||
await page.reload()
|
||||
const view = ui(page)
|
||||
const search = view.settings.getByRole("searchbox", { name: "Search projects", exact: true })
|
||||
await view.settings.getByRole("tab", { name: "Projects", exact: true }).click()
|
||||
await expect(search).toBeVisible()
|
||||
await expect(search).not.toBeFocused()
|
||||
await expect(view.settings.getByRole("button", { name: /^OpenCode / })).toHaveCount(8)
|
||||
})
|
||||
|
||||
test("all indexed client controls resolve to visible production controls", async ({ page }) => {
|
||||
const view = ui(page)
|
||||
for (const entry of clientSettings.filter((entry) => entry.target && !entry.available)) {
|
||||
@@ -207,11 +394,13 @@ test("qualified project results preserve query and selection on return", async (
|
||||
})
|
||||
|
||||
test("returning from a project restores a scrolled result list", async ({ page }) => {
|
||||
const projects = projectList(30)
|
||||
await page.route("**/api/project", (route) =>
|
||||
route.fulfill({
|
||||
json: projectList(30),
|
||||
json: projects,
|
||||
}),
|
||||
)
|
||||
await persistProjects(page, projects)
|
||||
await page.reload()
|
||||
const view = ui(page)
|
||||
await view.search.fill("OpenCode")
|
||||
@@ -313,14 +502,17 @@ test("multi-server results navigate to the named server and hide search in neste
|
||||
body: Buffer.from(await response.arrayBuffer()),
|
||||
})
|
||||
})
|
||||
await page.addInitScript(
|
||||
(server) =>
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:server",
|
||||
JSON.stringify({ list: [{ type: "http", displayName: "Build server", http: { url: server } }] }),
|
||||
),
|
||||
server,
|
||||
)
|
||||
await page.addInitScript((server) => {
|
||||
const value = JSON.parse(localStorage.getItem("opencode.global.dat:server") ?? "{}")
|
||||
localStorage.setItem(
|
||||
"opencode.global.dat:server",
|
||||
JSON.stringify({
|
||||
...value,
|
||||
list: [{ type: "http", displayName: "Build server", http: { url: server } }],
|
||||
projects: { ...value.projects, [server]: [{ worktree: "/remote/opencode", expanded: true }] },
|
||||
}),
|
||||
)
|
||||
}, server)
|
||||
await page.reload()
|
||||
const view = ui(page)
|
||||
await view.search.fill("MCPs")
|
||||
@@ -335,6 +527,13 @@ test("multi-server results navigate to the named server and hide search in neste
|
||||
await view.results.getByRole("option").click()
|
||||
await expect(view.settings.getByRole("searchbox", { name: "Search models", exact: true })).toBeFocused()
|
||||
await view.settings.getByRole("button", { name: "Back to settings", exact: true }).click()
|
||||
await view.search.fill("Build server projects")
|
||||
await view.results.getByRole("option").click()
|
||||
await expect(view.settings.getByRole("heading", { name: "Projects", exact: true })).toBeVisible()
|
||||
await expect(view.settings.getByRole("button", { name: "Add project", exact: true })).toBeVisible()
|
||||
await expect(view.settings.getByRole("list").getByRole("listitem")).toHaveCount(1)
|
||||
await expect(view.settings.getByRole("button", { name: "OpenCode", exact: true })).toBeVisible()
|
||||
await view.settings.getByRole("button", { name: "Back to settings", exact: true }).click()
|
||||
await view.search.fill("Build server OpenCode name")
|
||||
await expect(view.results.getByRole("option")).toHaveCount(1)
|
||||
await view.results.getByRole("option").click()
|
||||
|
||||
@@ -8,8 +8,13 @@ const directory = "C:/OpenCode/SubagentNavigation"
|
||||
const projectID = "proj_subagent_navigation"
|
||||
const parentID = "ses_subagent_parent"
|
||||
const childID = "ses_subagent_child"
|
||||
const grandchildID = "ses_subagent_grandchild"
|
||||
const greatGrandchildID = "ses_subagent_great_grandchild"
|
||||
const parentTitle = "Parent session"
|
||||
const childTitle = "Subagent child session"
|
||||
const grandchildTitle = "Nested subagent session"
|
||||
const greatGrandchildTitle =
|
||||
"Deep research subagent session investigating a very long chain of agent registry failures and navigation breadcrumbs"
|
||||
// Child session pages derive their heading from the task part that spawned them.
|
||||
const taskDescription = "Inspect child navigation"
|
||||
|
||||
@@ -25,6 +30,60 @@ test("navigates to a subagent child session missing from the session list", asyn
|
||||
await expect(page.getByRole("button", { name: "Toggle review", exact: true })).toBeVisible()
|
||||
})
|
||||
|
||||
test("opens a directly linked nested subagent in its root session tab", async ({ page }) => {
|
||||
await setup(page, undefined, 1)
|
||||
await page.goto(sessionHref(grandchildID), { waitUntil: "domcontentloaded" })
|
||||
|
||||
await expect(page.locator('[data-slot="session-title-parent"]')).toHaveText(childTitle)
|
||||
await expect(page.locator('[data-slot="session-title-child"]')).toHaveText(grandchildTitle)
|
||||
const tabs = page.locator('[data-slot="titlebar-tabs"] [data-titlebar-tab-slot]')
|
||||
await expect(tabs.locator(`a[href="${sessionHref(grandchildID)}"]`)).toHaveCount(1)
|
||||
await expect(tabs).toHaveCount(1)
|
||||
await expect(tabs.locator('[data-slot="tab-title"]')).toHaveText(parentTitle)
|
||||
})
|
||||
|
||||
test("shows the full ancestor path and navigates to an earlier subagent", async ({ page }) => {
|
||||
await setup(page, undefined, 2)
|
||||
await page.goto(sessionHref(greatGrandchildID), { waitUntil: "domcontentloaded" })
|
||||
|
||||
await expect(page.locator("[data-timeline-virtual-content]")).toBeAttached()
|
||||
const header = page.locator("[data-session-title]")
|
||||
await expect(header.locator('[data-slot="session-title-ancestor"]')).toHaveText([parentTitle, childTitle])
|
||||
await expect(header.locator('[data-slot="session-title-parent"]')).toHaveText(grandchildTitle)
|
||||
await expect(header.getByRole("heading", { name: greatGrandchildTitle })).toBeVisible()
|
||||
|
||||
await header.getByRole("button", { name: childTitle, exact: true }).click()
|
||||
await expect(page).toHaveURL(sessionHref(childID))
|
||||
await expect(page.locator("[data-session-title]").getByRole("heading", { name: childTitle })).toBeVisible()
|
||||
await expect(page.locator('[data-slot="titlebar-tabs"] [data-titlebar-tab-slot]')).toHaveCount(1)
|
||||
})
|
||||
|
||||
test("keeps the active nested session visible in a narrow desktop header", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 820, height: 720 })
|
||||
await setup(page, undefined, 2)
|
||||
await page.goto(sessionHref(greatGrandchildID), { waitUntil: "domcontentloaded" })
|
||||
|
||||
const header = page.locator("[data-session-title]")
|
||||
const heading = header.getByRole("heading", { name: greatGrandchildTitle })
|
||||
const separator = header.locator('[data-slot="session-title-ancestors"] + [data-slot="session-title-separator"]')
|
||||
await expect(header.locator('[data-slot="session-title-ancestor"]')).toHaveText([parentTitle, childTitle])
|
||||
await expect(heading).toBeInViewport()
|
||||
await expect(separator).toBeInViewport()
|
||||
const bounds = await heading.boundingBox()
|
||||
expect(bounds).not.toBeNull()
|
||||
expect(bounds!.x + bounds!.width).toBeLessThanOrEqual(820)
|
||||
|
||||
await page.evaluate(() => document.documentElement.setAttribute("dir", "rtl"))
|
||||
await expect(heading).toBeInViewport()
|
||||
await expect(separator).toBeInViewport()
|
||||
|
||||
const root = header.locator(`[data-slot="session-title-ancestor"][data-session-id="${parentID}"]`)
|
||||
await root.focus()
|
||||
await expect(root).toBeFocused()
|
||||
await root.press("Enter")
|
||||
await expect(page).toHaveURL(sessionHref(parentID))
|
||||
})
|
||||
|
||||
test("returns to the parent session with Escape", async ({ page }) => {
|
||||
await setup(page)
|
||||
await openChildFromParent(page)
|
||||
@@ -144,7 +203,7 @@ test("shows the not found fallback when the viewed session is deleted", async ({
|
||||
await expect(page.getByRole("heading", { name: taskDescription })).toHaveCount(0)
|
||||
})
|
||||
|
||||
async function setup(page: Page, events?: () => OpenCodeEvent[]) {
|
||||
async function setup(page: Page, events?: () => OpenCodeEvent[], nestedDepth: 0 | 1 | 2 = 0) {
|
||||
await mockOpenCodeServer(page, {
|
||||
directory,
|
||||
project: {
|
||||
@@ -168,7 +227,14 @@ async function setup(page: Page, events?: () => OpenCodeEvent[]) {
|
||||
connected: ["opencode"],
|
||||
default: { providerID: "opencode", modelID: "claude-opus-4-6" },
|
||||
},
|
||||
sessions: [session(parentID, parentTitle, 1700000000000), childSession()],
|
||||
sessions: [
|
||||
session(parentID, parentTitle, 1700000000000),
|
||||
childSession(),
|
||||
...(nestedDepth >= 1 ? [session(grandchildID, grandchildTitle, 1700000002000, { parentID: childID })] : []),
|
||||
...(nestedDepth >= 2
|
||||
? [session(greatGrandchildID, greatGrandchildTitle, 1700000003000, { parentID: grandchildID })]
|
||||
: []),
|
||||
],
|
||||
pageMessages: (sessionID) => ({ items: sessionID === parentID ? parentMessages() : [] }),
|
||||
events,
|
||||
eventRetry: events ? 16 : undefined,
|
||||
|
||||
@@ -154,13 +154,13 @@ test("mobile drawer exposes close controls and navigates between tabs", async ({
|
||||
}
|
||||
})
|
||||
|
||||
test("vertical tabs show project details, resize, and navigate", async ({ page }) => {
|
||||
test("vertical tabs resize and navigate without retired project labels", async ({ page }) => {
|
||||
await mockServer(page)
|
||||
await page.addInitScript(
|
||||
({ server, sessionA, sessionB }) => {
|
||||
localStorage.setItem(
|
||||
"settings.v3",
|
||||
JSON.stringify({ appearance: { tabLayout: "vertical", showProjectName: true }, general: { showStatus: true } }),
|
||||
JSON.stringify({ appearance: { tabLayout: "vertical" }, general: { showStatus: true } }),
|
||||
)
|
||||
localStorage.setItem(
|
||||
"opencode.window.browser.dat:tabs",
|
||||
@@ -183,7 +183,7 @@ test("vertical tabs show project details, resize, and navigate", async ({ page }
|
||||
await expect(sidebar).toHaveCSS("width", "260px")
|
||||
await expect(tabA).toContainText(sessionA.title)
|
||||
await expect(tabB).toContainText(sessionB.title)
|
||||
await expect(tabB.locator('[data-slot="tab-project"]')).toHaveText("tab-project")
|
||||
await expect(tabB.locator('[data-slot="tab-project"]')).toHaveCount(0)
|
||||
await expect(
|
||||
sidebar.getByRole("button", { name: "Home", exact: true }).getByText("Home", { exact: true }),
|
||||
).toBeVisible()
|
||||
@@ -209,7 +209,7 @@ test("vertical tabs show project details, resize, and navigate", async ({ page }
|
||||
await page.mouse.move(box.x + box.width / 2 - 80, box.y + box.height / 2)
|
||||
await page.mouse.up()
|
||||
await expect(sidebar).toHaveCSS("width", "180px")
|
||||
await expect(tabB.locator('[data-slot="tab-project"]')).toHaveText("tab-project")
|
||||
await expect(tabB.locator('[data-slot="tab-project"]')).toHaveCount(0)
|
||||
|
||||
const resized = await handle.boundingBox()
|
||||
if (!resized) throw new Error("resized vertical tab handle has no bounding box")
|
||||
@@ -432,7 +432,7 @@ for (const profile of [
|
||||
})
|
||||
}
|
||||
|
||||
test("dedicated experimental settings control vertical tab details", async ({ page }) => {
|
||||
test("preferences control vertical tab layout and hide empty experimental settings", async ({ page }) => {
|
||||
await mockServer(page)
|
||||
await page.addInitScript(
|
||||
({ server, sessionA }) => {
|
||||
@@ -452,15 +452,20 @@ test("dedicated experimental settings control vertical tab details", async ({ pa
|
||||
await expect(settings).toBeVisible()
|
||||
await expect(settings.getByRole("tablist").getByText("OpenCode Desktop", { exact: true })).toHaveCount(0)
|
||||
await expect(settings.getByRole("tablist").getByText(/^v\d+\./)).toHaveCount(0)
|
||||
await settings.getByRole("tab", { name: "Appearance" }).click()
|
||||
await expect(settings.getByRole("heading", { name: "Appearance", exact: true })).toBeVisible()
|
||||
await expect(settings.locator('[data-action="settings-tab-layout"]')).toHaveCount(0)
|
||||
await expect(settings.getByRole("heading", { name: "Preferences", exact: true })).toBeVisible()
|
||||
await expect(settings.getByRole("tab", { name: "Experimental", exact: true })).toHaveCount(0)
|
||||
await expect(settings.getByRole("switch", { name: "Show project names", exact: true })).toHaveCount(0)
|
||||
await settings.getByRole("tab", { name: "Experimental", exact: true }).click()
|
||||
await expect(settings.getByRole("heading", { name: "Experimental", level: 2, exact: true })).toBeVisible()
|
||||
|
||||
const language = settings.locator('[data-action="settings-language"]')
|
||||
const layout = settings.locator('[data-action="settings-tab-layout"]')
|
||||
await expect(language).toBeVisible()
|
||||
await expect(layout).toContainText("Horizontal")
|
||||
await expect
|
||||
.poll(async () => {
|
||||
const [languageBox, layoutBox] = await Promise.all([language.boundingBox(), layout.boundingBox()])
|
||||
return !!languageBox && !!layoutBox && layoutBox.y > languageBox.y
|
||||
})
|
||||
.toBe(true)
|
||||
await layout.click()
|
||||
await page.getByRole("option", { name: "Vertical" }).click()
|
||||
|
||||
@@ -469,42 +474,38 @@ test("dedicated experimental settings control vertical tab details", async ({ pa
|
||||
await expect(page.locator('[data-slot="titlebar-tabs"]')).toHaveCount(0)
|
||||
const projectNames = page.locator('[data-slot="vertical-tabs-sidebar"] [data-slot="tab-project"]')
|
||||
await expect(projectNames).toHaveCount(0)
|
||||
const projectNameSwitch = settings.getByRole("switch", { name: "Show project names", exact: true })
|
||||
await settings.locator('[data-action="settings-show-project-name"] [data-slot="switch-control"]').click()
|
||||
await expect(projectNameSwitch).toBeChecked()
|
||||
await expect(projectNames).toHaveText(["tab-project"])
|
||||
await expect(settings.getByRole("complementary")).toHaveCSS("width", "240px")
|
||||
|
||||
await page.setViewportSize({ width: 920, height: 720 })
|
||||
await expect(page.locator('[data-slot="vertical-tabs-sidebar"]')).toHaveCSS("width", "260px")
|
||||
await expect(settings.getByRole("tablist")).toBeHidden()
|
||||
await expect(settings.getByRole("button", { name: "Experimental", exact: true })).toBeVisible()
|
||||
await expect(settings.getByRole("button", { name: "Preferences", exact: true })).toBeVisible()
|
||||
|
||||
await page.setViewportSize({ width: 800, height: 720 })
|
||||
await expect(settings.getByRole("tablist")).toBeHidden()
|
||||
await expect(settings.getByRole("button", { name: "Experimental", exact: true })).toBeVisible()
|
||||
await expect(settings.getByRole("button", { name: "Preferences", exact: true })).toBeVisible()
|
||||
|
||||
await page.setViewportSize({ width: 390, height: 720 })
|
||||
await settings.getByRole("button", { name: "Experimental", exact: true }).click()
|
||||
await settings.getByRole("button", { name: "Preferences", exact: true }).click()
|
||||
await expect(page.getByRole("menuitemradio", { name: "Experimental", exact: true })).toHaveCount(0)
|
||||
await page.getByRole("menuitemradio", { name: "Appearance", exact: true }).click()
|
||||
await expect(settings.getByRole("heading", { name: "Appearance", exact: true })).toBeVisible()
|
||||
await expect(layout).toHaveCount(0)
|
||||
await settings.getByRole("button", { name: "Appearance", exact: true }).click()
|
||||
await page.getByRole("menuitemradio", { name: "Experimental", exact: true }).click()
|
||||
await expect(settings.getByRole("heading", { name: "Experimental", level: 2, exact: true })).toBeVisible()
|
||||
await page.getByRole("menuitemradio", { name: "Preferences", exact: true }).click()
|
||||
await expect(settings.getByRole("heading", { name: "Preferences", level: 2, exact: true })).toBeVisible()
|
||||
await expect(layout).toContainText("Vertical")
|
||||
await expect(projectNameSwitch).toBeChecked()
|
||||
await settings.evaluate((element) => element.setAttribute("dir", "rtl"))
|
||||
await expect(settings.getByRole("button", { name: "Experimental", exact: true })).toBeInViewport()
|
||||
await expect(settings.getByRole("button", { name: "Preferences", exact: true })).toBeInViewport()
|
||||
|
||||
await page.setViewportSize({ width: 390, height: 360 })
|
||||
await expect(settings.getByRole("button", { name: "Experimental", exact: true })).toBeInViewport()
|
||||
await expect(settings.getByRole("button", { name: "Preferences", exact: true })).toBeInViewport()
|
||||
|
||||
// Reload the UI-selected preference without seeding settings storage.
|
||||
await page.reload()
|
||||
const href = `/server/${base64Encode(server)}/session/${sessionA.id}`
|
||||
await page.getByRole("button", { name: "Tabs", exact: true }).click()
|
||||
await expect(page.locator('[data-slot="mobile-tabs-drawer"] [data-slot="tab-project"]')).toHaveText(["tab-project"])
|
||||
await expect(page.locator('[data-slot="mobile-tabs-drawer"] [data-slot="tab-project"]')).toHaveCount(0)
|
||||
await expect(
|
||||
page
|
||||
.locator('[data-slot="mobile-tabs-drawer"]')
|
||||
@@ -522,7 +523,7 @@ test("dedicated experimental settings control vertical tab details", async ({ pa
|
||||
).toBeVisible()
|
||||
await expect(page.locator('[data-slot="titlebar-tabs"]')).toHaveCount(0)
|
||||
await page.keyboard.press("Control+,")
|
||||
await settings.getByRole("tab", { name: "Experimental", exact: true }).click()
|
||||
await expect(settings.getByRole("heading", { name: "Preferences", exact: true })).toBeVisible()
|
||||
await expect(layout).toContainText("Vertical")
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode/app",
|
||||
"version": "2.0.15",
|
||||
"version": "2.0.16",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -27,7 +27,10 @@ export const uploads = {
|
||||
const controller = new AbortController()
|
||||
setState("items", (items) => [...items, { ...input, loaded: 0, cancel: () => controller.abort() }])
|
||||
try {
|
||||
return await work((loaded) => setState("items", (item) => item.id === input.id, "loaded", loaded), controller.signal)
|
||||
return await work(
|
||||
(loaded) => setState("items", (item) => item.id === input.id, "loaded", loaded),
|
||||
controller.signal,
|
||||
)
|
||||
} catch (error) {
|
||||
if (controller.signal.aborted) return undefined
|
||||
throw error
|
||||
@@ -101,7 +104,7 @@ function UploadToast(props: { toastId: number; language: ReturnType<typeof useLa
|
||||
<button
|
||||
type="button"
|
||||
data-slot="upload-row-cancel"
|
||||
aria-label={props.language.t("prompt.toast.uploading.cancel")}
|
||||
aria-label={props.language.t("prompt.toast.uploading.cancelFile", { filename: item.filename })}
|
||||
onClick={() => item.cancel()}
|
||||
>
|
||||
<Icon name="outline-xmark" />
|
||||
|
||||
@@ -57,6 +57,8 @@ function ComposerStory(props: {
|
||||
continueOnStop?: boolean
|
||||
longLabels?: boolean
|
||||
alternate?: "queue" | "steer"
|
||||
manySuggestions?: boolean
|
||||
suggestionBoundary?: () => HTMLElement | undefined
|
||||
}) {
|
||||
const [draft, setDraft] = createStore<ComposerPersistedState>({
|
||||
prompt: props.prompt ?? [{ type: "text", content: "", start: 0, end: 0 }],
|
||||
@@ -93,6 +95,15 @@ function ComposerStory(props: {
|
||||
const commands: ComposerSuggestion[] = [
|
||||
{ id: "command.test", kind: "command", label: "/test", trigger: "test", title: "Run tests" },
|
||||
{ id: "command.review", kind: "command", label: "/review", trigger: "review", title: "Review changes" },
|
||||
...(props.manySuggestions
|
||||
? Array.from({ length: 12 }, (_, index) => ({
|
||||
id: `command.example-${index}`,
|
||||
kind: "command" as const,
|
||||
label: `/example-${index}`,
|
||||
trigger: `example-${index}`,
|
||||
title: `Run example ${index}`,
|
||||
}))
|
||||
: []),
|
||||
]
|
||||
const context: ComposerSuggestion[] = [
|
||||
{
|
||||
@@ -206,7 +217,7 @@ function ComposerStory(props: {
|
||||
<output class="text-12-regular text-text-weak" aria-live="polite">
|
||||
{story.activity}
|
||||
</output>
|
||||
<Composer model={model} borderUnderlay />
|
||||
<Composer model={model} borderUnderlay suggestionBoundary={props.suggestionBoundary} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -273,6 +284,25 @@ export const SlashSuggestions = { render: () => <ComposerStory suggestions="comm
|
||||
|
||||
export const ContextSuggestions = { render: () => <ComposerStory suggestions="context" /> }
|
||||
|
||||
function ConstrainedCommandSuggestionsStory() {
|
||||
let boundary: HTMLDivElement | undefined
|
||||
return (
|
||||
<div class="mx-auto w-full max-w-200">
|
||||
<div ref={boundary} data-slot="composer-suggestion-boundary-story" class="h-60" />
|
||||
<ComposerStory suggestions="command" manySuggestions suggestionBoundary={() => boundary} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const ConstrainedCommandSuggestions = { render: () => <ConstrainedCommandSuggestionsStory /> }
|
||||
|
||||
export const DetachedCommandSuggestionBoundary = {
|
||||
render: () => {
|
||||
const detached = document.createElement("div")
|
||||
return <ComposerStory suggestions="command" manySuggestions suggestionBoundary={() => detached} />
|
||||
},
|
||||
}
|
||||
|
||||
export const RunningAndStopping = { render: () => <ComposerStory working stopping label="Session is running" /> }
|
||||
|
||||
export const SteeringFollowUp = {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Button } from "@opencode/ui/button"
|
||||
import { useDialog } from "@opencode/ui/context/dialog"
|
||||
import { Icon } from "@opencode/ui/icon"
|
||||
import { Keybind } from "@opencode/ui/keybind"
|
||||
import { ProviderIcon } from "@opencode/ui/provider-icon"
|
||||
import { ProviderModelIcon } from "@/providers/models/provider-group"
|
||||
import { Tooltip } from "@opencode/ui/tooltip"
|
||||
import { ComposerEditor } from "./editor/editor"
|
||||
import { ModelSelectorPopover } from "@/providers/models/select-dialog"
|
||||
@@ -12,7 +12,12 @@ import { formatKeybind, useCommand } from "@/shell/commands/command"
|
||||
import { useLanguage } from "@/runtime/i18n/language"
|
||||
import type { ComposerModel } from "./model"
|
||||
|
||||
export function Composer(props: { class?: string; model: ComposerModel; borderUnderlay?: boolean }) {
|
||||
export function Composer(props: {
|
||||
class?: string
|
||||
model: ComposerModel
|
||||
borderUnderlay?: boolean
|
||||
suggestionBoundary?: () => HTMLElement | undefined
|
||||
}) {
|
||||
const dialog = useDialog()
|
||||
const command = useCommand()
|
||||
const language = useLanguage()
|
||||
@@ -28,6 +33,7 @@ export function Composer(props: { class?: string; model: ComposerModel; borderUn
|
||||
attachShortcut={command.keybind("file.attach")}
|
||||
alternateKeybind={[formatKeybind("mod", language.t), "↵"]}
|
||||
exitShellKeybind={[formatKeybind("esc", language.t)]}
|
||||
suggestionBoundary={props.suggestionBoundary}
|
||||
modelControl={
|
||||
<ComposerModelControl
|
||||
loading={props.model.model.loading}
|
||||
@@ -35,7 +41,7 @@ export function Composer(props: { class?: string; model: ComposerModel; borderUn
|
||||
title={language.t("command.model.choose")}
|
||||
keybind={command.keybindParts("model.choose")}
|
||||
model={props.model.model.selection}
|
||||
providerID={props.model.model.selection.current()?.provider?.id}
|
||||
provider={props.model.model.selection.current()?.provider}
|
||||
modelName={props.model.model.selection.current()?.name ?? language.t("dialog.model.select.title")}
|
||||
onClose={props.model.restoreFocus}
|
||||
onUnpaidClick={() => dialog.show(() => <DialogSelectModelUnpaid model={props.model.model.selection} />)}
|
||||
@@ -52,7 +58,7 @@ function ComposerModelControl(props: {
|
||||
title: string
|
||||
keybind: string[]
|
||||
model: ComposerModel["model"]["selection"]
|
||||
providerID?: string
|
||||
provider?: { id: string; canonical?: string; name: string }
|
||||
modelName: string
|
||||
onClose: () => void
|
||||
onUnpaidClick: () => void
|
||||
@@ -60,12 +66,11 @@ function ComposerModelControl(props: {
|
||||
const shouldAnimate = createMemo<boolean>((previous) => previous ?? props.loading)
|
||||
const content = () => (
|
||||
<>
|
||||
<Show when={props.providerID}>
|
||||
{(providerID) => (
|
||||
<ProviderIcon
|
||||
id={providerID()}
|
||||
class="size-4 shrink-0 opacity-40 group-hover:opacity-100 transition-opacity duration-150"
|
||||
style={{ "will-change": "opacity", transform: "translateZ(0)" }}
|
||||
<Show when={props.provider}>
|
||||
{(provider) => (
|
||||
<ProviderModelIcon
|
||||
provider={provider()}
|
||||
class="shrink-0 opacity-40 transition-opacity duration-150 group-hover:opacity-100"
|
||||
/>
|
||||
)}
|
||||
</Show>
|
||||
|
||||
@@ -11,12 +11,13 @@ import {
|
||||
type JSX,
|
||||
} from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { createResizeObserver } from "@solid-primitives/resize-observer"
|
||||
import { FileIcon } from "@opencode/ui/file-icon"
|
||||
import { Icon } from "@opencode/ui/icon"
|
||||
import { IconButton } from "@opencode/ui/icon-button"
|
||||
import { createAnimatedPresence } from "@/runtime/animated-presence"
|
||||
import { resolveBlobUrl } from "@/runtime/persistence/drafts"
|
||||
import { ProviderIcon } from "@opencode/ui/provider-icon"
|
||||
import { ProviderModelIcon } from "@/providers/models/provider-group"
|
||||
import { useI18n } from "@opencode/ui/context/i18n"
|
||||
import { Button } from "@opencode/ui/button"
|
||||
import { Keybind } from "@opencode/ui/keybind"
|
||||
@@ -51,6 +52,12 @@ export type {
|
||||
} from "../types"
|
||||
|
||||
export type ComposerMode = "normal" | "shell"
|
||||
const COMPOSER_SUGGESTION_MAX_HEIGHT = 320
|
||||
const COMPOSER_SUGGESTION_ROW_HEIGHT = 28
|
||||
const COMPOSER_SUGGESTION_ROW_PEEK = 18
|
||||
const COMPOSER_SUGGESTION_TOP_PADDING = 8
|
||||
const COMPOSER_SUGGESTION_SEARCH_HEIGHT = 28
|
||||
const COMPOSER_SUGGESTION_CONTEXT_RESERVE = 80
|
||||
|
||||
export type ComposerEditorProps = {
|
||||
controller: ComposerEditorModel
|
||||
@@ -64,6 +71,7 @@ export type ComposerEditorProps = {
|
||||
attachShortcut?: string
|
||||
alternateKeybind?: string[]
|
||||
exitShellKeybind?: string[]
|
||||
suggestionBoundary?: () => HTMLElement | undefined
|
||||
}
|
||||
|
||||
export function ComposerEditor(props: ComposerEditorProps) {
|
||||
@@ -128,6 +136,7 @@ export function ComposerEditor(props: ComposerEditorProps) {
|
||||
<ComposerEditorPopover
|
||||
emptyLabel={i18n.t("ui.promptInput.noMatchingItems")}
|
||||
items={props.controller.suggestions()}
|
||||
boundary={props.suggestionBoundary}
|
||||
activeID={state.popover.type === "closed" ? undefined : state.popover.activeID}
|
||||
search={
|
||||
state.popover.type === "command-menu"
|
||||
@@ -533,7 +542,7 @@ export function ComposerAttachments(props: {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => props.onCommentRemove?.(comment)}
|
||||
class="absolute -top-1 -end-1 size-4 rounded-full bg-v2-icon-icon-muted outline-solid outline-1 outline-v2-icon-icon-contrast flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
class="absolute -top-1 -end-1 size-4 rounded-full bg-v2-icon-icon-muted outline-solid outline-1 outline-v2-icon-icon-contrast flex items-center justify-center hover-reveal group-hover:opacity-100"
|
||||
aria-label={props.removeLabel}
|
||||
>
|
||||
<Icon name="outline-xmark" class="text-v2-icon-icon-contrast" />
|
||||
@@ -580,7 +589,7 @@ export function ComposerAttachments(props: {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => props.onAttachmentRemove(attachment)}
|
||||
class="absolute -top-1 -end-1 size-4 rounded-full bg-v2-icon-icon-muted outline-solid outline-1 outline-v2-icon-icon-contrast flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
class="absolute -top-1 -end-1 size-4 rounded-full bg-v2-icon-icon-muted outline-solid outline-1 outline-v2-icon-icon-contrast flex items-center justify-center hover-reveal group-hover:opacity-100"
|
||||
aria-label={props.removeLabel}
|
||||
>
|
||||
<Icon name="outline-xmark" class="text-v2-icon-icon-contrast" />
|
||||
@@ -602,7 +611,7 @@ export function ComposerAttachments(props: {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => props.onUploadCancel?.(upload)}
|
||||
class="absolute -top-1 -end-1 size-4 rounded-full bg-v2-icon-icon-muted outline-solid outline-1 outline-v2-icon-icon-contrast flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
class="absolute -top-1 -end-1 size-4 rounded-full bg-v2-icon-icon-muted outline-solid outline-1 outline-v2-icon-icon-contrast flex items-center justify-center hover-reveal group-hover:opacity-100"
|
||||
aria-label={i18n.t("ui.promptInput.cancelUpload")}
|
||||
>
|
||||
<Icon name="outline-xmark" class="text-v2-icon-icon-contrast" />
|
||||
@@ -702,7 +711,7 @@ function ComposerEditorConfiguredSelect(props: {
|
||||
current={current()}
|
||||
currentIcon={
|
||||
<Show when={props.model && providerID()}>
|
||||
<ProviderIcon id={providerID()!} class="size-4 shrink-0 opacity-60" />
|
||||
{(id) => <ProviderModelIcon provider={{ id: id(), name: id() }} class="shrink-0 opacity-60" />}
|
||||
</Show>
|
||||
}
|
||||
onSelect={props.control.onSelect}
|
||||
@@ -775,18 +784,31 @@ export function ComposerEditorPopover(props: {
|
||||
onValueChange: (value: string) => void
|
||||
onKeyDown: (event: KeyboardEvent) => void
|
||||
}
|
||||
boundary?: () => HTMLElement | undefined
|
||||
onActiveChange: (item: ComposerSuggestion) => void
|
||||
onSelect: (item: ComposerSuggestion) => void
|
||||
}) {
|
||||
const [store, setStore] = createStore({ maxHeight: COMPOSER_SUGGESTION_MAX_HEIGHT })
|
||||
const resize = (height: number) =>
|
||||
setStore("maxHeight", composerSuggestionMaxHeight(height, props.search !== undefined))
|
||||
// A detached boundary (e.g. the previous session's timeline while the next one loads) measures 0px.
|
||||
const boundary = () => {
|
||||
const element = props.boundary?.()
|
||||
return element?.isConnected ? element : undefined
|
||||
}
|
||||
createEffect(() => resize(boundary()?.clientHeight ?? COMPOSER_SUGGESTION_MAX_HEIGHT * 2))
|
||||
createResizeObserver(boundary, (rect) => resize(rect.height))
|
||||
|
||||
return (
|
||||
<div
|
||||
data-component="composer-suggestions"
|
||||
class="absolute inset-x-0 -top-2 z-40 flex max-h-80 -translate-y-full flex-col overflow-auto rounded-xl bg-v2-background-bg-base p-2 shadow-[var(--v2-elevation-raised)] no-scrollbar"
|
||||
class="absolute inset-x-0 -top-2 z-40 flex -translate-y-full scroll-pb-[18px] flex-col overflow-auto rounded-xl bg-v2-background-bg-base p-2 shadow-[var(--v2-elevation-raised)] no-scrollbar"
|
||||
style={{ "max-height": `${store.maxHeight}px` }}
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
>
|
||||
<Show when={props.search}>
|
||||
{(search) => (
|
||||
<div class="px-2 py-1">
|
||||
<div class="shrink-0 px-2 py-1">
|
||||
<input
|
||||
ref={(element) => requestAnimationFrame(() => element.focus())}
|
||||
value={search().value}
|
||||
@@ -810,7 +832,7 @@ export function ComposerEditorPopover(props: {
|
||||
type="button"
|
||||
data-suggestion-id={item.id}
|
||||
data-active={props.activeID === item.id ? "" : undefined}
|
||||
class="flex w-full items-center gap-2 rounded-md px-2 py-1 text-start hover:bg-v2-overlay-simple-overlay-hover"
|
||||
class="flex h-7 w-full shrink-0 items-center gap-2 rounded-md px-2 py-1 text-start hover:bg-v2-overlay-simple-overlay-hover"
|
||||
classList={{ "bg-v2-overlay-simple-overlay-hover": props.activeID === item.id }}
|
||||
onPointerMove={() => props.onActiveChange(item)}
|
||||
onClick={() => props.onSelect(item)}
|
||||
@@ -835,6 +857,19 @@ export function ComposerEditorPopover(props: {
|
||||
)
|
||||
}
|
||||
|
||||
function composerSuggestionMaxHeight(boundaryHeight: number, search: boolean) {
|
||||
const reserve = Math.min(COMPOSER_SUGGESTION_CONTEXT_RESERVE, boundaryHeight / 4)
|
||||
const limit = Math.min(COMPOSER_SUGGESTION_MAX_HEIGHT, boundaryHeight - reserve)
|
||||
const chrome = COMPOSER_SUGGESTION_TOP_PADDING + (search ? COMPOSER_SUGGESTION_SEARCH_HEIGHT : 0)
|
||||
if (limit < chrome + COMPOSER_SUGGESTION_ROW_HEIGHT + COMPOSER_SUGGESTION_ROW_PEEK) return limit
|
||||
return (
|
||||
chrome +
|
||||
Math.floor((limit - chrome - COMPOSER_SUGGESTION_ROW_PEEK) / COMPOSER_SUGGESTION_ROW_HEIGHT) *
|
||||
COMPOSER_SUGGESTION_ROW_HEIGHT +
|
||||
COMPOSER_SUGGESTION_ROW_PEEK
|
||||
)
|
||||
}
|
||||
|
||||
// "Steer ⌘⏎" / "Queue ⌘⏎" hint next to the submit button: submits with the
|
||||
// delivery opposite to what plain Enter does. Visible only while the queue
|
||||
// exposes an alternate (turn running and composer holding a value), so it
|
||||
|
||||
@@ -5,6 +5,8 @@ import { useTabs } from "@/shell/tabs/tabs"
|
||||
import { toggleHomeProjectSelection } from "@/shell/layout/helpers"
|
||||
import { createEffect, createMemo, startTransition } from "solid-js"
|
||||
import type { SessionInfo } from "@opencode/client/promise"
|
||||
import { pathKey } from "@/workspaces/path-key"
|
||||
import { addProjects } from "./projects/add"
|
||||
|
||||
export function createHomeController() {
|
||||
const layout = useLayout()
|
||||
@@ -41,6 +43,24 @@ export function createHomeController() {
|
||||
// Selecting a project is the demand for its worktree inventory: the session filter spans its worktrees.
|
||||
void ctx.sync.worktrees.list(id).then(() => ctx.sync.worktrees.refresh(id))
|
||||
})
|
||||
createEffect(() => {
|
||||
// The project list is empty until the server store hydrates; clearing the restored
|
||||
// selection against it would persist the loss.
|
||||
if (!servers.hydrated()) return
|
||||
const current = selection()
|
||||
const directory = current.directory
|
||||
if (!directory) return
|
||||
const conn = servers.visible.find((conn) => ServerConnection.key(conn) === current.server)
|
||||
if (!conn) return
|
||||
if (
|
||||
global
|
||||
.ensureServerCtx(conn)
|
||||
.projects.list()
|
||||
.some((project) => pathKey(project.worktree) === pathKey(directory))
|
||||
)
|
||||
return
|
||||
setSelection({ server: current.server })
|
||||
})
|
||||
|
||||
function setSelection(next: HomeProjectSelection) {
|
||||
layout.home.setSelection(next)
|
||||
@@ -99,23 +119,8 @@ export function createHomeController() {
|
||||
setSelection(toggleHomeProjectSelection(selection(), key, directory))
|
||||
},
|
||||
add: (conn: ServerConnection.Any, directories: string[]) => {
|
||||
const directory = directories[0]
|
||||
const directory = addProjects(global.ensureServerCtx(conn), directories)
|
||||
if (!directory) return
|
||||
const ctx = global.ensureServerCtx(conn)
|
||||
directories.forEach((item) => {
|
||||
if (ctx.projects.list().some((project) => project.worktree === item)) return
|
||||
const location = { directory: item }
|
||||
void ctx.sdk.api.file
|
||||
.list({ path: ".", location })
|
||||
.then(async (files) => {
|
||||
// TODO: Initialize empty directories when V2 exposes a native Git init API.
|
||||
return ctx.sdk.api.location.get({ location }).then((result) => result.project)
|
||||
})
|
||||
.then((project) => ctx.sync.child(item, { bootstrap: false })[1]("project", project.id))
|
||||
.catch(() => undefined)
|
||||
ctx.projects.open(item)
|
||||
})
|
||||
ctx.projects.touch(directory)
|
||||
setSelection({ server: ServerConnection.key(conn), directory })
|
||||
},
|
||||
openNewSession: () => {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { ServerCtx } from "@/runtime/server/runtime"
|
||||
|
||||
export function addProjects(context: ServerCtx, directories: string[]) {
|
||||
const directory = directories[0]
|
||||
if (!directory) return
|
||||
|
||||
directories.forEach((item) => {
|
||||
if (context.projects.list().some((project) => project.worktree === item)) return
|
||||
const location = { directory: item }
|
||||
void context.sdk.api.file
|
||||
.list({ path: ".", location })
|
||||
.then(() => context.sdk.api.location.get({ location }))
|
||||
.then((value) => context.sync.child(item, { bootstrap: false })[1]("project", value.project.id))
|
||||
.catch(() => undefined)
|
||||
context.projects.open(item)
|
||||
})
|
||||
context.projects.touch(directory)
|
||||
return directory
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import type { HomeController } from "../model"
|
||||
import { useGlobal } from "@/runtime/server/runtime"
|
||||
import { SessionTransfer } from "@opencode/schema/session-transfer"
|
||||
import { useSshAuthenticate } from "@/servers/ssh/authenticate"
|
||||
import { useRevealProject } from "./reveal"
|
||||
|
||||
export const HomeServersSchema = Schema.Struct({
|
||||
collapsed: Persistence.record(Persistence.fallback(Schema.Boolean, () => false)),
|
||||
@@ -32,6 +33,7 @@ export function createHomeProjectsController(home: HomeController) {
|
||||
const serverManagement = useServerActionsController()
|
||||
const global = useGlobal()
|
||||
const authenticate = useSshAuthenticate()
|
||||
const revealProject = useRevealProject()
|
||||
const [_state, setState, _, ready] = persisted(Persist.global("home.servers"), HomeServersSchema, { collapsed: {} })
|
||||
const [state] = createResource(
|
||||
() => ready.promise ?? Promise.resolve(),
|
||||
@@ -42,10 +44,6 @@ export function createHomeProjectsController(home: HomeController) {
|
||||
return [project.worktree, ...(project.sandboxes ?? [])]
|
||||
}
|
||||
|
||||
function canRevealProject(conn: ServerConnection.Any) {
|
||||
return platform.platform === "desktop" && !!platform.openPath && ServerConnection.local(conn)
|
||||
}
|
||||
|
||||
function choose(conn: ServerConnection.Any) {
|
||||
pickDirectory({
|
||||
server: conn,
|
||||
@@ -165,16 +163,8 @@ export function createHomeProjectsController(home: HomeController) {
|
||||
move: (conn: ServerConnection.Any, worktree: string, index: number) => {
|
||||
home.server.context(conn).projects.move(worktree, index)
|
||||
},
|
||||
canReveal: canRevealProject,
|
||||
reveal: (conn: ServerConnection.Any, project: LocalProject) => {
|
||||
if (!platform.openPath || !canRevealProject(conn)) return
|
||||
platform.openPath(project.worktree).catch((cause: unknown) =>
|
||||
showToast({
|
||||
title: language.t("common.requestFailed"),
|
||||
description: errorMessage(cause, language.t("common.requestFailed")),
|
||||
}),
|
||||
)
|
||||
},
|
||||
canReveal: revealProject.available,
|
||||
reveal: revealProject.reveal,
|
||||
},
|
||||
utility: {
|
||||
settings: openSettings,
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { useLanguage } from "@/runtime/i18n/language"
|
||||
import { usePlatform } from "@/runtime/platform/platform"
|
||||
import { ServerConnection } from "@/runtime/server/registry"
|
||||
import { displayName, errorMessage } from "@/shell/layout/helpers"
|
||||
import type { LocalProject } from "@/shell/state/layout"
|
||||
import { showToast } from "@/shell/notifications/toast"
|
||||
|
||||
export function useRevealProject() {
|
||||
const language = useLanguage()
|
||||
const platform = usePlatform()
|
||||
const available = (conn: ServerConnection.Any) =>
|
||||
platform.platform === "desktop" && !!platform.revealPath && ServerConnection.local(conn)
|
||||
|
||||
return {
|
||||
available,
|
||||
reveal(conn: ServerConnection.Any, project: LocalProject) {
|
||||
if (!platform.revealPath || !available(conn)) return
|
||||
void platform
|
||||
.revealPath(project.worktree)
|
||||
.then((revealed) => {
|
||||
if (revealed) return
|
||||
showToast({
|
||||
variant: "error",
|
||||
title: language.t("home.project.missing.title"),
|
||||
description: language.t("home.project.missing.description", { name: displayName(project) }),
|
||||
})
|
||||
})
|
||||
.catch((cause: unknown) =>
|
||||
showToast({
|
||||
title: language.t("common.requestFailed"),
|
||||
description: errorMessage(cause, language.t("common.requestFailed")),
|
||||
}),
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { createRoot } from "solid-js"
|
||||
import { createAltHold } from "./alt-hold"
|
||||
|
||||
describe("createAltHold", () => {
|
||||
test("is active only while Alt is held and resets on blur", () => {
|
||||
let active = () => false
|
||||
let presses = 0
|
||||
const dispose = createRoot((dispose) => {
|
||||
active = createAltHold(true, () => presses++)
|
||||
return dispose
|
||||
})
|
||||
|
||||
window.dispatchEvent(new KeyboardEvent("keydown", { key: "Alt" }))
|
||||
window.dispatchEvent(new KeyboardEvent("keydown", { key: "Alt", repeat: true }))
|
||||
expect(active()).toBe(true)
|
||||
expect(presses).toBe(1)
|
||||
|
||||
window.dispatchEvent(new KeyboardEvent("keyup", { key: "Alt" }))
|
||||
expect(active()).toBe(false)
|
||||
|
||||
window.dispatchEvent(new KeyboardEvent("keydown", { key: "Alt" }))
|
||||
window.dispatchEvent(new Event("blur"))
|
||||
expect(active()).toBe(false)
|
||||
expect(presses).toBe(2)
|
||||
dispose()
|
||||
})
|
||||
|
||||
test("does nothing outside Desktop", () => {
|
||||
let presses = 0
|
||||
const active = createRoot((dispose) => {
|
||||
const value = createAltHold(false, () => presses++)
|
||||
dispose()
|
||||
return value
|
||||
})
|
||||
|
||||
window.dispatchEvent(new KeyboardEvent("keydown", { key: "Alt" }))
|
||||
expect(active()).toBe(false)
|
||||
expect(presses).toBe(0)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
import { makeEventListener } from "@solid-primitives/event-listener"
|
||||
import { createStore } from "solid-js/store"
|
||||
|
||||
export function createAltHold(enabled: boolean, onPress: () => void) {
|
||||
const [state, setState] = createStore({ active: false })
|
||||
if (!enabled) return () => false
|
||||
|
||||
makeEventListener(window, "keydown", (event) => {
|
||||
if (event.key !== "Alt" || state.active) return
|
||||
setState("active", true)
|
||||
onPress()
|
||||
})
|
||||
makeEventListener(window, "keyup", (event) => {
|
||||
if (event.key === "Alt") setState("active", false)
|
||||
})
|
||||
makeEventListener(window, "blur", () => setState("active", false))
|
||||
|
||||
return () => state.active
|
||||
}
|
||||
@@ -26,7 +26,7 @@ import { sessionLabel, sessionTitle } from "@/session/title"
|
||||
import { showToast } from "@/shell/notifications/toast"
|
||||
import { archiveHomeSession } from "./archive"
|
||||
import type { HomeController } from "../model"
|
||||
import { buildHomeSessionRecords, homeProjectForSession, type HomeSessionRecord } from "./records"
|
||||
import { buildHomeSessionRecords, homeProjectForSession, homeSessionLocation, type HomeSessionRecord } from "./records"
|
||||
|
||||
export type { HomeSessionRecord } from "./records"
|
||||
|
||||
@@ -92,6 +92,25 @@ export function createHomeSessionsController(home: HomeController) {
|
||||
const groups = createMemo(() => groupSessions(records(), language))
|
||||
const prefetched = new Set<string>()
|
||||
|
||||
const location = (record: HomeSessionRecord) => {
|
||||
const branch = home.server.focusedContext()?.data.location.vcs.info(record.session.location)?.branch.current
|
||||
return homeSessionLocation(record.session.location.directory, branch)
|
||||
}
|
||||
|
||||
const syncLocations = (record?: HomeSessionRecord) => {
|
||||
if (platform.platform !== "desktop") return
|
||||
const ctx = home.server.focusedContext()
|
||||
if (!ctx) return
|
||||
if (record) {
|
||||
void ctx.data.location.vcs.sync(record.session.location).catch(() => undefined)
|
||||
return
|
||||
}
|
||||
const locations = new Map(
|
||||
records().map((record) => [pathKey(record.session.location.directory), record.session.location] as const),
|
||||
)
|
||||
void Promise.allSettled(Array.from(locations.values(), (location) => ctx.data.location.vcs.sync(location)))
|
||||
}
|
||||
|
||||
createEffect(() => {
|
||||
const ctx = home.server.focusedContext()
|
||||
const conn = home.server.focused()
|
||||
@@ -252,6 +271,13 @@ export function createHomeSessionsController(home: HomeController) {
|
||||
loading: () => sessionLoad.isPending,
|
||||
searchRecords: allRecords,
|
||||
},
|
||||
platform: {
|
||||
desktop: platform.platform === "desktop",
|
||||
},
|
||||
location: {
|
||||
value: location,
|
||||
sync: syncLocations,
|
||||
},
|
||||
session: {
|
||||
showProjectName: () => !home.project.selected(),
|
||||
server: () => home.selection.value().server,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import type { SessionInfo } from "@opencode/client/promise"
|
||||
import type { LocalProject } from "@/shell/state/layout"
|
||||
import { buildHomeSessionRecords } from "./records"
|
||||
import { buildHomeSessionRecords, homeSessionLocation } from "./records"
|
||||
|
||||
const session = (id: string, directory: string, projectID: string) =>
|
||||
({
|
||||
@@ -59,3 +59,19 @@ describe("buildHomeSessionRecords", () => {
|
||||
expect(records[0]?.project.worktree).toBe("/repo/a/packages/app")
|
||||
})
|
||||
})
|
||||
|
||||
describe("homeSessionLocation", () => {
|
||||
test("returns the worktree directory name and branch", () => {
|
||||
expect(homeSessionLocation("/repo/.worktrees/crisp-cactus", "feature/home")).toEqual({
|
||||
worktree: "crisp-cactus",
|
||||
branch: "feature/home",
|
||||
})
|
||||
})
|
||||
|
||||
test("uses the worktree name while branch metadata is unavailable", () => {
|
||||
expect(homeSessionLocation("/repo/.worktrees/crisp-cactus")).toEqual({
|
||||
worktree: "crisp-cactus",
|
||||
branch: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { SessionInfo } from "@opencode/client/promise"
|
||||
import type { LocalProject } from "@/shell/state/layout"
|
||||
import { compareSessionTime, displayName } from "@/shell/layout/helpers"
|
||||
import { pathKey } from "@/workspaces/path-key"
|
||||
import { getFilename } from "@opencode/util/path"
|
||||
|
||||
export type HomeSessionRecord = {
|
||||
session: SessionInfo
|
||||
@@ -9,6 +10,10 @@ export type HomeSessionRecord = {
|
||||
projectName: string
|
||||
}
|
||||
|
||||
export function homeSessionLocation(directory: string, branch?: string) {
|
||||
return { worktree: getFilename(directory) || directory, branch }
|
||||
}
|
||||
|
||||
export function buildHomeSessionRecords(input: {
|
||||
sessions: () => SessionInfo[]
|
||||
projectDirectories: () => string[] | undefined
|
||||
|
||||
@@ -16,6 +16,9 @@ export function HomeSessions(props: {
|
||||
language={props.sessions.copy.language}
|
||||
groups={props.sessions.data.groups()}
|
||||
loading={props.sessions.data.loading()}
|
||||
desktop={props.sessions.platform.desktop}
|
||||
location={props.sessions.location.value}
|
||||
onRevealLocations={props.sessions.location.sync}
|
||||
showProjectName={props.sessions.session.showProjectName()}
|
||||
server={server()}
|
||||
canCreateSession={props.sessions.session.canCreate()}
|
||||
|
||||
@@ -15,6 +15,7 @@ import { ServerConnection } from "@/runtime/server/registry"
|
||||
import { SessionTabAvatarView } from "@/shell/layout/session-tab-avatar"
|
||||
import { sessionLabel } from "@/session/title"
|
||||
import { shouldOpenSessionInBackground } from "./open"
|
||||
import { createAltHold } from "./alt-hold"
|
||||
import "./view.css"
|
||||
import {
|
||||
HomeSessionStatusController,
|
||||
@@ -46,6 +47,9 @@ export type HomeSessionsViewProps = {
|
||||
language: ReturnType<typeof useLanguage>
|
||||
groups: HomeSessionGroup[]
|
||||
loading: boolean
|
||||
desktop: boolean
|
||||
location: (record: HomeSessionRecord) => { worktree: string; branch: string | undefined }
|
||||
onRevealLocations: (record?: HomeSessionRecord) => void
|
||||
showProjectName: boolean
|
||||
server: ServerConnection.Key
|
||||
canCreateSession: boolean
|
||||
@@ -91,6 +95,8 @@ type HomeSessionRowUI = {
|
||||
|
||||
export function HomeSessionsView(props: HomeSessionsViewProps) {
|
||||
const [rowUI, setRowUI] = createStore<HomeSessionRowUI>({ menu: undefined, editor: undefined })
|
||||
const [hover, setHover] = createStore<{ sessionID: string | undefined }>({ sessionID: undefined })
|
||||
const showLocations = createAltHold(props.desktop, props.onRevealLocations)
|
||||
return (
|
||||
<section
|
||||
ref={props.onSetHoverTarget}
|
||||
@@ -101,7 +107,12 @@ export function HomeSessionsView(props: HomeSessionsViewProps) {
|
||||
class="sticky top-0 z-30 shrink-0 bg-v2-background-bg-base pb-1 pt-6 md:pb-3 lg:pt-12"
|
||||
onWheel={props.onWheel}
|
||||
>
|
||||
<HomeSessionSearch {...props} />
|
||||
<HomeSessionSearch
|
||||
{...props}
|
||||
showLocations={showLocations()}
|
||||
hoveredSession={hover.sessionID}
|
||||
onHoverSession={(sessionID) => setHover("sessionID", sessionID)}
|
||||
/>
|
||||
<Show when={props.groups.length > 0 && props.canCreateSession}>
|
||||
<div class="pointer-events-none absolute right-0 top-[68px] z-20 flex md:top-[84px] lg:top-[108px]">
|
||||
<Button
|
||||
@@ -162,7 +173,17 @@ export function HomeSessionsView(props: HomeSessionsViewProps) {
|
||||
rows would be disposed mid-interaction whenever a
|
||||
sync response lands. */}
|
||||
<Key each={group().sessions} by={(record) => record.session.id}>
|
||||
{(record) => <HomeSessionRow {...props} record={record()} rowUI={rowUI} setRowUI={setRowUI} />}
|
||||
{(record) => (
|
||||
<HomeSessionRow
|
||||
{...props}
|
||||
record={record()}
|
||||
rowUI={rowUI}
|
||||
setRowUI={setRowUI}
|
||||
showLocations={showLocations()}
|
||||
hoveredSession={hover.sessionID}
|
||||
onHoverSession={(sessionID) => setHover("sessionID", sessionID)}
|
||||
/>
|
||||
)}
|
||||
</Key>
|
||||
</div>
|
||||
</>
|
||||
@@ -198,12 +219,7 @@ function HomeSessionLeadingController(props: {
|
||||
)
|
||||
}
|
||||
|
||||
function HomeSessionLeading(props: {
|
||||
record: HomeSessionRecord
|
||||
open: boolean
|
||||
unread: boolean
|
||||
loading: boolean
|
||||
}) {
|
||||
function HomeSessionLeading(props: { record: HomeSessionRecord; open: boolean; unread: boolean; loading: boolean }) {
|
||||
return (
|
||||
<div class="relative shrink-0">
|
||||
<Show when={props.open}>
|
||||
@@ -226,7 +242,13 @@ function HomeSessionLeading(props: {
|
||||
)
|
||||
}
|
||||
|
||||
function HomeSessionSearch(props: HomeSessionsViewProps) {
|
||||
function HomeSessionSearch(
|
||||
props: HomeSessionsViewProps & {
|
||||
showLocations: boolean
|
||||
hoveredSession: string | undefined
|
||||
onHoverSession: (sessionID: string | undefined) => void
|
||||
},
|
||||
) {
|
||||
return (
|
||||
<div class="w-full">
|
||||
<div ref={props.onSetSearchRoot} data-component="home-session-search" class="relative z-30 w-full">
|
||||
@@ -369,9 +391,13 @@ function HomeSessionSearchResultRow(
|
||||
props: HomeSessionsViewProps & {
|
||||
record: HomeSessionRecord
|
||||
selected: boolean
|
||||
showLocations: boolean
|
||||
hoveredSession: string | undefined
|
||||
onHoverSession: (sessionID: string | undefined) => void
|
||||
},
|
||||
) {
|
||||
const title = createMemo(() => sessionLabel(props.record.session))
|
||||
const location = createMemo(() => props.location(props.record))
|
||||
const showProjectName = () => props.showProjectName && props.record.projectName
|
||||
const key = () => homeSessionSearchKey(props.record)
|
||||
|
||||
@@ -385,14 +411,21 @@ function HomeSessionSearchResultRow(
|
||||
role="option"
|
||||
aria-selected={props.selected}
|
||||
class={`
|
||||
flex h-10 w-full shrink-0 cursor-default items-center gap-2 border-0 py-3 pl-[18px] pr-6 text-left
|
||||
flex h-10 w-full shrink-0 cursor-default items-center border-0 py-3 pl-[18px] pr-6 text-left
|
||||
transition-[background-color] duration-[120ms] ease-in-out
|
||||
hover:bg-v2-overlay-simple-overlay-hover focus-visible:bg-v2-overlay-simple-overlay-hover focus-visible:outline-none
|
||||
`}
|
||||
classList={{
|
||||
"bg-v2-overlay-simple-overlay-hover": props.selected,
|
||||
"gap-1.5": props.desktop,
|
||||
"gap-2": !props.desktop,
|
||||
}}
|
||||
onMouseEnter={() => props.onSearchHighlight(props.record)}
|
||||
onMouseEnter={() => {
|
||||
props.onSearchHighlight(props.record)
|
||||
props.onHoverSession(props.record.session.id)
|
||||
props.onRevealLocations(props.record)
|
||||
}}
|
||||
onMouseLeave={() => props.onHoverSession(undefined)}
|
||||
onMouseDown={(event) => {
|
||||
if (event.button === 1) event.preventDefault()
|
||||
}}
|
||||
@@ -403,16 +436,22 @@ function HomeSessionSearchResultRow(
|
||||
props.onSearchSelect(props.record, { background: true })
|
||||
}}
|
||||
>
|
||||
<HomeSessionLeadingController
|
||||
server={props.server}
|
||||
isOpenTab={props.isOpenTab}
|
||||
record={props.record}
|
||||
/>
|
||||
<HomeSessionLeadingController server={props.server} isOpenTab={props.isOpenTab} record={props.record} />
|
||||
<div data-slot="home-session-labels" class="flex min-w-0 flex-1 items-center gap-1.5">
|
||||
<HomeSessionTitle title={title()} showProjectName={!!showProjectName()} search />
|
||||
<Show when={showProjectName()}>
|
||||
<HomeSessionProjectName name={props.record.projectName} search />
|
||||
<HomeSessionProjectName name={props.record.projectName} trailing={props.desktop} search />
|
||||
</Show>
|
||||
<HomeSessionLocation
|
||||
location={location()}
|
||||
show={props.showLocations || props.hoveredSession === props.record.session.id}
|
||||
instantHide={
|
||||
!props.showLocations &&
|
||||
props.hoveredSession !== undefined &&
|
||||
props.hoveredSession !== props.record.session.id
|
||||
}
|
||||
desktop={props.desktop}
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
@@ -445,9 +484,13 @@ function HomeSessionRow(
|
||||
record: HomeSessionRecord
|
||||
rowUI: HomeSessionRowUI
|
||||
setRowUI: SetStoreFunction<HomeSessionRowUI>
|
||||
showLocations: boolean
|
||||
hoveredSession: string | undefined
|
||||
onHoverSession: (sessionID: string | undefined) => void
|
||||
},
|
||||
) {
|
||||
const title = createMemo(() => sessionLabel(props.record.session))
|
||||
const location = createMemo(() => props.location(props.record))
|
||||
const showProjectName = () => props.showProjectName && props.record.projectName
|
||||
const sessionID = () => props.record.session.id
|
||||
const menu = () => (props.rowUI.menu?.id === sessionID() ? props.rowUI.menu : undefined)
|
||||
@@ -530,13 +573,10 @@ function HomeSessionRow(
|
||||
fallback={
|
||||
<div
|
||||
data-slot="home-session-editor"
|
||||
class="flex h-10 min-w-0 w-full flex-1 items-center gap-2 py-3 ps-1.5 pe-3 md:ps-3 md:pe-10"
|
||||
class="flex h-10 min-w-0 w-full flex-1 items-center py-3 ps-1.5 pe-3 md:ps-3 md:pe-10"
|
||||
classList={{ "gap-1.5": props.desktop, "gap-2": !props.desktop }}
|
||||
>
|
||||
<HomeSessionLeadingController
|
||||
server={props.server}
|
||||
isOpenTab={props.isOpenTab}
|
||||
record={props.record}
|
||||
/>
|
||||
<HomeSessionLeadingController server={props.server} isOpenTab={props.isOpenTab} record={props.record} />
|
||||
<div data-slot="home-session-labels" class="contents">
|
||||
<InlineInput
|
||||
data-component="home-session-rename"
|
||||
@@ -547,7 +587,7 @@ function HomeSessionRow(
|
||||
class={`
|
||||
block min-w-0 overflow-hidden text-ellipsis whitespace-nowrap text-v2-text-text-base
|
||||
[font-weight:530] field-sizing-content outline-none focus:outline-none focus-visible:outline-none
|
||||
${showProjectName() ? "max-w-[min(70%,480px)] flex-[0_1_auto]" : "flex-[1_1_auto]"}
|
||||
${showProjectName() ? "max-w-[min(70%,480px)] flex-[0_1_auto]" : "flex-[1_1_auto]"}
|
||||
`}
|
||||
style={{ "--inline-input-shadow": "none", "text-align": "start" }}
|
||||
onInput={(event) => {
|
||||
@@ -586,14 +626,20 @@ function HomeSessionRow(
|
||||
aria-haspopup="menu"
|
||||
aria-expanded={!!menu()}
|
||||
class={`
|
||||
flex h-10 min-w-0 w-full flex-1 shrink-0 cursor-default items-center gap-2 rounded-[6px] border-0
|
||||
flex h-10 min-w-0 w-full flex-1 shrink-0 cursor-default items-center rounded-[6px] border-0
|
||||
bg-transparent py-3 ps-1.5 pe-3 md:ps-3 md:pe-10 text-start text-v2-text-text-muted [font-weight:530]
|
||||
transition-[background-color,color,box-shadow] duration-[120ms] ease-in-out
|
||||
hover:bg-v2-overlay-simple-overlay-hover focus-visible:bg-v2-overlay-simple-overlay-hover focus-visible:outline-none
|
||||
`}
|
||||
classList={{ "gap-1.5": props.desktop, "gap-2": !props.desktop }}
|
||||
onMouseDown={(event) => {
|
||||
if (event.button === 1) event.preventDefault()
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
props.onHoverSession(props.record.session.id)
|
||||
props.onRevealLocations(props.record)
|
||||
}}
|
||||
onMouseLeave={() => props.onHoverSession(undefined)}
|
||||
onPointerDown={(event) => {
|
||||
suppressClick = false
|
||||
if (event.pointerType !== "touch") return
|
||||
@@ -644,16 +690,26 @@ function HomeSessionRow(
|
||||
props.onOpenSession(props.record.session, { background: true })
|
||||
}}
|
||||
>
|
||||
<HomeSessionLeadingController
|
||||
server={props.server}
|
||||
isOpenTab={props.isOpenTab}
|
||||
record={props.record}
|
||||
/>
|
||||
<div data-slot="home-session-labels" class="contents">
|
||||
<HomeSessionLeadingController server={props.server} isOpenTab={props.isOpenTab} record={props.record} />
|
||||
<div
|
||||
data-slot="home-session-labels"
|
||||
class="min-w-0 flex-1 items-center gap-1.5"
|
||||
classList={{ flex: props.desktop, contents: !props.desktop }}
|
||||
>
|
||||
<HomeSessionTitle title={title()} showProjectName={!!showProjectName()} />
|
||||
<Show when={showProjectName()}>
|
||||
<HomeSessionProjectName name={props.record.projectName} />
|
||||
<HomeSessionProjectName name={props.record.projectName} trailing={props.desktop} />
|
||||
</Show>
|
||||
<HomeSessionLocation
|
||||
location={location()}
|
||||
show={props.showLocations || props.hoveredSession === props.record.session.id}
|
||||
instantHide={
|
||||
!props.showLocations &&
|
||||
props.hoveredSession !== undefined &&
|
||||
props.hoveredSession !== props.record.session.id
|
||||
}
|
||||
desktop={props.desktop}
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
</Show>
|
||||
@@ -746,13 +802,50 @@ function HomeSessionTitle(props: { title: string; showProjectName: boolean; sear
|
||||
)
|
||||
}
|
||||
|
||||
function HomeSessionProjectName(props: { name: string; search?: boolean }) {
|
||||
function HomeSessionLocation(props: {
|
||||
location: { worktree: string; branch: string | undefined }
|
||||
show: boolean
|
||||
instantHide: boolean
|
||||
desktop: boolean
|
||||
}) {
|
||||
if (!props.desktop) return null
|
||||
return (
|
||||
<span
|
||||
dir="ltr"
|
||||
aria-hidden={!props.show || undefined}
|
||||
class="flex min-w-0 shrink-0 items-center gap-1.5 overflow-hidden whitespace-nowrap ease-out motion-reduce:transition-none"
|
||||
classList={{
|
||||
"-ms-1.5 max-w-0 opacity-0": !props.show,
|
||||
"max-w-[60%] opacity-100": props.show,
|
||||
"transition-[max-width,opacity] duration-[120ms]": !props.instantHide,
|
||||
"transition-none": props.instantHide,
|
||||
}}
|
||||
>
|
||||
<Icon name="outline-worktree" class="shrink-0 text-v2-icon-icon-muted" />
|
||||
<span class="min-w-0 overflow-hidden text-ellipsis [font-weight:440]">{props.location.worktree}</span>
|
||||
<Show when={props.location.branch}>
|
||||
{(branch) => (
|
||||
<>
|
||||
<Icon name="branch" class="shrink-0 text-v2-icon-icon-muted" />
|
||||
<span class="min-w-0 overflow-hidden text-ellipsis [font-weight:440]">{branch()}</span>
|
||||
</>
|
||||
)}
|
||||
</Show>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
function HomeSessionProjectName(props: { name: string; search?: boolean; trailing?: boolean }) {
|
||||
return (
|
||||
<span
|
||||
data-component="home-session-project-name"
|
||||
dir="auto"
|
||||
class="min-w-0 flex-[1_1_auto] overflow-hidden text-ellipsis whitespace-nowrap text-v2-text-text-muted [font-weight:440]"
|
||||
classList={{ "text-[13px] leading-4 tracking-[-0.04px]": !!props.search }}
|
||||
class="min-w-0 overflow-hidden text-ellipsis whitespace-nowrap text-v2-text-text-muted [font-weight:440]"
|
||||
classList={{
|
||||
"flex-[0_1_auto]": !!props.trailing,
|
||||
"flex-[1_1_auto]": !props.trailing,
|
||||
"text-[13px] leading-4 tracking-[-0.04px]": !!props.search,
|
||||
}}
|
||||
>
|
||||
{props.name}
|
||||
</span>
|
||||
|
||||
@@ -38,57 +38,6 @@
|
||||
}
|
||||
|
||||
@layer components {
|
||||
[data-slot="session-chat-panel"] {
|
||||
container-name: session-chat;
|
||||
}
|
||||
|
||||
[data-component="new-session"] {
|
||||
container-type: inline-size;
|
||||
container-name: new-session;
|
||||
}
|
||||
|
||||
[data-slot="session-chat-panel"]
|
||||
:is([data-timeline-virtual-content], [data-component="session-composer-dock"] > div),
|
||||
[data-slot="new-session-content"] {
|
||||
translate: var(--session-summary-resize-translate, var(--session-summary-translate, none));
|
||||
transition: translate 240ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="session-chat-panel"][data-summary-resizing="true"]
|
||||
:is([data-timeline-virtual-content], [data-component="session-composer-dock"] > div),
|
||||
[data-component="new-session"][data-summary-resizing="true"] [data-slot="new-session-content"] {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
/* Keep the 1000px conversation intact, with 320px for the summary and its gutters.
|
||||
When they overlap, center the conversation in the space that remains beside the summary. */
|
||||
@container session-chat (min-width: 1320px) and (width < 1640px) {
|
||||
[data-slot="session-chat-panel"][data-summary-open="true"]
|
||||
:is([data-timeline-virtual-content], [data-component="session-composer-dock"] > div) {
|
||||
--session-summary-translate: -160px;
|
||||
|
||||
&:dir(rtl) {
|
||||
--session-summary-translate: 160px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Shift only while centered content overlaps the 280px summary cards and their 16px edge inset:
|
||||
880px + 2 * (280px + 16px) = 1472px. Center it in the remaining space, reserving 320px. */
|
||||
@container new-session (min-width: 1200px) and (width < 1472px) {
|
||||
[data-component="new-session"][data-summary-open="true"] [data-slot="new-session-content"] {
|
||||
--session-summary-translate: -160px;
|
||||
|
||||
&:dir(rtl) {
|
||||
--session-summary-translate: 160px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="session-chat-panel"][data-scrollbar-hidden="true"]
|
||||
[data-slot="session-timeline-scroll"]
|
||||
> .scroll-view__thumb {
|
||||
|
||||
@@ -88,7 +88,7 @@ export default function NewSessionPage(props: { draftId: string }) {
|
||||
<div class="relative size-full overflow-hidden flex flex-col">
|
||||
{suspendUntilPromptReady()}
|
||||
<div class="flex-1 min-h-0 flex flex-col gap-2 px-2 pb-[var(--shell-bottom-inset,8px)] pt-[var(--shell-top-inset,8px)]">
|
||||
<NewSessionView composer={model} project={project} workspace={workspace} mcp={mcp} />
|
||||
<NewSessionView composer={model} project={project} workspace={workspace} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
import { Icon } from "@opencode/ui/icon"
|
||||
import { Show } from "solid-js"
|
||||
import { useLanguage } from "@/runtime/i18n/language"
|
||||
import { ProjectSummaryCard } from "@/session/summary/project-card"
|
||||
import { SessionServerPanel } from "@/session/summary/server-panel"
|
||||
import type { PromptProject } from "./project/selector"
|
||||
import type { DraftMcpControls } from "./mcp"
|
||||
import type { NewSessionWorkspaceController } from "./workspace/controller"
|
||||
import { PromptWorkspaceSelector } from "./workspace/selector"
|
||||
|
||||
export function NewSessionSummary(props: {
|
||||
project?: PromptProject
|
||||
workspace: NewSessionWorkspaceController
|
||||
mcp: DraftMcpControls
|
||||
shown: boolean
|
||||
onChooseProject: () => void
|
||||
}) {
|
||||
const language = useLanguage()
|
||||
return (
|
||||
<div data-component="session-summary-panel">
|
||||
<Show
|
||||
when={props.project}
|
||||
fallback={
|
||||
<div class="session-summary-card">
|
||||
<button type="button" class="session-summary-row" onClick={props.onChooseProject}>
|
||||
<Icon name="folder" class="text-v2-icon-icon-muted" />
|
||||
<span class="session-summary-label">{language.t("session.summary.chooseProject")}</span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{(project) => (
|
||||
<>
|
||||
<ProjectSummaryCard project={project()}>
|
||||
<Show
|
||||
when={props.workspace.bar.visible()}
|
||||
fallback={
|
||||
<div class="session-summary-row">
|
||||
<Icon name="monitor" class="shrink-0 text-v2-icon-icon-muted" />
|
||||
<span class="session-summary-label">{language.t("session.new.git.none")}</span>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<PromptWorkspaceSelector
|
||||
variant="summary"
|
||||
value={props.workspace.selection.value()}
|
||||
projectRoot={props.workspace.project.root()}
|
||||
workspaces={props.workspace.project.workspaces()}
|
||||
branches={props.workspace.project.branches()}
|
||||
branch={props.workspace.bar.branch()}
|
||||
onChange={props.workspace.selection.set}
|
||||
onCreate={props.workspace.selection.create}
|
||||
onSearch={props.workspace.project.searchBranches}
|
||||
onViewAll={props.workspace.project.openAll}
|
||||
/>
|
||||
</Show>
|
||||
</ProjectSummaryCard>
|
||||
<SessionServerPanel directory={props.mcp.directory()} shown={props.shown} mcp={props.mcp.controls} />
|
||||
</>
|
||||
)}
|
||||
</Show>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
import { useDialog } from "@opencode/ui/context/dialog"
|
||||
import { Tooltip } from "@opencode/ui/tooltip"
|
||||
import { Icon } from "@opencode/ui/icon"
|
||||
import { Show, Suspense, createMemo, createSignal, lazy, onMount } from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { makeEventListener } from "@solid-primitives/event-listener"
|
||||
import { debounce } from "@solid-primitives/scheduled"
|
||||
import { Show, createMemo, createSignal } from "solid-js"
|
||||
import { Schema } from "effect"
|
||||
import createPresence from "solid-presence"
|
||||
import { Composer } from "@/composer/composer"
|
||||
@@ -24,13 +21,6 @@ import { Persist, persisted } from "@/runtime/persistence/storage"
|
||||
import { Persistence } from "@/runtime/persistence/schema"
|
||||
import type { NewSessionWorkspaceController } from "./workspace/controller"
|
||||
import { NewSessionWordmark } from "./wordmark"
|
||||
import { SummaryPopover } from "@/session/summary/popover"
|
||||
import type { DraftMcpControls } from "./mcp"
|
||||
|
||||
const NewSessionSummary = lazy(async () => {
|
||||
const { NewSessionSummary } = await import("./summary")
|
||||
return { default: NewSessionSummary }
|
||||
})
|
||||
|
||||
const providerTipDismissalDuration = 30 * 24 * 60 * 60 * 1000
|
||||
|
||||
@@ -48,23 +38,7 @@ export function NewSessionView(props: {
|
||||
composer: ComposerModel
|
||||
project: PromptProjectController
|
||||
workspace: NewSessionWorkspaceController
|
||||
mcp: DraftMcpControls
|
||||
}) {
|
||||
const [store, setStore] = createStore({
|
||||
summary: false,
|
||||
content: undefined as HTMLDivElement | undefined,
|
||||
summaryResizeTranslate: undefined as string | undefined,
|
||||
})
|
||||
const finishWindowResize = debounce(() => setStore("summaryResizeTranslate", undefined), 150)
|
||||
onMount(() => {
|
||||
makeEventListener(window, "resize", () => {
|
||||
if (store.summaryResizeTranslate === undefined) {
|
||||
// Freeze the painted offset, including an in-flight slide, until resizing settles.
|
||||
setStore("summaryResizeTranslate", store.content ? getComputedStyle(store.content).translate : "none")
|
||||
}
|
||||
finishWindowResize()
|
||||
})
|
||||
})
|
||||
const [onboarding, setOnboarding, , onboardingReady] = persisted(
|
||||
Persist.global("workspace-onboarding"),
|
||||
WorkspaceOnboardingSchema,
|
||||
@@ -79,40 +53,14 @@ export function NewSessionView(props: {
|
||||
<div class="@container relative flex flex-col min-h-0 h-full flex-1">
|
||||
<div
|
||||
data-component="new-session"
|
||||
data-summary-open={store.summary}
|
||||
data-summary-resizing={store.summaryResizeTranslate !== undefined}
|
||||
style={{ "--session-summary-resize-translate": store.summaryResizeTranslate }}
|
||||
class="relative flex-1 min-h-0 overflow-hidden rounded-[10px] bg-v2-background-bg-base shadow-[var(--v2-elevation-raised)]"
|
||||
>
|
||||
<ComposerDropzone
|
||||
active={props.composer.state.drag === "active"}
|
||||
input={props.composer.model.selection.current()?.capabilities.input}
|
||||
/>
|
||||
<div
|
||||
data-slot="new-session-summary"
|
||||
class="absolute inset-x-0 top-0 z-20 flex h-12 items-center justify-end px-3"
|
||||
>
|
||||
<SummaryPopover open={store.summary} onOpenChange={(open) => setStore("summary", open)}>
|
||||
<Suspense>
|
||||
<NewSessionSummary
|
||||
project={props.project.selected()}
|
||||
workspace={props.workspace}
|
||||
mcp={props.mcp}
|
||||
shown={store.summary}
|
||||
onChooseProject={() => {
|
||||
setStore("summary", false)
|
||||
props.project.add()
|
||||
}}
|
||||
/>
|
||||
</Suspense>
|
||||
</SummaryPopover>
|
||||
</div>
|
||||
<div class="absolute inset-x-0 top-[25.375%] flex justify-center px-6">
|
||||
<div
|
||||
ref={(element) => setStore("content", element)}
|
||||
data-slot="new-session-content"
|
||||
class={NEW_SESSION_CONTENT_WIDTH}
|
||||
>
|
||||
<div class={NEW_SESSION_CONTENT_WIDTH}>
|
||||
<NewSessionWordmark />
|
||||
<div class="mt-8 flex flex-col gap-8">
|
||||
<Composer model={props.composer} />
|
||||
@@ -152,6 +100,8 @@ export function NewSessionView(props: {
|
||||
</div>
|
||||
</div>
|
||||
<NewSessionTips
|
||||
selection={props.composer.model.selection}
|
||||
onDone={props.composer.restoreFocus}
|
||||
workspaceEligible={
|
||||
!!props.project.selected() &&
|
||||
props.workspace.bar.visible() &&
|
||||
@@ -165,7 +115,12 @@ export function NewSessionView(props: {
|
||||
)
|
||||
}
|
||||
|
||||
function NewSessionTips(props: { workspaceEligible: boolean; onWorkspace: () => void }) {
|
||||
function NewSessionTips(props: {
|
||||
selection: ComposerModel["model"]["selection"]
|
||||
onDone: () => void
|
||||
workspaceEligible: boolean
|
||||
onWorkspace: () => void
|
||||
}) {
|
||||
const language = useLanguage()
|
||||
const dialog = useDialog()
|
||||
const sdk = useWorkspaceLocation()
|
||||
@@ -188,9 +143,8 @@ function NewSessionTips(props: { workspaceEligible: boolean; onWorkspace: () =>
|
||||
)
|
||||
const providerVisible = createMemo(
|
||||
() =>
|
||||
providers.ready() &&
|
||||
providerReady() &&
|
||||
providers.paid().length === 0 &&
|
||||
providers.anyConnection() === false &&
|
||||
Date.now() - providerState.dismissedAt >= providerTipDismissalDuration,
|
||||
)
|
||||
const tip = createMemo<"workspace" | "provider" | undefined>(() => {
|
||||
@@ -212,7 +166,9 @@ function NewSessionTips(props: { workspaceEligible: boolean; onWorkspace: () =>
|
||||
return
|
||||
}
|
||||
void import("@/providers/connect/dialog").then(({ DialogConnectProvider }) => {
|
||||
void dialog.show(() => <DialogConnectProvider directory={sdk().directory} />)
|
||||
void dialog.show(() => (
|
||||
<DialogConnectProvider directory={sdk().directory} selection={props.selection} onDone={props.onDone} />
|
||||
))
|
||||
})
|
||||
}
|
||||
const dismiss = () => {
|
||||
|
||||
@@ -194,9 +194,7 @@ export function PromptWorkspaceSelector(props: {
|
||||
}}
|
||||
>
|
||||
<Icon name="outline-worktree" />
|
||||
<span class="min-w-0 flex-1 truncate">
|
||||
{language.t("session.new.workspace.existing").replace(/(…|\.{3})$/, "")}
|
||||
</span>
|
||||
<span class="min-w-0 flex-1 truncate">{language.t("session.new.workspace.existingLabel")}</span>
|
||||
</Menu.SubTrigger>
|
||||
<Menu.Portal>
|
||||
<Menu.SubContent class="max-h-[66.667dvh] w-[200px] overflow-y-auto !pb-0 [&>[data-component=menu-v2-item]:last-child]:mb-0.5 [@media(max-height:600px)]:max-h-[calc(100dvh-48px)]">
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { expect, test } from "bun:test"
|
||||
import { consoleProviderGroup, consoleProviderName } from "./console"
|
||||
|
||||
test("groups only providers managed by the active Console workspace", () => {
|
||||
const direct = { id: "openai", integrationID: "openai", name: "Anomaly / OpenAI" }
|
||||
const group = consoleProviderGroup([
|
||||
{ id: "opencode", integrationID: "opencode", name: "Anomaly / OpenCode" },
|
||||
{ id: "console-openai", integrationID: "opencode", name: "Anomaly / OpenAI" },
|
||||
{ id: "console-google", integrationID: "opencode", name: "Anomaly / Google" },
|
||||
direct,
|
||||
])
|
||||
|
||||
expect(group).toBeDefined()
|
||||
if (!group) throw new Error("Expected Console provider group")
|
||||
expect(group.workspace).toBe("Anomaly")
|
||||
expect(group.providers.map((provider) => provider.id)).toEqual(["opencode", "console-openai", "console-google"])
|
||||
expect(consoleProviderName(group, group.providers[1].name)).toBe("OpenAI")
|
||||
expect(group.providers).not.toContain(direct)
|
||||
})
|
||||
@@ -0,0 +1,26 @@
|
||||
type Provider = {
|
||||
id: string
|
||||
integrationID?: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export function consoleProviderGroup<T extends Provider>(providers: readonly T[]) {
|
||||
const root = providers.find((provider) => provider.id === "opencode" && provider.integrationID === "opencode")
|
||||
const suffix = " / OpenCode"
|
||||
if (!root?.name.endsWith(suffix)) return
|
||||
const workspace = root.name.slice(0, -suffix.length).trim()
|
||||
if (!workspace) return
|
||||
const prefix = `${workspace} / `
|
||||
return {
|
||||
root,
|
||||
workspace,
|
||||
prefix,
|
||||
providers: providers.filter(
|
||||
(provider) => provider.integrationID === "opencode" && provider.name.startsWith(prefix),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
export function consoleProviderName(group: { prefix: string }, name: string) {
|
||||
return name.startsWith(group.prefix) ? name.slice(group.prefix.length) : name
|
||||
}
|
||||
@@ -16,7 +16,13 @@ export function useIntegrations(directory: Accessor<string | undefined>) {
|
||||
})().catch(() => undefined)
|
||||
})
|
||||
|
||||
const location = () => {
|
||||
const value = directory()
|
||||
return value ? { directory: value } : undefined
|
||||
}
|
||||
|
||||
return {
|
||||
list: () => data.location.integration.list(directory() ? { directory: directory()! } : undefined) ?? [],
|
||||
ready: () => data.location.integration.list(location()) !== undefined,
|
||||
list: () => data.location.integration.list(location()) ?? [],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,11 +38,13 @@ export function useProviders(directory: Accessor<string | undefined>) {
|
||||
return normalizeProviderList(provider, model)
|
||||
})
|
||||
|
||||
const ready = () => {
|
||||
const ref = location()
|
||||
return data.location.provider.list(ref) !== undefined && data.location.model.list(ref) !== undefined
|
||||
}
|
||||
|
||||
return {
|
||||
ready: () => {
|
||||
const ref = location()
|
||||
return data.location.provider.list(ref) !== undefined && data.location.model.list(ref) !== undefined
|
||||
},
|
||||
ready,
|
||||
all: () => providers().all,
|
||||
default: () => providers().default,
|
||||
// V2 servers list only available providers, so the connectable catalog
|
||||
@@ -70,6 +72,15 @@ export function useProviders(directory: Accessor<string | undefined>) {
|
||||
(v) => Array.from(v),
|
||||
)
|
||||
},
|
||||
// Any stored or detected connection, or a provider with models beyond the keyless OpenCode catalog.
|
||||
// Undefined until both catalogs load, so callers never mistake loading for a first run.
|
||||
anyConnection: () => {
|
||||
if (!integrations.ready() || !ready()) return undefined
|
||||
if (integrations.list().some((integration) => integration.connections.length > 0)) return true
|
||||
return providers().connected.some(
|
||||
(id) => id !== "opencode" && Object.keys(providers().all.get(id)?.models ?? {}).length > 0,
|
||||
)
|
||||
},
|
||||
paid: () => {
|
||||
const connected = new Set(providers().connected)
|
||||
const paid = [
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import { For, Show } from "solid-js"
|
||||
import { Button } from "@opencode/ui/button"
|
||||
import { TextShimmer } from "@opencode/ui/text-shimmer"
|
||||
import { useLanguage } from "@/runtime/i18n/language"
|
||||
|
||||
export function ConsoleAuthorization(props: {
|
||||
/** Undefined until the server returns the sign-in attempt. */
|
||||
code: string | undefined
|
||||
browserFailed: boolean
|
||||
copied: boolean
|
||||
copyFailed: boolean
|
||||
onOpen: () => void
|
||||
onCopy: () => void
|
||||
}) {
|
||||
const language = useLanguage()
|
||||
return (
|
||||
<div
|
||||
data-component="console-authorization"
|
||||
class="flex flex-col gap-5 text-[13px] leading-5 text-v2-text-text-muted"
|
||||
>
|
||||
<p>
|
||||
{language.t(
|
||||
props.browserFailed ? "provider.connect.console.browserFailed" : "provider.connect.console.instructions",
|
||||
)}
|
||||
</p>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="font-medium text-v2-text-text-base">{language.t("provider.connect.console.deviceCode")}</div>
|
||||
<Show
|
||||
when={props.code}
|
||||
fallback={
|
||||
<p role="status" class="flex h-12 items-center">
|
||||
<TextShimmer text={language.t("provider.connect.console.openingBrowser")} active />
|
||||
</p>
|
||||
}
|
||||
>
|
||||
{(code) => (
|
||||
<>
|
||||
<div
|
||||
dir="ltr"
|
||||
role="group"
|
||||
aria-label={language.t("provider.connect.console.deviceCode.label", { code: code() })}
|
||||
class="flex max-w-full gap-1 self-start font-mono text-xl font-[530] text-v2-text-text-base tabular-nums"
|
||||
>
|
||||
<For each={code().split("")}>
|
||||
{(character) => (
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class={
|
||||
character === "-"
|
||||
? "mx-1 flex h-12 items-center text-v2-text-text-muted"
|
||||
: "flex h-12 w-8 items-center justify-center rounded-md border border-v2-border-border-base bg-v2-background-bg-layer-02"
|
||||
}
|
||||
>
|
||||
{character}
|
||||
</span>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
<p role="status">
|
||||
<TextShimmer text={language.t("provider.connect.console.waiting")} active />
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</Show>
|
||||
</div>
|
||||
<div data-component="console-browser-fallback" class="flex min-h-7 flex-wrap items-center gap-x-3 gap-y-1">
|
||||
<span class="text-v2-text-text-faint">{language.t("provider.connect.console.browserHint")}</span>
|
||||
<Button variant="ghost-muted" disabled={!props.code} onClick={props.onCopy}>
|
||||
{language.t(props.copied ? "provider.connect.console.linkCopied" : "provider.connect.console.copyLink")}
|
||||
</Button>
|
||||
<Show when={props.browserFailed || props.copyFailed}>
|
||||
<Button variant="ghost" onClick={props.onOpen}>
|
||||
{language.t("provider.connect.console.openAgain")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
<Show when={props.copyFailed}>
|
||||
<p role="alert">{language.t("provider.connect.console.copyFailed")}</p>
|
||||
</Show>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -23,12 +23,20 @@ export function consoleIntegration(provider: string) {
|
||||
return CONSOLE_PROVIDERS.has(provider) ? CONSOLE_INTEGRATION : provider
|
||||
}
|
||||
|
||||
function hiddenDefaults(method: ProviderConnectMethod | undefined) {
|
||||
return Object.fromEntries(
|
||||
(method?.form ?? []).flatMap((field) =>
|
||||
field.type !== "external" && field.hidden && field.default !== undefined ? [[field.key, field.default]] : [],
|
||||
),
|
||||
) as FormAnswer
|
||||
export function providerFormDefaults(fields: ProviderConnectMethod["form"]) {
|
||||
return (fields ?? []).reduce<FormAnswer>((answer, field) => {
|
||||
if (field.type === "external" || !field.hidden || field.default === undefined) return answer
|
||||
const active = (field.when ?? []).every((condition) => {
|
||||
const actual = answer[condition.key]
|
||||
if (actual === undefined) return false
|
||||
const equal = Array.isArray(actual)
|
||||
? typeof condition.value === "string" && actual.includes(condition.value)
|
||||
: actual === condition.value
|
||||
return condition.op === "eq" ? equal : !equal
|
||||
})
|
||||
if (!active) return answer
|
||||
return { ...answer, [field.key]: field.default }
|
||||
}, {})
|
||||
}
|
||||
|
||||
export function createProviderConnectionController(options: {
|
||||
@@ -39,6 +47,8 @@ export function createProviderConnectionController(options: {
|
||||
onComplete: () => void
|
||||
/** Picks the method to start without asking when the integration exposes several. */
|
||||
autoSelect?: (methods: ProviderConnectMethod[]) => number | undefined
|
||||
/** Runs after the catalogs refresh; returning false keeps the dialog on a retryable error. */
|
||||
prepare?: (active: () => boolean) => Promise<boolean>
|
||||
pollInterval?: number
|
||||
}) {
|
||||
const language = useLanguage()
|
||||
@@ -49,6 +59,7 @@ export function createProviderConnectionController(options: {
|
||||
const directory = options.directory()
|
||||
return directory ? { directory } : undefined
|
||||
}
|
||||
const isConsole = () => options.provider() === CONSOLE_INTEGRATION
|
||||
// Not createResource: the dialog is owned by whichever page opened it, so reading a pending
|
||||
// resource here would suspend that page's <Suspense> and blank the screen behind the dialog.
|
||||
const [integration, setIntegration] = createStore({
|
||||
@@ -85,9 +96,14 @@ export function createProviderConnectionController(options: {
|
||||
formAnswer: undefined as FormAnswer | undefined,
|
||||
// Nothing is in flight until a method is selected; `busy()` reads this, so a truthy initial
|
||||
// value would keep multi-method providers on the spinner instead of the method list.
|
||||
state: undefined as "pending" | "complete" | "error" | "form" | undefined,
|
||||
state: undefined as "pending" | "waiting" | "refreshing" | "ready" | "error" | "form" | undefined,
|
||||
error: undefined as string | undefined,
|
||||
auto: false,
|
||||
// The credential is stored; a retry only needs to reload the catalogs.
|
||||
connected: false,
|
||||
browserFailed: false,
|
||||
// The attempt is still open on the server; a retry resumes polling it.
|
||||
statusFailed: false,
|
||||
})
|
||||
const polling = {
|
||||
generation: 0,
|
||||
@@ -112,26 +128,21 @@ export function createProviderConnectionController(options: {
|
||||
| { type: "auth.form" }
|
||||
| { type: "auth.answer"; answer: FormAnswer | undefined }
|
||||
| { type: "auth.pending" }
|
||||
| { type: "auth.complete"; authorization: Authorization }
|
||||
| { type: "auth.waiting"; authorization: Authorization }
|
||||
| { type: "auth.error"; error: string }
|
||||
|
||||
const dispatch = (action: Action) => {
|
||||
setStore(
|
||||
produce((draft) => {
|
||||
if (action.type === "method.select") {
|
||||
draft.methodIndex = action.index
|
||||
draft.authorization = undefined
|
||||
draft.formAnswer = undefined
|
||||
draft.state = undefined
|
||||
draft.error = undefined
|
||||
return
|
||||
}
|
||||
if (action.type === "method.reset") {
|
||||
draft.methodIndex = undefined
|
||||
if (action.type === "method.select" || action.type === "method.reset") {
|
||||
draft.methodIndex = action.type === "method.select" ? action.index : undefined
|
||||
draft.authorization = undefined
|
||||
draft.formAnswer = undefined
|
||||
draft.state = undefined
|
||||
draft.error = undefined
|
||||
draft.connected = false
|
||||
draft.browserFailed = false
|
||||
draft.statusFailed = false
|
||||
return
|
||||
}
|
||||
if (action.type === "auth.form") {
|
||||
@@ -150,8 +161,8 @@ export function createProviderConnectionController(options: {
|
||||
draft.error = undefined
|
||||
return
|
||||
}
|
||||
if (action.type === "auth.complete") {
|
||||
draft.state = "complete"
|
||||
if (action.type === "auth.waiting") {
|
||||
draft.state = "waiting"
|
||||
draft.authorization = action.authorization
|
||||
draft.error = undefined
|
||||
return
|
||||
@@ -162,6 +173,7 @@ export function createProviderConnectionController(options: {
|
||||
)
|
||||
}
|
||||
|
||||
const errorMessage = (error: unknown) => (error instanceof Error ? error.message : String(error))
|
||||
const cancelAttempt = () => {
|
||||
const attempt = polling.attempt
|
||||
polling.attempt = undefined
|
||||
@@ -179,16 +191,28 @@ export function createProviderConnectionController(options: {
|
||||
const finish = async () => {
|
||||
cancelPolling()
|
||||
polling.attempt = undefined
|
||||
const generation = polling.generation
|
||||
const active = () => !polling.disposed && generation === polling.generation
|
||||
setStore({ connected: true, state: "refreshing", error: undefined })
|
||||
const ref = location()
|
||||
data.location.integration.invalidate(ref)
|
||||
data.location.provider.invalidate(ref)
|
||||
data.location.model.invalidate(ref)
|
||||
await Promise.all([
|
||||
const refreshed = await Promise.all([
|
||||
data.location.integration.sync(ref),
|
||||
data.location.provider.sync(ref),
|
||||
data.location.model.sync(ref),
|
||||
]).catch(() => undefined)
|
||||
if (polling.disposed) return
|
||||
])
|
||||
.then(() => true)
|
||||
.catch(() => false)
|
||||
if (!active()) return
|
||||
const prepared = refreshed && options.prepare ? await options.prepare(active) : refreshed
|
||||
if (!active()) return
|
||||
if (!prepared && options.prepare) {
|
||||
dispatch({ type: "auth.error", error: language.t("provider.connect.console.refreshFailed") })
|
||||
return
|
||||
}
|
||||
setStore("state", "ready")
|
||||
options.onComplete()
|
||||
}
|
||||
const poll = async (authorization: Authorization, generation: number) => {
|
||||
@@ -202,10 +226,10 @@ export function createProviderConnectionController(options: {
|
||||
.catch((error) => ({ ok: false as const, error }))
|
||||
if (polling.disposed || generation !== polling.generation) return
|
||||
if (!result.ok) {
|
||||
polling.attempt = undefined
|
||||
setStore("statusFailed", true)
|
||||
dispatch({
|
||||
type: "auth.error",
|
||||
error: result.error instanceof Error ? result.error.message : String(result.error),
|
||||
error: isConsole() ? language.t("provider.connect.console.statusFailed") : errorMessage(result.error),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -215,19 +239,41 @@ export function createProviderConnectionController(options: {
|
||||
}
|
||||
if (result.status.status === "failed") {
|
||||
polling.attempt = undefined
|
||||
dispatch({ type: "auth.error", error: result.status.message })
|
||||
const message = result.status.message
|
||||
dispatch({
|
||||
type: "auth.error",
|
||||
error:
|
||||
isConsole() && message.includes("expired_token")
|
||||
? language.t("provider.connect.console.expired")
|
||||
: isConsole() && message.includes("access_denied")
|
||||
? language.t("provider.connect.console.denied")
|
||||
: message,
|
||||
})
|
||||
return
|
||||
}
|
||||
if (result.status.status === "expired") {
|
||||
polling.attempt = undefined
|
||||
dispatch({ type: "auth.error", error: language.t("provider.connect.oauth.expired") })
|
||||
dispatch({
|
||||
type: "auth.error",
|
||||
error: language.t(isConsole() ? "provider.connect.console.expired" : "provider.connect.oauth.expired"),
|
||||
})
|
||||
return
|
||||
}
|
||||
polling.timer = setTimeout(() => void poll(authorization, generation), options.pollInterval ?? 1_000)
|
||||
}
|
||||
const open = () => {
|
||||
const open = async () => {
|
||||
const url = store.authorization?.url
|
||||
if (url) platform.openExternal(url)
|
||||
if (!url) return
|
||||
const generation = polling.generation
|
||||
const opened = await Promise.resolve()
|
||||
.then(() => {
|
||||
if (platform.openBrowser) return platform.openBrowser(url)
|
||||
platform.openExternal(url)
|
||||
return true
|
||||
})
|
||||
.catch(() => false)
|
||||
if (polling.disposed || generation !== polling.generation) return
|
||||
setStore("browserFailed", !opened)
|
||||
}
|
||||
const select = async (index: number, answer?: FormAnswer) => {
|
||||
cancelPolling()
|
||||
@@ -240,14 +286,14 @@ export function createProviderConnectionController(options: {
|
||||
dispatch({ type: "auth.form" })
|
||||
return
|
||||
}
|
||||
const merged = { ...hiddenDefaults(selected), ...answer }
|
||||
const merged = { ...providerFormDefaults(selected.form), ...answer }
|
||||
if (selected.type === "key") {
|
||||
dispatch({ type: "auth.answer", answer: Object.keys(merged).length ? merged : undefined })
|
||||
return
|
||||
}
|
||||
if (selected.type !== "oauth") return
|
||||
if (selected.form?.some((field) => field.type !== "string")) {
|
||||
dispatch({ type: "auth.error", error: "This authentication form contains unsupported fields" })
|
||||
dispatch({ type: "auth.error", error: language.t("provider.connect.error.unsupportedFields") })
|
||||
return
|
||||
}
|
||||
dispatch({ type: "auth.pending" })
|
||||
@@ -259,9 +305,11 @@ export function createProviderConnectionController(options: {
|
||||
location: location(),
|
||||
})
|
||||
.then((response) => {
|
||||
if (options.provider() === CONSOLE_INTEGRATION && platform.platform === "desktop") {
|
||||
if (isConsole() && platform.platform === "desktop") {
|
||||
const url = new URL(response.data.url)
|
||||
url.searchParams.set("client_id", "opencode-desktop")
|
||||
// Lets the Console return link focus the window that started the sign-in.
|
||||
url.searchParams.set("return_window", platform.windowID)
|
||||
response.data.url = url.href
|
||||
}
|
||||
return { ok: true as const, authorization: response.data }
|
||||
@@ -281,21 +329,28 @@ export function createProviderConnectionController(options: {
|
||||
if (!result.ok) {
|
||||
dispatch({
|
||||
type: "auth.error",
|
||||
error: result.error instanceof Error ? result.error.message : String(result.error),
|
||||
error: isConsole() ? language.t("provider.connect.console.startFailed") : errorMessage(result.error),
|
||||
})
|
||||
return
|
||||
}
|
||||
polling.attempt = result.authorization
|
||||
dispatch({ type: "auth.complete", authorization: result.authorization })
|
||||
dispatch({ type: "auth.waiting", authorization: result.authorization })
|
||||
// Same as `opencode auth login`: hand the user straight to the browser instead of
|
||||
// asking them to click a link and retype a code.
|
||||
platform.openExternal(result.authorization.url)
|
||||
void open()
|
||||
if (result.authorization.mode === "auto") void poll(result.authorization, generation)
|
||||
}
|
||||
const retry = () => {
|
||||
const retry = async () => {
|
||||
if (store.connected) return finish()
|
||||
const authorization = store.authorization
|
||||
if (store.statusFailed && authorization) {
|
||||
polling.attempt = authorization
|
||||
setStore({ state: "waiting", error: undefined, statusFailed: false })
|
||||
return poll(authorization, polling.generation)
|
||||
}
|
||||
const index = store.methodIndex
|
||||
if (index === undefined) return
|
||||
void select(index, store.formAnswer)
|
||||
return select(index, store.formAnswer)
|
||||
}
|
||||
const reset = () => {
|
||||
cancelPolling()
|
||||
@@ -323,10 +378,7 @@ export function createProviderConnectionController(options: {
|
||||
})
|
||||
.then(() => ({ ok: true as const }))
|
||||
.catch((error) => ({ ok: false as const, error }))
|
||||
if (!result.ok) {
|
||||
const message = result.error instanceof Error ? result.error.message : String(result.error)
|
||||
return message || language.t("provider.connect.oauth.code.invalid")
|
||||
}
|
||||
if (!result.ok) return errorMessage(result.error) || language.t("provider.connect.oauth.code.invalid")
|
||||
await finish()
|
||||
return undefined
|
||||
}
|
||||
@@ -350,6 +402,7 @@ export function createProviderConnectionController(options: {
|
||||
currentMethod,
|
||||
methodIndex: () => store.methodIndex,
|
||||
authorization: () => store.authorization,
|
||||
browserFailed: () => store.browserFailed,
|
||||
// True while nothing useful can be shown yet: the integration is loading, a method is
|
||||
// about to be picked automatically, or the authorization request is in flight.
|
||||
busy: () =>
|
||||
@@ -363,6 +416,7 @@ export function createProviderConnectionController(options: {
|
||||
reset,
|
||||
retry,
|
||||
open,
|
||||
refresh: finish,
|
||||
connectKey,
|
||||
completeCode,
|
||||
},
|
||||
|
||||
@@ -1,55 +1,91 @@
|
||||
import { Button } from "@opencode/ui/button"
|
||||
import { Badge } from "@opencode/ui/badge"
|
||||
import { useDialog } from "@opencode/ui/context/dialog"
|
||||
import { Icon } from "@opencode/ui/icon"
|
||||
import { List } from "@opencode/ui/list"
|
||||
import { ProviderIcon } from "@opencode/ui/provider-icon"
|
||||
import { Spinner } from "@opencode/ui/spinner"
|
||||
import { TextField } from "@opencode/ui/text-field"
|
||||
import { DialogBody, DialogHeader, DialogTitle, Dialog } from "@opencode/ui/dialog"
|
||||
import { TextInput } from "@opencode/ui/text-input"
|
||||
import { showToast } from "@/shell/notifications/toast"
|
||||
import { type Component, createMemo, createUniqueId, For, type JSX, Match, onMount, Show, Switch } from "solid-js"
|
||||
import {
|
||||
type Component,
|
||||
createEffect,
|
||||
createMemo,
|
||||
createUniqueId,
|
||||
For,
|
||||
type JSX,
|
||||
Match,
|
||||
onMount,
|
||||
Show,
|
||||
Switch,
|
||||
} from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { useParams } from "@solidjs/router"
|
||||
import { ExternalLink } from "@/runtime/platform/external-link"
|
||||
import { useLanguage } from "@/runtime/i18n/language"
|
||||
import { usePlatform } from "@/runtime/platform/platform"
|
||||
import { useServerSDK } from "@/runtime/server/client"
|
||||
import { useData } from "@/runtime/server/current"
|
||||
import { useGlobal } from "@/runtime/server/runtime"
|
||||
import { ServerConnection } from "@/runtime/server/registry"
|
||||
import { useProviders } from "@/providers/catalog/providers"
|
||||
import { consoleProviderGroup, consoleProviderName } from "@/providers/catalog/console"
|
||||
import { useIntegrations } from "@/providers/catalog/integrations"
|
||||
import { CustomProviderForm } from "@/providers/credentials/dialog"
|
||||
import { ProviderModelGroup, ProviderModelIcon } from "@/providers/models/provider-group"
|
||||
import type { ModelSelection } from "@/providers/models/selection"
|
||||
import { OpenCodeLogo } from "@/providers/opencode-logo"
|
||||
import { decode64 } from "@/runtime/persistence/base64"
|
||||
import { SettingsList } from "@/settings/list"
|
||||
import { useTabs } from "@/shell/tabs/tabs"
|
||||
import {
|
||||
CONSOLE_INTEGRATION,
|
||||
CONSOLE_PROVIDERS,
|
||||
consoleIntegration,
|
||||
createProviderConnectionController,
|
||||
providerFormDefaults,
|
||||
type ProviderConnectMethod,
|
||||
} from "./controller"
|
||||
import { ConsoleAuthorization } from "./console"
|
||||
import { authServerName, RemoteAuthNotice } from "./remote"
|
||||
import "./models.css"
|
||||
|
||||
const CUSTOM_ID = "_custom"
|
||||
type IntegrationForm = NonNullable<ProviderConnectMethod["form"]>[number]
|
||||
type StringForm = Extract<IntegrationForm, { type: "string" }>
|
||||
|
||||
export function useProviderConnectController(options: { onBack?: () => void } = {}) {
|
||||
export function useProviderConnectController() {
|
||||
const [store, setStore] = createStore({ selected: undefined as string | undefined })
|
||||
const reset = () => setStore("selected", undefined)
|
||||
|
||||
return {
|
||||
selected: () => store.selected,
|
||||
select: (provider?: string) => setStore("selected", provider),
|
||||
back: options.onBack ?? reset,
|
||||
reset,
|
||||
}
|
||||
}
|
||||
|
||||
export const DialogConnectProvider: Component<{
|
||||
directory?: string
|
||||
/** Connects at the server's default Location instead of the current route's directory. */
|
||||
defaultLocation?: boolean
|
||||
controller?: ReturnType<typeof useProviderConnectController>
|
||||
selection?: ModelSelection
|
||||
onDone?: () => void
|
||||
onConnected?: (provider: string) => void
|
||||
}> = (props) => {
|
||||
const fallback = useProviderConnectController()
|
||||
const controller = props.controller ?? fallback
|
||||
const [state, setState] = createStore({
|
||||
completed: false,
|
||||
modelProvider: undefined as { id: string; name: string } | undefined,
|
||||
authorization: false,
|
||||
})
|
||||
const language = useLanguage()
|
||||
const reset = controller.back
|
||||
const reset = controller.reset
|
||||
const back = { current: reset }
|
||||
const consoleSelected = () => CONSOLE_PROVIDERS.has(controller.selected() ?? "")
|
||||
let focusHost: HTMLDivElement | undefined
|
||||
const holdFocus = () => focusHost?.focus({ preventScroll: true })
|
||||
const select = (provider?: string) => {
|
||||
@@ -63,13 +99,22 @@ export const DialogConnectProvider: Component<{
|
||||
<Match when={controller.selected() === CUSTOM_ID}>
|
||||
<CustomProviderForm autofocus={false} />
|
||||
</Match>
|
||||
<Match when={controller.selected() && controller.selected() !== CUSTOM_ID ? controller.selected() : undefined}>
|
||||
<Match
|
||||
keyed
|
||||
when={controller.selected() && controller.selected() !== CUSTOM_ID ? controller.selected() : undefined}
|
||||
>
|
||||
{(provider) => (
|
||||
<ProviderConnection
|
||||
provider={provider()}
|
||||
provider={provider}
|
||||
directory={props.directory}
|
||||
defaultLocation={props.defaultLocation}
|
||||
onBack={reset}
|
||||
setBack={(handler) => (back.current = handler)}
|
||||
selection={props.selection}
|
||||
onDone={props.onDone ? () => setState("completed", true) : undefined}
|
||||
onConnected={() => props.onConnected?.(provider)}
|
||||
onFirstConnection={(provider) => setState("modelProvider", provider)}
|
||||
onAuthorization={(authorization) => setState("authorization", authorization)}
|
||||
/>
|
||||
)}
|
||||
</Match>
|
||||
@@ -82,25 +127,53 @@ export const DialogConnectProvider: Component<{
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
containerClass="!h-[min(calc(100vh_-_16px),512px)] !w-[min(calc(100vw_-_16px),640px)]"
|
||||
preventBackdropDismiss={state.authorization}
|
||||
containerClass={
|
||||
state.modelProvider
|
||||
? "!h-[min(calc(100vh_-_16px),560px)] !w-[min(calc(100vw_-_16px),640px)]"
|
||||
: consoleSelected() && state.authorization
|
||||
? "!h-auto !max-h-[min(calc(100vh_-_16px),560px)] !w-[min(calc(100vw_-_16px),640px)]"
|
||||
: "!h-[min(calc(100vh_-_16px),512px)] !w-[min(calc(100vw_-_16px),640px)]"
|
||||
}
|
||||
onCloseAutoFocus={(event) => {
|
||||
if (!state.completed || !props.onDone) return
|
||||
event.preventDefault()
|
||||
props.onDone()
|
||||
}}
|
||||
class="[font-family:var(--v2-font-family-sans)] [&_[data-slot=dialog-header]]:!px-5 [&_[data-slot=dialog-header-title]]:!text-[15px] [&_[data-slot=dialog-header-title]]:!tracking-[-0.13px]"
|
||||
classList={{
|
||||
"[&_[data-slot=dialog-header]]:!pt-4 [&_[data-slot=dialog-header]]:!pb-3": consoleSelected() && !state.modelProvider,
|
||||
"[&_[data-slot=dialog-header]]:!pt-5": !!state.modelProvider,
|
||||
}}
|
||||
>
|
||||
<DialogHeader closeLabel={language.t("common.close")}>
|
||||
<Show
|
||||
when={controller.selected()}
|
||||
fallback={<DialogTitle>{language.t("command.provider.connect")}</DialogTitle>}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="flex size-5 items-center justify-center rounded-sm text-v2-icon-icon-muted hover:bg-v2-overlay-simple-overlay-hover focus-visible:bg-v2-overlay-simple-overlay-hover focus-visible:outline-none"
|
||||
onClick={() => back.current()}
|
||||
aria-label={language.t("common.goBack")}
|
||||
>
|
||||
<Icon name="arrow-left" size="small" />
|
||||
</button>
|
||||
</Show>
|
||||
<Switch>
|
||||
<Match when={state.modelProvider}>
|
||||
{(provider) => (
|
||||
<div class="flex items-center gap-2">
|
||||
<ProviderModelIcon provider={provider()} class="shrink-0" />
|
||||
<DialogTitle>{language.t("provider.connect.models.title", { provider: provider().name })}</DialogTitle>
|
||||
</div>
|
||||
)}
|
||||
</Match>
|
||||
<Match when={controller.selected()}>
|
||||
<button
|
||||
type="button"
|
||||
class="flex size-5 items-center justify-center rounded-sm text-v2-icon-icon-muted hover:bg-v2-overlay-simple-overlay-hover focus-visible:bg-v2-overlay-simple-overlay-hover focus-visible:outline-none"
|
||||
onClick={() => back.current()}
|
||||
aria-label={language.t("common.goBack")}
|
||||
>
|
||||
<Icon name="arrow-left" size="small" />
|
||||
</button>
|
||||
</Match>
|
||||
<Match when={true}>
|
||||
<DialogTitle>{language.t("command.provider.connect")}</DialogTitle>
|
||||
</Match>
|
||||
</Switch>
|
||||
</DialogHeader>
|
||||
<DialogBody class="min-h-0 flex-1 overflow-hidden px-2 pb-2">
|
||||
<DialogBody
|
||||
class={`min-h-0 flex-1 overflow-hidden px-2 ${state.modelProvider || consoleSelected() ? "pb-0" : "pb-2"}`}
|
||||
>
|
||||
<div ref={focusHost} tabIndex={-1} class="flex min-h-0 flex-1 flex-col outline-none">
|
||||
<Content />
|
||||
</div>
|
||||
@@ -119,10 +192,27 @@ function ProviderPicker(props: { directory?: string; onSelect: (provider: string
|
||||
})
|
||||
const featured = ["opencode-go", "opencode", "anthropic", "openai", "google", "openrouter", "vercel"]
|
||||
const custom = () => ({ id: CUSTOM_ID, name: language.t("dialog.provider.custom.label") })
|
||||
// Only a stored credential hides a provider: environment and config connections can still be
|
||||
// replaced by a sign-in. OpenCode Zen stays until a Console account (not a key) is connected.
|
||||
const consoleAccount = createMemo(() =>
|
||||
integrations
|
||||
.list()
|
||||
.find((integration) => integration.id === CONSOLE_INTEGRATION)
|
||||
?.connections.some((connection) => connection.type === "credential" && connection.method === "oauth"),
|
||||
)
|
||||
const all = createMemo(() => {
|
||||
language.locale()
|
||||
const query = store.filter.trim().toLowerCase()
|
||||
const values = [custom(), ...integrations.list()]
|
||||
const values = [
|
||||
custom(),
|
||||
...integrations
|
||||
.list()
|
||||
.filter((integration) =>
|
||||
integration.id === CONSOLE_INTEGRATION
|
||||
? !consoleAccount()
|
||||
: !integration.connections.some((connection) => connection.type === "credential"),
|
||||
),
|
||||
]
|
||||
if (!query) return values
|
||||
return values.filter((provider) => `${provider.id} ${provider.name}`.toLowerCase().includes(query))
|
||||
})
|
||||
@@ -212,9 +302,9 @@ function ProviderPicker(props: { directory?: string; onSelect: (provider: string
|
||||
aria-busy={store.connecting === provider.id}
|
||||
onClick={() => connect(provider.id)}
|
||||
>
|
||||
<ProviderIcon id={provider.id} class="size-4 shrink-0 text-v2-icon-icon-base" />
|
||||
<ProviderModelIcon provider={provider} class="shrink-0 text-v2-icon-icon-base" />
|
||||
<span class="min-w-0 truncate font-[530] text-v2-text-text-base">{provider.name}</span>
|
||||
<Show when={provider.id === "opencode" || provider.id === "opencode-go"}>
|
||||
<Show when={CONSOLE_PROVIDERS.has(provider.id)}>
|
||||
<span class="min-w-0 truncate font-[440] text-v2-text-text-muted">
|
||||
{language.t(
|
||||
provider.id === "opencode"
|
||||
@@ -259,48 +349,81 @@ function ProviderPicker(props: { directory?: string; onSelect: (provider: string
|
||||
function ProviderConnection(props: {
|
||||
provider: string
|
||||
directory?: string
|
||||
defaultLocation?: boolean
|
||||
onBack: () => void
|
||||
setBack: (handler: () => void) => void
|
||||
selection?: ModelSelection
|
||||
onDone?: () => void
|
||||
onConnected?: () => void
|
||||
onFirstConnection: (provider: { id: string; name: string }) => void
|
||||
onAuthorization: (authorization: boolean) => void
|
||||
}) {
|
||||
const dialog = useDialog()
|
||||
const params = useParams()
|
||||
const language = useLanguage()
|
||||
const platform = usePlatform()
|
||||
const sdk = useServerSDK()
|
||||
const data = useData()
|
||||
const global = useGlobal()
|
||||
const providers = useProviders(() => props.directory)
|
||||
const integrations = useIntegrations(() => props.directory)
|
||||
const directory = () => props.directory ?? decode64(params.dir)
|
||||
const location = () => {
|
||||
const value = directory()
|
||||
return value ? { directory: value } : undefined
|
||||
}
|
||||
const integrationID = () => consoleIntegration(props.provider)
|
||||
const isConsole = () => CONSOLE_PROVIDERS.has(props.provider)
|
||||
const tabs = useTabs()
|
||||
// A sign-in belongs to the Location where it began, even if the route changes underneath it.
|
||||
const initialDirectory = props.defaultLocation ? undefined : (props.directory ?? decode64(params.dir))
|
||||
const directory = () => initialDirectory
|
||||
const location = () => (initialDirectory ? { directory: initialDirectory } : undefined)
|
||||
const providers = useProviders(directory)
|
||||
const integrations = useIntegrations(directory)
|
||||
const integrationID = consoleIntegration(props.provider)
|
||||
const isConsole = CONSOLE_PROVIDERS.has(props.provider)
|
||||
const remote = isConsole && authServerName(sdk.server) !== undefined
|
||||
const [state, setState] = createStore({
|
||||
copied: false,
|
||||
copyFailed: false,
|
||||
firstConnection: undefined as boolean | undefined,
|
||||
models: false,
|
||||
noModels: false,
|
||||
// The workspace providers had not loaded when the wait ran out.
|
||||
catalogPending: false,
|
||||
selectedModel: "",
|
||||
collapsed: {} as Record<string, boolean>,
|
||||
})
|
||||
|
||||
const controller = createProviderConnectionController({
|
||||
provider: integrationID,
|
||||
provider: () => integrationID,
|
||||
// A Go service-account key still belongs to the `opencode-go` integration (zen/go/v1),
|
||||
// exactly as before; only the sign-in is shared with the Console.
|
||||
keyProvider: () => props.provider,
|
||||
directory,
|
||||
autoSelect: (methods) => {
|
||||
if (!isConsole()) return undefined
|
||||
if (!isConsole) return undefined
|
||||
const index = methods.findIndex((method) => method.type === "oauth")
|
||||
return index === -1 ? undefined : index
|
||||
},
|
||||
prepare: isConsole ? prepareConsoleCatalog : undefined,
|
||||
pollInterval: isConsole ? 500 : undefined,
|
||||
onComplete: () => {
|
||||
props.onConnected?.()
|
||||
// The picker only lists the newest model per family by default, which hides most of
|
||||
// what a new connection just unlocked. Show everything the connected integration offers.
|
||||
// Console sign-in returns Go models inside the `opencode` provider, so this covers Go too.
|
||||
const linked = (data.location.provider.list(location()) ?? []).filter(
|
||||
(item) => item.id === props.provider || item.integrationID === integrationID(),
|
||||
)
|
||||
const ids = new Set(linked.map((item) => item.id))
|
||||
global.models.show(
|
||||
(data.location.model.list(location()) ?? [])
|
||||
.filter((model) => ids.has(model.providerID) && model.status !== "deprecated")
|
||||
.map((model) => ({ providerID: model.providerID, modelID: model.id })),
|
||||
connectionModels().map((model) => ({ providerID: model.providerID, modelID: model.id })),
|
||||
)
|
||||
if (state.catalogPending) {
|
||||
setState("noModels", true)
|
||||
return
|
||||
}
|
||||
if (state.firstConnection) {
|
||||
const first = connectionGroups()[0]?.models[0]
|
||||
if (first) {
|
||||
setState({ models: true, selectedModel: modelKey(first) })
|
||||
props.onFirstConnection({ id: props.provider, name: provider().name })
|
||||
return
|
||||
}
|
||||
// Keep the "connected, but no models" state visible so the workspace can be fixed.
|
||||
if (isConsole) {
|
||||
setState("noModels", true)
|
||||
return
|
||||
}
|
||||
}
|
||||
dialog.close()
|
||||
showToast({
|
||||
variant: "success",
|
||||
@@ -310,6 +433,75 @@ function ProviderConnection(props: {
|
||||
})
|
||||
},
|
||||
})
|
||||
// Captured before the new credential lands, so the connection itself never counts as existing.
|
||||
createEffect(() => {
|
||||
if (state.firstConnection !== undefined) return
|
||||
const existing = providers.anyConnection()
|
||||
if (existing === undefined) return
|
||||
setState("firstConnection", !existing)
|
||||
})
|
||||
const connectionProviders = createMemo(() =>
|
||||
(data.location.provider.list(location()) ?? []).filter(
|
||||
(provider) => provider.id === props.provider || provider.integrationID === integrationID,
|
||||
),
|
||||
)
|
||||
const connectionModels = createMemo(() => {
|
||||
const ids = new Set(connectionProviders().map((provider) => provider.id))
|
||||
return (data.location.model.list(location()) ?? []).filter(
|
||||
(model) => ids.has(model.providerID) && model.enabled && model.status !== "deprecated",
|
||||
)
|
||||
})
|
||||
const connectionGroups = createMemo(() => {
|
||||
const models = connectionModels()
|
||||
return connectionProviders()
|
||||
.map((provider) => ({ provider, models: models.filter((model) => model.providerID === provider.id) }))
|
||||
.filter((group) => group.models.length > 0)
|
||||
})
|
||||
const managedProviders = createMemo(() => (isConsole ? consoleProviderGroup(connectionProviders()) : undefined))
|
||||
|
||||
// The server loads the Console workspace's providers after the grant lands, so the first refresh
|
||||
// can still show only the free catalog. Poll briefly for the workspace providers before moving on.
|
||||
async function prepareConsoleCatalog(active: () => boolean) {
|
||||
if (controller.currentMethod()?.type === "key") return active()
|
||||
const loaded = () =>
|
||||
managedProviders() !== undefined || connectionProviders().some((provider) => provider.id !== "opencode")
|
||||
const deadline = Date.now() + 10_000
|
||||
while (!loaded() && active() && Date.now() < deadline) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 250))
|
||||
if (!active()) return false
|
||||
data.location.provider.invalidate(location())
|
||||
data.location.model.invalidate(location())
|
||||
await Promise.all([data.location.provider.sync(location()), data.location.model.sync(location())]).catch(
|
||||
() => undefined,
|
||||
)
|
||||
}
|
||||
setState("catalogPending", !loaded())
|
||||
return active()
|
||||
}
|
||||
const connectionGroupName = (name: string) => {
|
||||
const managed = managedProviders()
|
||||
return managed ? consoleProviderName(managed, name) : name
|
||||
}
|
||||
const modelKey = (model: { providerID: string; id: string }) => `${model.providerID}:${model.id}`
|
||||
const selectedModel = () => connectionModels().find((model) => modelKey(model) === state.selectedModel)
|
||||
const copyLink = async () => {
|
||||
const url = controller.authorization()?.url
|
||||
if (!url) return
|
||||
const copied = await Promise.resolve()
|
||||
.then(() => (platform.writeClipboardText ? platform.writeClipboardText(url) : navigator.clipboard.writeText(url)))
|
||||
.then(() => true)
|
||||
.catch(() => false)
|
||||
if (controller.authorization()?.url !== url) return
|
||||
setState({ copied, copyFailed: !copied })
|
||||
}
|
||||
createEffect(() => {
|
||||
controller.authorization()?.attemptID
|
||||
setState({ copied: false, copyFailed: false })
|
||||
})
|
||||
createEffect(() => {
|
||||
const current = controller.auth.state()
|
||||
props.onAuthorization(controller.authorization() !== undefined && (current === "waiting" || current === "refreshing"))
|
||||
})
|
||||
const provider = createMemo(() => ({
|
||||
id: props.provider,
|
||||
name:
|
||||
@@ -339,16 +531,30 @@ function ProviderConnection(props: {
|
||||
}
|
||||
}
|
||||
const code = createMemo(() => {
|
||||
const instructions = controller.authorization()?.instructions
|
||||
const authorization = controller.authorization()
|
||||
if (!authorization) return
|
||||
const userCode = new URL(authorization.url).searchParams.get("user_code")
|
||||
if (userCode) return userCode
|
||||
const instructions = authorization.instructions
|
||||
if (instructions?.includes(":")) return instructions.split(":").pop()?.trim()
|
||||
return instructions
|
||||
})
|
||||
const keyIndex = () => controller.methods().findIndex((method) => method.type === "key")
|
||||
const oauthIndex = () => controller.methods().findIndex((method) => method.type === "oauth")
|
||||
// The Console device flow owns the dialog from the first frame until the catalogs are loaded.
|
||||
const consoleSignIn = () =>
|
||||
isConsole &&
|
||||
!state.noModels &&
|
||||
controller.currentMethod()?.type !== "key" &&
|
||||
controller.auth.state() !== "error" &&
|
||||
(controller.busy() || controller.authorization()?.mode === "auto")
|
||||
|
||||
function AuthFormView() {
|
||||
const defaults = providerFormDefaults(controller.currentMethod()?.form)
|
||||
const [formStore, setFormStore] = createStore({
|
||||
value: {} as Record<string, string>,
|
||||
value: Object.fromEntries(
|
||||
Object.entries(defaults).flatMap(([key, value]) => (typeof value === "string" ? [[key, value]] : [])),
|
||||
) as Record<string, string>,
|
||||
index: 0,
|
||||
})
|
||||
|
||||
@@ -471,11 +677,11 @@ function ProviderConnection(props: {
|
||||
function goBack() {
|
||||
// The API key path for the Console is an escape hatch below the sign-in flow, so
|
||||
// "back" returns to the sign-in rather than leaving the provider.
|
||||
if (isConsole() && controller.currentMethod()?.type === "key" && oauthIndex() !== -1) {
|
||||
if (isConsole && controller.currentMethod()?.type === "key" && oauthIndex() !== -1) {
|
||||
void controller.auth.select(oauthIndex())
|
||||
return
|
||||
}
|
||||
if (!isConsole() && controller.methods().length > 1 && controller.methodIndex() !== undefined) {
|
||||
if (!isConsole && controller.methods().length > 1 && controller.methodIndex() !== undefined) {
|
||||
controller.auth.reset()
|
||||
return
|
||||
}
|
||||
@@ -531,10 +737,12 @@ function ProviderConnection(props: {
|
||||
<div class="flex items-start gap-2 text-[13px] font-[440] leading-5 tracking-[-0.04px] text-v2-text-text-base">
|
||||
<Icon name="circle-ban-sign" size="small" class="mt-0.5 shrink-0 text-v2-state-fg-danger" />
|
||||
<span role="alert">
|
||||
{language.t("provider.connect.status.failed", { error: controller.auth.error() ?? "" })}
|
||||
{isConsole
|
||||
? controller.auth.error()
|
||||
: language.t("provider.connect.status.failed", { error: controller.auth.error() ?? "" })}
|
||||
</span>
|
||||
</div>
|
||||
<Button variant="neutral" onClick={() => controller.auth.retry()}>
|
||||
<Button variant="neutral" onClick={() => void controller.auth.retry()}>
|
||||
{language.t("common.retry")}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -572,7 +780,7 @@ function ProviderConnection(props: {
|
||||
return (
|
||||
<div class="flex flex-col gap-5 px-3 text-[13px] font-[440] leading-5 tracking-[-0.04px] text-v2-text-text-muted">
|
||||
<Show
|
||||
when={isConsole()}
|
||||
when={isConsole}
|
||||
fallback={language.t("provider.connect.apiKey.description", { provider: provider().name })}
|
||||
>
|
||||
<div>
|
||||
@@ -586,7 +794,7 @@ function ProviderConnection(props: {
|
||||
</div>
|
||||
</Show>
|
||||
<form onSubmit={handleSubmit} class="flex flex-col items-start gap-5 self-stretch">
|
||||
<label class="flex w-full flex-col gap-1 font-[530] leading-4 text-v2-text-text-base">
|
||||
<label class="flex w-full flex-col gap-2 font-[530] leading-4 text-v2-text-text-base">
|
||||
{language.t("provider.connect.apiKey.label", { provider: provider().name })}
|
||||
<TextInput
|
||||
ref={apiKey}
|
||||
@@ -648,11 +856,11 @@ function ProviderConnection(props: {
|
||||
return (
|
||||
<div class="flex flex-col gap-5 px-3 text-[13px] font-[440] leading-5 tracking-[-0.04px] text-v2-text-text-muted">
|
||||
<div>{language.t("provider.connect.oauth.code.description", { provider: provider().name })}</div>
|
||||
<Button variant="neutral" icon="arrow-up-right" onClick={() => controller.auth.open()}>
|
||||
<Button variant="neutral" icon="arrow-up-right" onClick={() => void controller.auth.open()}>
|
||||
{language.t("provider.connect.oauth.openBrowser")}
|
||||
</Button>
|
||||
<form onSubmit={handleSubmit} class="flex flex-col items-start gap-5 self-stretch">
|
||||
<label class="flex w-full flex-col gap-1 font-[530] leading-4 text-v2-text-text-base">
|
||||
<label class="flex w-full flex-col gap-2 font-[530] leading-4 text-v2-text-text-base">
|
||||
{language.t("provider.connect.oauth.code.label", { method: controller.currentMethod()?.label ?? "" })}
|
||||
<TextInput
|
||||
ref={codeInput}
|
||||
@@ -688,7 +896,7 @@ function ProviderConnection(props: {
|
||||
<div>{language.t("provider.connect.oauth.auto.description", { provider: provider().name })}</div>
|
||||
<StatusRow>{language.t("provider.connect.status.waiting")}</StatusRow>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<Button variant="neutral" icon="arrow-up-right" onClick={() => controller.auth.open()}>
|
||||
<Button variant="neutral" icon="arrow-up-right" onClick={() => void controller.auth.open()}>
|
||||
{language.t("provider.connect.oauth.openBrowser")}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -708,109 +916,286 @@ function ProviderConnection(props: {
|
||||
)
|
||||
}
|
||||
|
||||
// Rendered from the first frame of the Console sign-in, before the attempt exists. Only the
|
||||
// status line changes once the browser opens, so nothing around it moves.
|
||||
function ConsoleSignInView() {
|
||||
const ready = () => controller.authorization()?.url !== undefined
|
||||
// Deliberately quiet: most people should never need a key, so this stays small and at the bottom.
|
||||
function ConsoleApiKeySwitch() {
|
||||
return (
|
||||
<div class="flex flex-col gap-5 px-3 text-[13px] font-[440] leading-5 tracking-[-0.04px] text-v2-text-text-muted">
|
||||
<div>{language.t("provider.connect.console.description", { provider: provider().name })}</div>
|
||||
<StatusRow>
|
||||
{language.t(ready() ? "provider.connect.status.waiting" : "provider.connect.console.opening")}
|
||||
</StatusRow>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<Button variant="neutral" icon="arrow-up-right" disabled={!ready()} onClick={() => controller.auth.open()}>
|
||||
{language.t("provider.connect.oauth.openBrowser")}
|
||||
</Button>
|
||||
</div>
|
||||
<TextField
|
||||
label={language.t("provider.connect.oauth.auto.confirmationCode")}
|
||||
description={language.t("provider.connect.oauth.auto.confirmationCode.description")}
|
||||
class="font-mono"
|
||||
value={code() ?? ""}
|
||||
placeholder={language.t("provider.connect.console.code.placeholder")}
|
||||
readOnly
|
||||
copyable={code() !== undefined}
|
||||
/>
|
||||
<div data-component="console-service-account" class="flex h-7 items-center gap-1 px-3 pt-5 text-[13px]">
|
||||
<span class="text-v2-text-text-faint">{language.t("provider.connect.console.serviceAccount")}</span>
|
||||
<Button
|
||||
variant="ghost-muted"
|
||||
data-action="provider-connect-api-key"
|
||||
onClick={() => void controller.auth.select(keyIndex())}
|
||||
>
|
||||
{language.t("provider.connect.console.useApiKey")}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Deliberately quiet: most people should never need a key, so this stays small and at the bottom.
|
||||
function ConsoleApiKeySwitch() {
|
||||
function ConsoleNoModels() {
|
||||
return (
|
||||
<div class="mt-auto flex justify-end px-3 pt-4 text-[11px] leading-4 text-v2-text-text-muted">
|
||||
<button
|
||||
type="button"
|
||||
data-action="provider-connect-api-key"
|
||||
class="rounded-xs px-1 underline decoration-v2-border-border-base underline-offset-2 hover:text-v2-text-text-base focus-visible:outline-2 focus-visible:outline-v2-border-border-focus"
|
||||
onClick={() => void controller.auth.select(keyIndex())}
|
||||
<div role="status" class="flex flex-col items-start gap-5 px-3 text-[13px] leading-5 text-v2-text-text-muted">
|
||||
<div>
|
||||
<p class="flex items-center gap-2 font-medium text-v2-text-text-base">
|
||||
<Icon name="circle-check" />
|
||||
{language.t("provider.connect.console.connected")}
|
||||
</p>
|
||||
<p>
|
||||
{language.t(
|
||||
state.catalogPending ? "provider.connect.console.modelsLoading" : "provider.connect.console.noModels",
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<Show when={!state.catalogPending}>
|
||||
<Button onClick={() => platform.openExternal("https://opencode.ai/console")}>
|
||||
{language.t("provider.connect.console.openAgain")}
|
||||
</Button>
|
||||
</Show>
|
||||
<Button
|
||||
disabled={controller.auth.state() === "refreshing"}
|
||||
aria-busy={controller.auth.state() === "refreshing"}
|
||||
onClick={() => void controller.auth.refresh()}
|
||||
>
|
||||
{language.t("provider.connect.console.refresh")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const startWithModel = async () => {
|
||||
const model = selectedModel()
|
||||
if (!model) return
|
||||
const selection = { providerID: model.providerID, modelID: model.id }
|
||||
if (props.selection) {
|
||||
props.selection.set(selection)
|
||||
props.onDone?.()
|
||||
dialog.close()
|
||||
return
|
||||
}
|
||||
dialog.close()
|
||||
await tabs.newDraft(
|
||||
{
|
||||
server: ServerConnection.key(sdk.server),
|
||||
directory: initialDirectory ?? data.location.default().directory,
|
||||
},
|
||||
undefined,
|
||||
selection,
|
||||
)
|
||||
}
|
||||
|
||||
function ConnectionModelList(listProps: { items: ReturnType<typeof connectionModels> }) {
|
||||
return (
|
||||
<SettingsList>
|
||||
<For each={listProps.items}>
|
||||
{(model) => {
|
||||
const selected = () => state.selectedModel === modelKey(model)
|
||||
return (
|
||||
<div data-component="connected-model-row-shell" class="connected-model-row-shell">
|
||||
<button
|
||||
type="button"
|
||||
role="radio"
|
||||
data-component="settings-row"
|
||||
data-first-provider-model=""
|
||||
data-selected={selected() ? "" : undefined}
|
||||
aria-checked={selected()}
|
||||
class="connected-model-row text-start focus-visible:outline-none"
|
||||
onClick={() => setState("selectedModel", modelKey(model))}
|
||||
>
|
||||
<div data-slot="settings-row-copy">
|
||||
<div data-slot="settings-row-title">
|
||||
<span class="min-w-0 truncate">{model.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div data-slot="settings-row-control" class="size-4">
|
||||
<Show when={selected()}>
|
||||
<Icon name="check" size="small" class="shrink-0 text-v2-icon-icon-base" />
|
||||
</Show>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</For>
|
||||
</SettingsList>
|
||||
)
|
||||
}
|
||||
|
||||
function FirstConnectionModels() {
|
||||
return (
|
||||
<div data-component="first-provider-models" class="flex min-h-0 flex-1 flex-col px-3">
|
||||
<p class="shrink-0 pb-5 text-[13px] leading-5 text-v2-text-text-muted">
|
||||
{language.t("provider.connect.models.description")}
|
||||
</p>
|
||||
<div
|
||||
data-component="first-provider-model-scroll"
|
||||
class="settings-panel settings-models min-h-0 flex-1 overflow-y-auto pb-4"
|
||||
>
|
||||
{language.t("provider.connect.console.apiKey.switch")}
|
||||
</button>
|
||||
<div data-component="available-models-heading" class="flex items-center gap-1.5">
|
||||
<span class="text-[13px] font-[530] leading-4 text-v2-text-text-base">
|
||||
{language.t("provider.connect.models.available")}
|
||||
</span>
|
||||
<Show when={managedProviders()}>{(managed) => <Badge>{managed().workspace}</Badge>}</Show>
|
||||
</div>
|
||||
<div role="radiogroup" aria-label={language.t("provider.connect.models.list", { provider: provider().name })}>
|
||||
<Show
|
||||
when={managedProviders()}
|
||||
fallback={
|
||||
<Show
|
||||
when={connectionGroups().length > 1}
|
||||
fallback={<ConnectionModelList items={connectionGroups()[0]?.models ?? []} />}
|
||||
>
|
||||
<For each={connectionGroups()}>
|
||||
{(group) => {
|
||||
const expanded = () => !state.collapsed[group.provider.id]
|
||||
return (
|
||||
<section class="settings-section" data-expanded={expanded() ? "" : undefined}>
|
||||
<h3 class="settings-models-group-header sticky top-0 z-[1] box-content bg-v2-background-bg-layer-01">
|
||||
<button
|
||||
type="button"
|
||||
class="settings-models-group-trigger"
|
||||
aria-expanded={expanded()}
|
||||
onClick={() => setState("collapsed", group.provider.id, expanded())}
|
||||
>
|
||||
<span class="settings-models-group-chevron">
|
||||
<Icon name="chevron-down" size="small" classList={{ collapsed: !expanded() }} />
|
||||
</span>
|
||||
<span class="settings-models-group-label">
|
||||
<ProviderModelIcon provider={group.provider} class="shrink-0" />
|
||||
<span class="settings-section-title">{group.provider.name}</span>
|
||||
</span>
|
||||
</button>
|
||||
</h3>
|
||||
<Show when={expanded()}>
|
||||
<ConnectionModelList items={group.models} />
|
||||
</Show>
|
||||
</section>
|
||||
)
|
||||
}}
|
||||
</For>
|
||||
</Show>
|
||||
}
|
||||
>
|
||||
<div class="provider-model-groups provider-model-groups--dialog">
|
||||
<For each={connectionGroups()}>
|
||||
{(group) => (
|
||||
<ProviderModelGroup
|
||||
provider={group.provider}
|
||||
name={connectionGroupName(group.provider.name)}
|
||||
expanded={!state.collapsed[group.provider.id]}
|
||||
onExpandedChange={(value) => setState("collapsed", group.provider.id, !value)}
|
||||
>
|
||||
<ConnectionModelList items={group.models} />
|
||||
</ProviderModelGroup>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
data-component="first-provider-model-footer"
|
||||
class="-mx-5 flex h-15 shrink-0 items-center justify-end border-t border-v2-border-border-muted px-4"
|
||||
>
|
||||
<Button variant="contrast" disabled={!selectedModel()} onClick={() => void startWithModel()}>
|
||||
{language.t("common.continue")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="flex min-h-0 flex-1 flex-col">
|
||||
<div class="flex h-10 shrink-0 items-start gap-2 px-3">
|
||||
<ProviderIcon id={props.provider} class="mt-0.5 size-4 shrink-0 text-v2-icon-icon-base" />
|
||||
<div class="text-[15px] font-[530] leading-5 tracking-[-0.13px] text-v2-text-text-base">
|
||||
<Switch>
|
||||
<Match
|
||||
when={props.provider === "anthropic" && controller.currentMethod()?.label?.toLowerCase().includes("max")}
|
||||
>
|
||||
{language.t("provider.connect.title.anthropicProMax")}
|
||||
</Match>
|
||||
<Match when={true}>{language.t("provider.connect.title", { provider: provider().name })}</Match>
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
<Show when={!state.models} fallback={<FirstConnectionModels />}>
|
||||
<div class="flex min-h-0 flex-1 flex-col">
|
||||
<Switch>
|
||||
<Match
|
||||
<div
|
||||
class={isConsole ? "flex shrink-0 items-center gap-2 px-3 pb-6" : "flex h-10 shrink-0 items-start gap-2 px-3"}
|
||||
>
|
||||
<ProviderModelIcon
|
||||
provider={provider()}
|
||||
class={isConsole ? "shrink-0 text-v2-icon-icon-base" : "mt-0.5 shrink-0 text-v2-icon-icon-base"}
|
||||
/>
|
||||
<div class="text-[15px] font-[530] leading-5 tracking-[-0.13px] text-v2-text-text-base">
|
||||
<DialogTitle>
|
||||
<Switch>
|
||||
<Match when={consoleSignIn()}>{language.t("provider.connect.console.title")}</Match>
|
||||
<Match
|
||||
when={
|
||||
props.provider === "anthropic" && controller.currentMethod()?.label?.toLowerCase().includes("max")
|
||||
}
|
||||
>
|
||||
{language.t("provider.connect.title.anthropicProMax")}
|
||||
</Match>
|
||||
<Match when={true}>{language.t("provider.connect.title", { provider: provider().name })}</Match>
|
||||
</Switch>
|
||||
</DialogTitle>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
data-component="provider-connect-content"
|
||||
class={isConsole ? "flex min-h-0 flex-1 flex-col overflow-y-auto pb-4" : "flex min-h-0 flex-1 flex-col"}
|
||||
>
|
||||
<Show when={remote}>
|
||||
<div class="mb-5 px-3">
|
||||
<RemoteAuthNotice server={sdk.server} />
|
||||
</div>
|
||||
</Show>
|
||||
<Switch>
|
||||
<Match when={state.noModels && controller.auth.state() !== "error"}>
|
||||
<ConsoleNoModels />
|
||||
</Match>
|
||||
<Match when={consoleSignIn()}>
|
||||
<div class="px-3">
|
||||
<ConsoleAuthorization
|
||||
code={code()}
|
||||
browserFailed={controller.browserFailed()}
|
||||
copied={state.copied}
|
||||
copyFailed={state.copyFailed}
|
||||
onCopy={() => void copyLink()}
|
||||
onOpen={() => void controller.auth.open()}
|
||||
/>
|
||||
</div>
|
||||
</Match>
|
||||
<Match when={controller.busy()}>
|
||||
<div class="px-3">
|
||||
<StatusRow>{language.t("provider.connect.status.inProgress")}</StatusRow>
|
||||
</div>
|
||||
</Match>
|
||||
<Match when={controller.methodIndex() === undefined}>
|
||||
<MethodSelection />
|
||||
</Match>
|
||||
<Match when={controller.auth.state() === "form"}>
|
||||
<AuthFormView />
|
||||
</Match>
|
||||
<Match when={controller.auth.state() === "error"}>
|
||||
<div class="px-3">
|
||||
<ErrorRow />
|
||||
</div>
|
||||
</Match>
|
||||
<Match when={controller.currentMethod()?.type === "key"}>
|
||||
<ApiAuthView />
|
||||
</Match>
|
||||
<Match when={controller.authorization()?.mode === "code"}>
|
||||
<OAuthCodeView />
|
||||
</Match>
|
||||
<Match when={controller.authorization()?.mode === "auto"}>
|
||||
<OAuthAutoView />
|
||||
</Match>
|
||||
</Switch>
|
||||
<Show
|
||||
when={
|
||||
isConsole() &&
|
||||
isConsole &&
|
||||
!controller.loading() &&
|
||||
!state.noModels &&
|
||||
controller.currentMethod()?.type !== "key" &&
|
||||
controller.auth.state() !== "error" &&
|
||||
(controller.busy() || controller.authorization()?.mode === "auto")
|
||||
keyIndex() !== -1
|
||||
}
|
||||
>
|
||||
<ConsoleSignInView />
|
||||
</Match>
|
||||
<Match when={controller.busy()}>
|
||||
<div class="px-3">
|
||||
<StatusRow>{language.t("provider.connect.status.inProgress")}</StatusRow>
|
||||
</div>
|
||||
</Match>
|
||||
<Match when={controller.methodIndex() === undefined}>
|
||||
<MethodSelection />
|
||||
</Match>
|
||||
<Match when={controller.auth.state() === "form"}>
|
||||
<AuthFormView />
|
||||
</Match>
|
||||
<Match when={controller.auth.state() === "error"}>
|
||||
<div class="px-3">
|
||||
<ErrorRow />
|
||||
</div>
|
||||
</Match>
|
||||
<Match when={controller.currentMethod()?.type === "key"}>
|
||||
<ApiAuthView />
|
||||
</Match>
|
||||
<Match when={controller.authorization()?.mode === "code"}>
|
||||
<OAuthCodeView />
|
||||
</Match>
|
||||
<Match when={controller.authorization()?.mode === "auto"}>
|
||||
<OAuthAutoView />
|
||||
</Match>
|
||||
</Switch>
|
||||
<Show
|
||||
when={isConsole() && !controller.loading() && controller.currentMethod()?.type !== "key" && keyIndex() !== -1}
|
||||
>
|
||||
<ConsoleApiKeySwitch />
|
||||
</Show>
|
||||
<ConsoleApiKeySwitch />
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
.connected-model-row-shell {
|
||||
position: relative;
|
||||
margin-inline: 4px;
|
||||
padding-block: 4px;
|
||||
}
|
||||
|
||||
.connected-model-row-shell:not(:last-child)::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset-inline: 12px;
|
||||
bottom: 0;
|
||||
height: 0.5px;
|
||||
background: var(--v2-border-border-base);
|
||||
}
|
||||
|
||||
.connected-model-row {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
padding-inline: 12px;
|
||||
padding-block: 0;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
.connected-model-row:hover {
|
||||
background-color: var(--v2-background-bg-layer-03);
|
||||
}
|
||||
}
|
||||
|
||||
.connected-model-row:focus-visible {
|
||||
background-color: var(--v2-background-bg-layer-03);
|
||||
}
|
||||
|
||||
[data-component="first-provider-models"] [data-component="settings-list"] {
|
||||
background-color: var(--v2-background-bg-layer-02);
|
||||
overflow: hidden;
|
||||
padding-inline: 0;
|
||||
}
|
||||
|
||||
[data-component="first-provider-models"] .provider-model-groups--dialog .provider-model-group {
|
||||
background-color: var(--v2-background-bg-layer-02);
|
||||
}
|
||||
|
||||
[data-component="first-provider-models"] .provider-model-groups--dialog .provider-model-group-models {
|
||||
padding-inline: 0;
|
||||
}
|
||||
|
||||
[data-component="first-provider-models"]
|
||||
.provider-model-groups--dialog
|
||||
.provider-model-group-models
|
||||
> [data-component="settings-list"] {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
[data-component="first-provider-models"]
|
||||
.provider-model-groups--dialog
|
||||
.provider-model-group-trigger:not(:disabled):hover {
|
||||
background-color: var(--v2-background-bg-layer-03);
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="first-provider-models"] .settings-section {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
[data-component="first-provider-models"] .settings-section[data-expanded] {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { expect, test } from "bun:test"
|
||||
import { authServerName } from "./remote"
|
||||
|
||||
test("SSH disclosure uses the remote identity even with a loopback proxy", () => {
|
||||
expect(authServerName({ type: "ssh", host: "production.example", http: { url: "http://127.0.0.1:4096" } })).toBe(
|
||||
"production.example",
|
||||
)
|
||||
expect(
|
||||
authServerName({
|
||||
type: "ssh",
|
||||
host: "production.example",
|
||||
displayName: "Production server",
|
||||
http: { url: "http://127.0.0.1:4096" },
|
||||
}),
|
||||
).toBe("Production server")
|
||||
})
|
||||
|
||||
test("local Desktop and loopback HTTP connections do not show remote disclosure", () => {
|
||||
expect(authServerName({ type: "sidecar", variant: "base", http: { url: "http://127.0.0.1:4096" } })).toBeUndefined()
|
||||
for (const host of ["localhost", "127.0.0.1", "[::1]"]) {
|
||||
expect(authServerName({ type: "http", http: { url: `http://${host}:4096` } })).toBeUndefined()
|
||||
}
|
||||
})
|
||||
|
||||
test("WSL and remote HTTP connections show their server identity", () => {
|
||||
expect(
|
||||
authServerName({ type: "sidecar", variant: "wsl", distro: "Ubuntu", http: { url: "http://127.0.0.1:4096" } }),
|
||||
).toBe("Ubuntu")
|
||||
expect(authServerName({ type: "http", http: { url: "https://production.example" } })).toBe("production.example")
|
||||
})
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Show } from "solid-js"
|
||||
import { useLanguage } from "@/runtime/i18n/language"
|
||||
import { ServerConnection, serverName } from "@/runtime/server/registry"
|
||||
|
||||
export function authServerName(server: ServerConnection.Any) {
|
||||
if (ServerConnection.builtin(server)) return undefined
|
||||
if (server.type === "http" && ["localhost", "127.0.0.1", "[::1]"].includes(new URL(server.http.url).hostname))
|
||||
return undefined
|
||||
if (server.type === "sidecar" && server.variant === "wsl") return server.displayName ?? server.distro
|
||||
return serverName(server)
|
||||
}
|
||||
|
||||
export function RemoteAuthNotice(props: { server: ServerConnection.Any }) {
|
||||
const language = useLanguage()
|
||||
return (
|
||||
<Show when={authServerName(props.server)}>
|
||||
{(name) => (
|
||||
<div
|
||||
class="rounded-md border border-v2-border-border-base bg-v2-background-bg-layer-02 p-3 text-[13px] leading-5"
|
||||
role="note"
|
||||
>
|
||||
<p class="font-medium text-v2-text-text-base">
|
||||
{language.t("provider.connect.remote.title", { server: name() })}
|
||||
</p>
|
||||
<p class="text-v2-text-text-muted">{language.t("provider.connect.remote.description")}</p>
|
||||
</div>
|
||||
)}
|
||||
</Show>
|
||||
)
|
||||
}
|
||||
@@ -2,7 +2,6 @@ import { Button } from "@opencode/ui/button"
|
||||
import { useDialog } from "@opencode/ui/context/dialog"
|
||||
import { Icon } from "@opencode/ui/icon"
|
||||
import { IconButton } from "@opencode/ui/icon-button"
|
||||
import { ProviderIcon } from "@opencode/ui/provider-icon"
|
||||
import { useMutation } from "@tanstack/solid-query"
|
||||
import { TextField } from "@opencode/ui/text-field"
|
||||
import { showToast } from "@/shell/notifications/toast"
|
||||
@@ -12,6 +11,7 @@ import { ExternalLink } from "@/runtime/platform/external-link"
|
||||
import { useData } from "@/runtime/server/current"
|
||||
import { useLanguage } from "@/runtime/i18n/language"
|
||||
import { type FormState, headerRow, modelRow, validateCustomProvider } from "./form"
|
||||
import { CustomManagedProviderIcon } from "@/providers/models/provider-group"
|
||||
|
||||
export function CustomProviderForm(props: { autofocus?: boolean } = {}) {
|
||||
const dialog = useDialog()
|
||||
@@ -134,7 +134,7 @@ export function CustomProviderForm(props: { autofocus?: boolean } = {}) {
|
||||
return (
|
||||
<div class="flex flex-col gap-6 px-2.5 pb-3 overflow-y-auto max-h-[60vh]">
|
||||
<div class="px-2.5 flex gap-4 items-center">
|
||||
<ProviderIcon id="synthetic" class="size-5 shrink-0 icon-strong-base" />
|
||||
<CustomManagedProviderIcon class="size-5 shrink-0" />
|
||||
<div class="text-16-medium text-text-strong">{language.t("provider.custom.title")}</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_2582_70989)">
|
||||
<rect x="1.33496" y="1.33496" width="13.33" height="13.33" rx="1.66625" fill="#3A3A3A"/>
|
||||
<rect x="1.33496" y="1.33496" width="13.33" height="13.33" rx="1.66625" fill="url(#paint0_linear_2582_70989)" fill-opacity="0.2"/>
|
||||
<circle cx="7.99988" cy="7.99988" r="4.26977" stroke="#808080" stroke-width="0.208281"/>
|
||||
<circle cx="7.99993" cy="7.99993" r="2.2786" stroke="#808080" stroke-width="0.208281"/>
|
||||
<rect x="1.38703" y="7.94782" width="13.2259" height="0.104141" stroke="#808080" stroke-width="0.104141"/>
|
||||
<rect x="1.38703" y="12.2176" width="13.2259" height="0.104141" stroke="#808080" stroke-width="0.104141"/>
|
||||
<rect x="1.38703" y="3.67805" width="13.2259" height="0.104141" stroke="#808080" stroke-width="0.104141"/>
|
||||
<rect x="7.94782" y="1.38703" width="0.104141" height="13.2259" stroke="#808080" stroke-width="0.104141"/>
|
||||
<rect x="3.67805" y="1.38703" width="0.104141" height="13.2259" stroke="#808080" stroke-width="0.104141"/>
|
||||
<rect x="12.2176" y="1.38703" width="0.104141" height="13.2259" stroke="#808080" stroke-width="0.104141"/>
|
||||
<rect x="0.930816" y="1.00439" width="0.104141" height="19.8909" transform="rotate(-45 0.930816 1.00439)" stroke="#808080" stroke-width="0.104141"/>
|
||||
<rect x="14.9958" y="0.930572" width="0.104141" height="19.8909" transform="rotate(45 14.9958 0.930572)" stroke="#808080" stroke-width="0.104141"/>
|
||||
<foreignObject x="0.293476" y="0.293476" width="15.4128" height="15.4128"><div xmlns="http://www.w3.org/1999/xhtml" style="backdrop-filter:blur(1.67px);clip-path:url(#bgblur_1_2582_70989_clip_path);height:100%;width:100%"></div></foreignObject><path data-figma-bg-blur-radius="3.3325" d="M8 3.73047C10.3541 3.73055 12.2695 5.64586 12.2695 8C12.2695 10.3541 10.3541 12.2695 8 12.2695C7.25389 12.2695 6.55544 12.071 5.94434 11.7324H5.94531L7.18457 10.1377C7.43838 10.2348 7.71265 10.291 8 10.291C9.26359 10.291 10.2909 9.26329 10.291 8C10.291 7.763 10.2451 7.54049 10.1807 7.33105L10.1367 7.18945L10.0186 7.27832L8.75879 8.22363H8.22656L7.80469 7.80566C7.80396 7.79142 7.80278 7.77391 7.80176 7.75391C7.79891 7.69808 7.79481 7.6227 7.79102 7.5459C7.78495 7.42322 7.77957 7.29979 7.77734 7.24023L8.72168 5.98145L8.81055 5.86328L8.66895 5.81934C8.45944 5.7548 8.23708 5.709 8 5.70898C6.73632 5.70898 5.70898 6.73661 5.70898 8C5.709 8.2865 5.76377 8.56025 5.86035 8.81348L4.2666 10.0547H4.26562C3.92743 9.4439 3.73049 8.74556 3.73047 8C3.73047 5.64581 5.64581 3.73047 8 3.73047Z" fill="url(#paint1_linear_2582_70989)" stroke="white" stroke-width="0.208281"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="bgblur_1_2582_70989_clip_path" transform="translate(-0.293476 -0.293476)"><path d="M8 3.73047C10.3541 3.73055 12.2695 5.64586 12.2695 8C12.2695 10.3541 10.3541 12.2695 8 12.2695C7.25389 12.2695 6.55544 12.071 5.94434 11.7324H5.94531L7.18457 10.1377C7.43838 10.2348 7.71265 10.291 8 10.291C9.26359 10.291 10.2909 9.26329 10.291 8C10.291 7.763 10.2451 7.54049 10.1807 7.33105L10.1367 7.18945L10.0186 7.27832L8.75879 8.22363H8.22656L7.80469 7.80566C7.80396 7.79142 7.80278 7.77391 7.80176 7.75391C7.79891 7.69808 7.79481 7.6227 7.79102 7.5459C7.78495 7.42322 7.77957 7.29979 7.77734 7.24023L8.72168 5.98145L8.81055 5.86328L8.66895 5.81934C8.45944 5.7548 8.23708 5.709 8 5.70898C6.73632 5.70898 5.70898 6.73661 5.70898 8C5.709 8.2865 5.76377 8.56025 5.86035 8.81348L4.2666 10.0547H4.26562C3.92743 9.4439 3.73049 8.74556 3.73047 8C3.73047 5.64581 5.64581 3.73047 8 3.73047Z"/>
|
||||
</clipPath><linearGradient id="paint0_linear_2582_70989" x1="7.99996" y1="1.33496" x2="7.99996" y2="14.665" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="white" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_2582_70989" x1="7.99988" y1="3.62598" x2="7.99988" y2="12.3737" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white" stop-opacity="0.8"/>
|
||||
<stop offset="1" stop-color="white" stop-opacity="0.5"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_2582_70989">
|
||||
<rect x="1.33496" y="1.33496" width="13.33" height="13.33" rx="1.66625" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
@@ -2,11 +2,10 @@ import { Button } from "@opencode/ui/button"
|
||||
import { Dialog, DialogBody, DialogHeader, DialogTitleGroup } from "@opencode/ui/dialog"
|
||||
import { Icon } from "@opencode/ui/icon"
|
||||
import { IconButton } from "@opencode/ui/icon-button"
|
||||
import { ProviderIcon } from "@opencode/ui/provider-icon"
|
||||
import { Switch } from "@opencode/ui/switch"
|
||||
import { TextInput } from "@opencode/ui/text-input"
|
||||
import { useFilteredList } from "@opencode/ui/hooks"
|
||||
import { For, Show, type Component } from "solid-js"
|
||||
import { createMemo, For, Show, type Component } from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { useLocal } from "@/providers/models/selection"
|
||||
import { popularProviders } from "@/providers/catalog/providers"
|
||||
@@ -16,6 +15,7 @@ import { DialogConnectProvider } from "@/providers/connect/dialog"
|
||||
import { decode64 } from "@/runtime/persistence/base64"
|
||||
import { SettingsList } from "@/settings/list"
|
||||
import { SettingsRow } from "@/settings/row"
|
||||
import { consoleModelGroup, ProviderModelSections } from "@/providers/models/provider-group"
|
||||
import "@/settings/settings.css"
|
||||
|
||||
type ModelItem = ReturnType<ReturnType<typeof useLocal>["model"]["list"]>[number]
|
||||
@@ -54,9 +54,35 @@ export const DialogManageModels: Component = () => {
|
||||
const bPopular = bRank >= 0
|
||||
if (aPopular && !bPopular) return -1
|
||||
if (!aPopular && bPopular) return 1
|
||||
return aRank - bRank
|
||||
if (aPopular && bPopular) return aRank - bRank
|
||||
return a.items[0].provider.name.localeCompare(b.items[0].provider.name)
|
||||
},
|
||||
})
|
||||
const managed = createMemo(() => consoleModelGroup(local.model.list()))
|
||||
const searching = () => list.filter().length > 0
|
||||
const expanded = (key: string) => searching() || !store.collapsed[key]
|
||||
|
||||
function ModelRows(props: { items: ModelItem[] }) {
|
||||
return (
|
||||
<SettingsList variant="catalog">
|
||||
<For each={props.items}>
|
||||
{(item) => (
|
||||
<SettingsRow title={item.name} description="">
|
||||
<div>
|
||||
<Switch
|
||||
checked={local.model.visible({ modelID: item.id, providerID: item.provider.id })}
|
||||
onChange={(checked) => setModelVisibility(item, checked)}
|
||||
hideLabel
|
||||
>
|
||||
{item.name}
|
||||
</Switch>
|
||||
</div>
|
||||
</SettingsRow>
|
||||
)}
|
||||
</For>
|
||||
</SettingsList>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog size="large" variant="settings" class="settings-manage-models-dialog">
|
||||
@@ -100,7 +126,7 @@ export const DialogManageModels: Component = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div data-slot="manage-models-scroll" class="relative min-h-0 flex-1">
|
||||
<div class="settings-panel settings-models h-full px-4 pt-4 pb-4">
|
||||
<div class="settings-panel settings-models h-full px-4 pt-1 pb-4">
|
||||
<Show
|
||||
when={!list.grouped.loading}
|
||||
fallback={
|
||||
@@ -121,69 +147,25 @@ export const DialogManageModels: Component = () => {
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<For each={list.grouped.latest}>
|
||||
{(group) => {
|
||||
const searching = () => list.filter().length > 0
|
||||
const expanded = () => searching() || !store.collapsed[group.category]
|
||||
|
||||
return (
|
||||
<div
|
||||
class="settings-section"
|
||||
data-component="settings-models-provider"
|
||||
data-expanded={expanded() ? "" : undefined}
|
||||
>
|
||||
<div class="settings-models-group-header justify-between">
|
||||
<button
|
||||
type="button"
|
||||
class="settings-models-group-trigger"
|
||||
aria-expanded={expanded()}
|
||||
disabled={searching()}
|
||||
onClick={() => setStore("collapsed", group.category, expanded())}
|
||||
>
|
||||
<span class="settings-models-group-chevron">
|
||||
<Icon
|
||||
name="chevron-down"
|
||||
size="small"
|
||||
classList={{ "-rotate-90 rtl:rotate-90": !expanded() }}
|
||||
/>
|
||||
</span>
|
||||
<span class="settings-models-group-label">
|
||||
<ProviderIcon id={group.category} width={16} height={16} class="shrink-0" />
|
||||
<span class="settings-models-group-title">{group.items[0].provider.name}</span>
|
||||
</span>
|
||||
</button>
|
||||
<Switch
|
||||
class="me-6"
|
||||
checked={providerVisible(group.category)}
|
||||
onChange={(checked) => setProviderVisibility(group.category, checked)}
|
||||
hideLabel
|
||||
>
|
||||
{group.items[0].provider.name}
|
||||
</Switch>
|
||||
</div>
|
||||
<Show when={expanded()}>
|
||||
<SettingsList variant="catalog">
|
||||
<For each={group.items}>
|
||||
{(item) => (
|
||||
<SettingsRow title={item.name} description="">
|
||||
<div>
|
||||
<Switch
|
||||
checked={local.model.visible({ modelID: item.id, providerID: item.provider.id })}
|
||||
onChange={(checked) => setModelVisibility(item, checked)}
|
||||
hideLabel
|
||||
>
|
||||
{item.name}
|
||||
</Switch>
|
||||
</div>
|
||||
</SettingsRow>
|
||||
)}
|
||||
</For>
|
||||
</SettingsList>
|
||||
</Show>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</For>
|
||||
<ProviderModelSections
|
||||
groups={list.grouped.latest}
|
||||
managed={managed()}
|
||||
expanded={expanded}
|
||||
disabled={searching()}
|
||||
onExpandedChange={(key, value) => setStore("collapsed", key, !value)}
|
||||
onSetVisibility={setProviderVisibility}
|
||||
action={(group) => (
|
||||
<Switch
|
||||
class="me-6"
|
||||
checked={providerVisible(group.category)}
|
||||
onChange={(checked) => setProviderVisibility(group.category, checked)}
|
||||
hideLabel
|
||||
>
|
||||
{group.items[0].provider.name}
|
||||
</Switch>
|
||||
)}
|
||||
rows={(items) => <ModelRows items={items} />}
|
||||
/>
|
||||
</Show>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
import { Badge } from "@opencode/ui/badge"
|
||||
import { Icon } from "@opencode/ui/icon"
|
||||
import { IconButton } from "@opencode/ui/icon-button"
|
||||
import { iconNames, type IconName } from "@opencode/ui/icons/provider"
|
||||
import { Menu } from "@opencode/ui/menu"
|
||||
import { ProviderIcon } from "@opencode/ui/provider-icon"
|
||||
import type { JSX } from "solid-js"
|
||||
import { createMemo, For, Match, Show, Switch } from "solid-js"
|
||||
import { consoleProviderGroup, consoleProviderName } from "@/providers/catalog/console"
|
||||
import { OpenCodeLogo } from "@/providers/opencode-logo"
|
||||
import { useLanguage } from "@/runtime/i18n/language"
|
||||
import customManagedProvider from "@/providers/custom-managed-provider.svg"
|
||||
import "@/settings/settings.css"
|
||||
|
||||
type ModelProvider = { id: string; canonical?: string; name: string }
|
||||
type ModelItem = { provider: ModelProvider & { integrationID?: string }; cost?: { input: number } }
|
||||
type ModelGroup<T> = { category: string; items: T[] }
|
||||
|
||||
export const CONSOLE_GROUP_KEY = "console:opencode"
|
||||
|
||||
export function CustomManagedProviderIcon(props: { class?: string }) {
|
||||
return <img data-component="custom-managed-provider-icon" src={customManagedProvider} alt="" class={props.class} />
|
||||
}
|
||||
|
||||
export function ProviderModelIcon(props: { provider: ModelProvider; class?: string }) {
|
||||
const icon = () =>
|
||||
[
|
||||
props.provider.canonical,
|
||||
props.provider.canonical?.replace(/-token-plan$/, ""),
|
||||
props.provider.id.replace(/^console-/, ""),
|
||||
].find((id): id is IconName => !!id && id !== "synthetic" && iconNames.includes(id as IconName))
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Match when={props.provider.id === "opencode"}>
|
||||
<OpenCodeLogo class={`size-4 ${props.class ?? ""}`} />
|
||||
</Match>
|
||||
<Match when={icon()} keyed>
|
||||
{(id) => <ProviderIcon id={id} width={16} height={16} class={props.class} />}
|
||||
</Match>
|
||||
<Match when={true}>
|
||||
<CustomManagedProviderIcon class={`size-4 ${props.class ?? ""}`} />
|
||||
</Match>
|
||||
</Switch>
|
||||
)
|
||||
}
|
||||
|
||||
/** Detects the Console workspace from every listed model, so a search that hides some providers keeps the group. */
|
||||
export function consoleModelGroup<T extends ModelItem>(items: readonly T[]) {
|
||||
return consoleProviderGroup([...new Map(items.map((item) => [item.provider.id, item.provider])).values()])
|
||||
}
|
||||
|
||||
/** Provider sections for a model list, with Console workspace providers nested under one OpenCode Console section. */
|
||||
export function ProviderModelSections<T extends ModelItem>(props: {
|
||||
groups: ModelGroup<T>[]
|
||||
managed: ReturnType<typeof consoleModelGroup<T>>
|
||||
expanded: (key: string) => boolean
|
||||
disabled: boolean
|
||||
onExpandedChange: (key: string, expanded: boolean) => void
|
||||
rows: (items: T[]) => JSX.Element
|
||||
/** Trailing control in a direct provider's header. */
|
||||
action?: (group: ModelGroup<T>) => JSX.Element
|
||||
onSetVisibility?: (providerID: string, visible: boolean) => void
|
||||
ref?: (providerID: string, element: HTMLElement) => void
|
||||
}) {
|
||||
type Section = {
|
||||
group?: ModelGroup<T>
|
||||
managed?: { group: NonNullable<ReturnType<typeof consoleModelGroup<T>>>; providers: ModelGroup<T>[] }
|
||||
}
|
||||
const language = useLanguage()
|
||||
const sections = createMemo<Section[]>(() => {
|
||||
const managed = props.managed
|
||||
const ids = new Set(managed?.providers.map((provider) => provider.id))
|
||||
const nested = props.groups.filter((group) => ids.has(group.category))
|
||||
if (!managed || nested.length === 0) return props.groups.map((group) => ({ group }))
|
||||
const first = props.groups.findIndex((group) => ids.has(group.category))
|
||||
return props.groups.flatMap<Section>((group, index) => {
|
||||
if (!ids.has(group.category)) return [{ group }]
|
||||
if (index !== first) return []
|
||||
return [{ managed: { group: managed, providers: nested } }]
|
||||
})
|
||||
})
|
||||
// Only the keyless catalog is free; a Zen key or Console account keeps the provider's own name.
|
||||
const name = (group: ModelGroup<T>) =>
|
||||
group.category === "opencode" && group.items.every((item) => !item.cost?.input)
|
||||
? language.t("provider.connect.opencode.freeName")
|
||||
: group.items[0].provider.name
|
||||
|
||||
function Header(input: { id: string; icon: JSX.Element; title: JSX.Element; badge?: string; action?: JSX.Element }) {
|
||||
return (
|
||||
<h3 class="settings-models-group-header" classList={{ "justify-between": !!input.action }}>
|
||||
<button
|
||||
type="button"
|
||||
class="settings-models-group-trigger"
|
||||
aria-expanded={props.expanded(input.id)}
|
||||
disabled={props.disabled}
|
||||
onClick={() => props.onExpandedChange(input.id, !props.expanded(input.id))}
|
||||
>
|
||||
<span class="settings-models-group-chevron">
|
||||
<Icon name="chevron-down" size="small" classList={{ collapsed: !props.expanded(input.id) }} />
|
||||
</span>
|
||||
<span class="settings-models-group-label">
|
||||
{input.icon}
|
||||
<bdi class="settings-models-group-title">{input.title}</bdi>
|
||||
<Show when={input.badge}>{(badge) => <Badge>{badge()}</Badge>}</Show>
|
||||
</span>
|
||||
</button>
|
||||
{input.action}
|
||||
</h3>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<For each={sections()}>
|
||||
{(section) => (
|
||||
<Show
|
||||
when={section.managed}
|
||||
fallback={
|
||||
<Show when={section.group}>
|
||||
{(group) => (
|
||||
<section
|
||||
ref={(element) => props.ref?.(group().category, element)}
|
||||
class="settings-section"
|
||||
data-component="settings-models-provider"
|
||||
data-expanded={props.expanded(group().category) ? "" : undefined}
|
||||
>
|
||||
<Header
|
||||
id={group().category}
|
||||
icon={<ProviderModelIcon provider={group().items[0].provider} class="shrink-0" />}
|
||||
title={name(group())}
|
||||
action={props.action?.(group())}
|
||||
/>
|
||||
<Show when={props.expanded(group().category)}>{props.rows(group().items)}</Show>
|
||||
</section>
|
||||
)}
|
||||
</Show>
|
||||
}
|
||||
>
|
||||
{(managed) => (
|
||||
<section
|
||||
class="settings-section"
|
||||
data-component="settings-models-console"
|
||||
data-expanded={props.expanded(CONSOLE_GROUP_KEY) ? "" : undefined}
|
||||
>
|
||||
<Header
|
||||
id={CONSOLE_GROUP_KEY}
|
||||
icon={<OpenCodeLogo class="size-4 shrink-0" />}
|
||||
title={language.t("provider.connect.opencode.name")}
|
||||
badge={managed().group.workspace}
|
||||
/>
|
||||
<Show when={props.expanded(CONSOLE_GROUP_KEY)}>
|
||||
<div class="provider-model-groups settings-models-console-groups">
|
||||
<For each={managed().providers}>
|
||||
{(group) => (
|
||||
<ProviderModelGroup
|
||||
ref={(element) => props.ref?.(group.category, element)}
|
||||
provider={group.items[0].provider}
|
||||
name={consoleProviderName(managed().group, group.items[0].provider.name)}
|
||||
expanded={props.expanded(group.category)}
|
||||
disabled={props.disabled}
|
||||
onSetVisibility={
|
||||
props.onSetVisibility
|
||||
? (visible) => props.onSetVisibility?.(group.category, visible)
|
||||
: undefined
|
||||
}
|
||||
onExpandedChange={(value) => props.onExpandedChange(group.category, value)}
|
||||
>
|
||||
{props.rows(group.items)}
|
||||
</ProviderModelGroup>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
</Show>
|
||||
</section>
|
||||
)}
|
||||
</Show>
|
||||
)}
|
||||
</For>
|
||||
)
|
||||
}
|
||||
|
||||
export function ProviderModelGroup(props: {
|
||||
provider: ModelProvider
|
||||
name?: string
|
||||
expanded: boolean
|
||||
disabled?: boolean
|
||||
onSetVisibility?: (visible: boolean) => void
|
||||
children: JSX.Element
|
||||
ref?: (element: HTMLElement) => void
|
||||
onExpandedChange: (expanded: boolean) => void
|
||||
}) {
|
||||
const language = useLanguage()
|
||||
return (
|
||||
<section
|
||||
ref={props.ref}
|
||||
class="provider-model-group"
|
||||
data-component="provider-model-group"
|
||||
data-provider={props.provider.id}
|
||||
data-expanded={props.expanded ? "" : undefined}
|
||||
>
|
||||
<h3 class="provider-model-group-header">
|
||||
<button
|
||||
type="button"
|
||||
class="provider-model-group-trigger"
|
||||
aria-expanded={props.expanded}
|
||||
disabled={props.disabled}
|
||||
onClick={() => props.onExpandedChange(!props.expanded)}
|
||||
>
|
||||
<span class="provider-model-group-label">
|
||||
<ProviderModelIcon provider={props.provider} class="shrink-0" />
|
||||
<bdi class="provider-model-group-title">{props.name ?? props.provider.name}</bdi>
|
||||
<Icon
|
||||
name="chevron-down"
|
||||
size="small"
|
||||
classList={{ "provider-model-group-chevron": true, collapsed: !props.expanded }}
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
<Show when={props.onSetVisibility} keyed>
|
||||
{(setVisibility) => (
|
||||
<div class="provider-model-group-actions">
|
||||
<Menu gutter={4} modal={false} placement="bottom-end">
|
||||
<Menu.Trigger
|
||||
as={IconButton}
|
||||
variant="ghost-muted"
|
||||
size="small"
|
||||
icon={<Icon name="outline-dots" />}
|
||||
aria-label={language.t("common.moreOptions")}
|
||||
/>
|
||||
<Menu.Portal>
|
||||
<Menu.Content>
|
||||
<Menu.Item onSelect={() => setVisibility(true)}>{language.t("settings.models.enableAll")}</Menu.Item>
|
||||
<Menu.Item onSelect={() => setVisibility(false)}>
|
||||
{language.t("settings.models.disableAll")}
|
||||
</Menu.Item>
|
||||
</Menu.Content>
|
||||
</Menu.Portal>
|
||||
</Menu>
|
||||
</div>
|
||||
)}
|
||||
</Show>
|
||||
</h3>
|
||||
<Show when={props.expanded}>
|
||||
<div class="provider-model-group-models">{props.children}</div>
|
||||
</Show>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -6,14 +6,13 @@ import { useDialog } from "@opencode/ui/context/dialog"
|
||||
import { popularProviders } from "@/providers/catalog/providers"
|
||||
import { Button } from "@opencode/ui/button"
|
||||
import { Badge } from "@opencode/ui/badge"
|
||||
import { Dialog, DialogBody, DialogHeader, DialogTitle } from "@opencode/ui/dialog"
|
||||
import { Dialog, DialogBody, DialogHeader, DialogTitleGroup } from "@opencode/ui/dialog"
|
||||
import { Icon } from "@opencode/ui/icon"
|
||||
import { IconButton } from "@opencode/ui/icon-button"
|
||||
import { ScrollView } from "@opencode/ui/scroll-view"
|
||||
import { Tooltip } from "@opencode/ui/tooltip"
|
||||
import { Menu } from "@opencode/ui/menu"
|
||||
import { TextInput } from "@opencode/ui/text-input"
|
||||
import { ProviderIcon } from "@opencode/ui/provider-icon"
|
||||
import { ModelTooltip } from "./tooltip"
|
||||
import { useLanguage } from "@/runtime/i18n/language"
|
||||
import { decode64 } from "@/runtime/persistence/base64"
|
||||
@@ -22,6 +21,7 @@ import { createMenuDismissController } from "@/shell/commands/menu-dismiss"
|
||||
import { createEventListener } from "@solid-primitives/event-listener"
|
||||
import { matchesModelSearch } from "./search"
|
||||
import { SettingsList } from "@/settings/list"
|
||||
import { CONSOLE_GROUP_KEY, consoleModelGroup, ProviderModelSections } from "@/providers/models/provider-group"
|
||||
import "@/settings/settings.css"
|
||||
|
||||
const isFree = (provider: string, cost: { input: number } | undefined) =>
|
||||
@@ -62,9 +62,14 @@ const ModelList: Component<{
|
||||
collapsed: {} as Record<string, boolean>,
|
||||
})
|
||||
const models = createMemo(() => controller.models(store.search))
|
||||
const groups = createMemo(() => controller.groups(models()))
|
||||
const modelGroups = createMemo(() => controller.groups(models()))
|
||||
const managed = createMemo(() => consoleModelGroup(controller.all()))
|
||||
const expanded = (provider: string) => store.search.length > 0 || !store.collapsed[provider]
|
||||
const visibleModels = () => models().filter((item) => expanded(item.provider.id))
|
||||
const managedIDs = createMemo(() => new Set(managed()?.providers.map((provider) => provider.id) ?? []))
|
||||
const visibleModels = () =>
|
||||
models().filter(
|
||||
(item) => expanded(item.provider.id) && (!managedIDs().has(item.provider.id) || expanded(CONSOLE_GROUP_KEY)),
|
||||
)
|
||||
let scrollRef: HTMLDivElement | undefined
|
||||
|
||||
const setSearch = (value: string) => {
|
||||
@@ -88,6 +93,53 @@ const ModelList: Component<{
|
||||
if (item) controller.select(item)
|
||||
}
|
||||
|
||||
function ModelRows(props: { items: ModelItem[] }) {
|
||||
return (
|
||||
<SettingsList variant="catalog">
|
||||
<For each={props.items}>
|
||||
{(item) => (
|
||||
<button
|
||||
type="button"
|
||||
data-component="settings-row"
|
||||
data-option-key={modelKey(item)}
|
||||
class="-mx-4 w-[calc(100%+32px)] px-4 text-start first:rounded-t-lg last:rounded-b-lg hover:bg-v2-overlay-simple-overlay-hover focus-visible:bg-v2-overlay-simple-overlay-hover focus-visible:outline-none"
|
||||
classList={{ "bg-v2-overlay-simple-overlay-hover": store.active === modelKey(item) }}
|
||||
onMouseEnter={() => setStore("active", modelKey(item))}
|
||||
onMouseLeave={() => setStore("active", "")}
|
||||
onClick={() => controller.select(item)}
|
||||
>
|
||||
<div data-slot="settings-row-copy">
|
||||
<div data-slot="settings-row-title" class="flex items-center gap-2">
|
||||
<Tooltip
|
||||
placement="right-start"
|
||||
gutter={12}
|
||||
openDelay={0}
|
||||
value={
|
||||
<ModelTooltip model={item} latest={item.latest} free={isFree(item.provider.id, item.cost)} v2 />
|
||||
}
|
||||
>
|
||||
<span class="min-w-0 truncate">{item.name}</span>
|
||||
</Tooltip>
|
||||
<Show when={isFree(item.provider.id, item.cost)}>
|
||||
<Badge class="shrink-0">{language.t("model.tag.free")}</Badge>
|
||||
</Show>
|
||||
<Show when={item.latest}>
|
||||
<Badge class="shrink-0">{language.t("model.tag.latest")}</Badge>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
<div data-slot="settings-row-control" class="size-4">
|
||||
<Show when={controller.current() === modelKey(item)}>
|
||||
<Icon name="check" size="small" class="shrink-0 text-v2-icon-icon-base" />
|
||||
</Show>
|
||||
</div>
|
||||
</button>
|
||||
)}
|
||||
</For>
|
||||
</SettingsList>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="flex min-h-0 flex-1 flex-col">
|
||||
<div class="shrink-0 px-4 pt-px pb-3">
|
||||
@@ -137,88 +189,19 @@ const ModelList: Component<{
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative min-h-0 flex-1">
|
||||
<div ref={(element) => (scrollRef = element)} class="settings-panel settings-models h-full px-4 pt-4 pb-4">
|
||||
<div ref={(element) => (scrollRef = element)} class="settings-panel settings-models h-full px-4 pt-1 pb-4">
|
||||
<Show
|
||||
when={models().length > 0}
|
||||
fallback={<div class="settings-models-status">{language.t("dialog.model.empty")}</div>}
|
||||
>
|
||||
<For each={groups()}>
|
||||
{(group) => {
|
||||
const searching = () => store.search.length > 0
|
||||
const open = () => expanded(group.category)
|
||||
|
||||
return (
|
||||
<section class="settings-section" data-expanded={open() ? "" : undefined}>
|
||||
<h3 class="settings-models-group-header">
|
||||
<button
|
||||
type="button"
|
||||
class="settings-models-group-trigger"
|
||||
aria-expanded={open()}
|
||||
disabled={searching()}
|
||||
onClick={() => setStore("collapsed", group.category, open())}
|
||||
>
|
||||
<span class="settings-models-group-chevron">
|
||||
<Icon name="chevron-down" size="small" classList={{ "-rotate-90 rtl:rotate-90": !open() }} />
|
||||
</span>
|
||||
<span class="settings-models-group-label">
|
||||
<ProviderIcon id={group.category} width={16} height={16} class="shrink-0" />
|
||||
<span class="settings-models-group-title">{group.items[0].provider.name}</span>
|
||||
</span>
|
||||
</button>
|
||||
</h3>
|
||||
<Show when={open()}>
|
||||
<SettingsList variant="catalog">
|
||||
<For each={group.items}>
|
||||
{(item) => (
|
||||
<button
|
||||
type="button"
|
||||
data-component="settings-row"
|
||||
data-option-key={modelKey(item)}
|
||||
class="-mx-4 w-[calc(100%+32px)] px-4 text-start first:rounded-t-lg last:rounded-b-lg hover:bg-v2-overlay-simple-overlay-hover focus-visible:bg-v2-overlay-simple-overlay-hover focus-visible:outline-none"
|
||||
classList={{ "bg-v2-overlay-simple-overlay-hover": store.active === modelKey(item) }}
|
||||
onMouseEnter={() => setStore("active", modelKey(item))}
|
||||
onMouseLeave={() => setStore("active", "")}
|
||||
onClick={() => controller.select(item)}
|
||||
>
|
||||
<div data-slot="settings-row-copy">
|
||||
<div data-slot="settings-row-title" class="flex items-center gap-2">
|
||||
<Tooltip
|
||||
placement="right-start"
|
||||
gutter={12}
|
||||
openDelay={0}
|
||||
value={
|
||||
<ModelTooltip
|
||||
model={item}
|
||||
latest={item.latest}
|
||||
free={isFree(item.provider.id, item.cost)}
|
||||
v2
|
||||
/>
|
||||
}
|
||||
>
|
||||
<span class="min-w-0 truncate">{item.name}</span>
|
||||
</Tooltip>
|
||||
<Show when={isFree(item.provider.id, item.cost)}>
|
||||
<Badge class="shrink-0">{language.t("model.tag.free")}</Badge>
|
||||
</Show>
|
||||
<Show when={item.latest}>
|
||||
<Badge class="shrink-0">{language.t("model.tag.latest")}</Badge>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
<div data-slot="settings-row-control" class="size-4">
|
||||
<Show when={controller.current() === modelKey(item)}>
|
||||
<Icon name="check" size="small" class="shrink-0 text-v2-icon-icon-base" />
|
||||
</Show>
|
||||
</div>
|
||||
</button>
|
||||
)}
|
||||
</For>
|
||||
</SettingsList>
|
||||
</Show>
|
||||
</section>
|
||||
)
|
||||
}}
|
||||
</For>
|
||||
<ProviderModelSections
|
||||
groups={modelGroups()}
|
||||
managed={managed()}
|
||||
expanded={expanded}
|
||||
disabled={store.search.length > 0}
|
||||
onExpandedChange={(key, value) => setStore("collapsed", key, !value)}
|
||||
rows={(items) => <ModelRows items={items} />}
|
||||
/>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
@@ -272,6 +255,7 @@ function createModelSelectorController(input: {
|
||||
)
|
||||
|
||||
return {
|
||||
all: () => model.list().filter((item) => (input.provider() ? item.provider.id === input.provider() : true)),
|
||||
models: (search: string) => {
|
||||
const query = search.trim()
|
||||
const filtered = query
|
||||
@@ -548,7 +532,7 @@ export const DialogSelectModel: Component<{ provider?: string; model?: ModelStat
|
||||
return (
|
||||
<Dialog size="large" variant="settings">
|
||||
<DialogHeader hideClose closeLabel={language.t("common.close")}>
|
||||
<DialogTitle>{language.t("dialog.model.select.title")}</DialogTitle>
|
||||
<DialogTitleGroup title={language.t("dialog.model.select.title")} />
|
||||
<Button icon="plus" onClick={provider}>
|
||||
{language.t("command.provider.connect")}
|
||||
</Button>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DialogBody, DialogHeader, DialogTitle, Dialog } from "@opencode/ui/dialog"
|
||||
import { Badge } from "@opencode/ui/badge"
|
||||
import { Icon } from "@opencode/ui/icon"
|
||||
import { ProviderIcon } from "@opencode/ui/provider-icon"
|
||||
import { ProviderModelIcon } from "@/providers/models/provider-group"
|
||||
import { Tooltip } from "@opencode/ui/tooltip"
|
||||
import { useDialog } from "@opencode/ui/context/dialog"
|
||||
import { useTheme } from "@opencode/ui/theme"
|
||||
@@ -31,6 +31,8 @@ export const DialogSelectModelUnpaid: Component<{ model?: ModelState }> = (props
|
||||
})
|
||||
const isFree = (item: ReturnType<ModelState["list"]>[number]) =>
|
||||
item.provider.id === "opencode" && (!item.cost || item.cost.input === 0)
|
||||
const providerName = (provider: { id: string; name: string }) =>
|
||||
provider.id === "opencode" ? language.t("provider.connect.opencode.name") : provider.name
|
||||
const freeModels = createMemo(() => model.list().filter(isFree))
|
||||
|
||||
const openProviders = (provider?: string) => {
|
||||
@@ -144,9 +146,12 @@ export const DialogSelectModelUnpaid: Component<{ model?: ModelState }> = (props
|
||||
}}
|
||||
onClick={() => openProviders(provider.id)}
|
||||
>
|
||||
<ProviderIcon id={provider.id} class="mt-0.5 size-4 shrink-0 text-v2-icon-icon-base" />
|
||||
<ProviderModelIcon
|
||||
provider={{ id: provider.id, name: providerName(provider) }}
|
||||
class="mt-0.5 shrink-0 text-v2-icon-icon-base"
|
||||
/>
|
||||
<span class="flex min-w-0 flex-col">
|
||||
<span class="truncate">{provider.name}</span>
|
||||
<span class="truncate">{providerName(provider)}</span>
|
||||
<Show when={provider.id === "opencode" || provider.id === "opencode-go"}>
|
||||
<span class="truncate font-[440] text-v2-text-text-muted">
|
||||
{language.t(
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
export function OpenCodeLogo(props: { class?: string }) {
|
||||
return (
|
||||
<svg
|
||||
data-component="opencode-logo"
|
||||
aria-hidden="true"
|
||||
class={props.class}
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g transform="translate(1.2 1.2) scale(0.85)">
|
||||
<path opacity="0.2" d="M11.1999 12.8H4.79993V6.40002H11.1999V12.8Z" fill="currentColor" />
|
||||
<path d="M11.2 3.2H4.79998V12.8H11.2V3.2ZM14.4 16H1.59998V0H14.4V16Z" fill="currentColor" />
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@@ -1068,4 +1068,439 @@ export const dict = {
|
||||
"workspace.reset.archived.many": "{{count}} ክፍለ-ጊዜዎች በማህደር ይቀመጣሉ።",
|
||||
"workspace.reset.note": "ይህ workspaceን ከነባሪው ቅርንጫፍ ጋር እንዲመሳሰል ዳግም ያስጀምረዋል።",
|
||||
"dialog.usageExceeded.dontShowAgain": "እንደገና አታሳይ",
|
||||
"toast.migration.failed.title": "የውሂብ ፍልሰት አልተሳካም",
|
||||
"command.session.background": "ወደ ዳራ አንቀሳቅስ",
|
||||
"session.timeline.notice.finished": "{{actor}} ጨርሷል",
|
||||
"session.timeline.notice.failed": "{{actor}} አልተሳካም",
|
||||
"session.timeline.notice.cancelled": "{{actor}} ተሰርዟል",
|
||||
"settings.tab.preferences": "ምርጫዎች",
|
||||
"settings.tab.notifications": "ማሳወቂያዎች",
|
||||
"settings.tab.projects": "ፕሮጀክቶች",
|
||||
"settings.tab.extensions": "ቅጥያዎች",
|
||||
"settings.preferences.description": "ምርጫዎችን፣ ገጽታን እና ነባሪ ባህሪን ያብጁ",
|
||||
"settings.appearance.description": "ገጽታን እና ቅርጸ ቁምፊዎችን ያብጁ",
|
||||
"settings.notifications.description": "ማሳወቂያዎች መቼ እንደሚደርሱዎት እና ድምፆች መቼ እንደሚሰሙ ይምረጡ",
|
||||
"settings.shortcuts.description": "ለተለመዱ ድርጊቶች አቋራጮችን ያብጁ",
|
||||
"settings.servers.description": "የአገልጋይ ግንኙነቶችን ያስተዳድሩ",
|
||||
"settings.projects.title": "ፕሮጀክቶች",
|
||||
"settings.projects.description": "በዚህ አገልጋይ ላይ የፕሮጀክት ቅንብሮችን ያስተዳድሩ",
|
||||
"settings.projects.empty": "ምንም ፕሮጀክት አልተገኘም",
|
||||
"settings.projects.server.all": "ሁሉም አገልጋዮች",
|
||||
"settings.mcps.description": "የModel Context Protocol (MCP) አገልጋዮችን እና መሣሪያዎችን ያስተዳድሩ",
|
||||
"settings.extensions.description": "በዚህ አገልጋይ ላይ የሚገኙ ቅጥያዎችን ያስተዳድሩ",
|
||||
"settings.extensions.tab.mcps": "MCPs",
|
||||
"settings.extensions.tab.skills": "ችሎታዎች",
|
||||
"settings.extensions.availableAll": "ለሁሉም ፕሮጀክቶች ይገኛል",
|
||||
"settings.extensions.manageConfig": "በopencode.json ውስጥ ያስተዳድሩ",
|
||||
"settings.extensions.addSkills": "ችሎታዎችን እንዴት ማከል እንደሚቻል",
|
||||
"dialog.server.authenticate.title": "ማንነትን ያረጋግጡ",
|
||||
"project.settings.general.description": "የፕሮጀክት ስምን እና ገጽታን ያስተዳድሩ",
|
||||
"project.settings.scripts": "ስክሪፕቶች",
|
||||
"project.settings.scripts.description": "ለዚህ ፕሮጀክት ስክሪፕቶችን ያዋቅሩ",
|
||||
"project.settings.extensions.description": "ለዚህ ፕሮጀክት የሚገኙ ቅጥያዎችን ይመልከቱ",
|
||||
"project.settings.extensions.tab.lsps": "LSPs",
|
||||
"project.settings.extensions.added": "ወደዚህ ፕሮጀክት ታክሏል",
|
||||
"project.settings.extensions.shared": "ከሁሉም ፕሮጀክቶች ጋር የተጋራ",
|
||||
"project.settings.extensions.lsp.detected": "የተገኙ የቋንቋ አገልጋዮች",
|
||||
"project.settings.extensions.lsp.description": "ከፋይል ዓይነቶች በራስ-ሰር የተገኘ",
|
||||
"project.settings.extensions.setupRequired": "ማዋቀር ያስፈልጋል",
|
||||
"settings.general.section.general": "አጠቃላይ",
|
||||
"common.viewAll": "ሁሉንም ይመልከቱ",
|
||||
"session.new.workspace.local.tooltip": "የአሁኑን checkout ይጠቀሙ",
|
||||
"session.new.workspace.new.tooltip": "የተለየ checkout ይፍጠሩ",
|
||||
"session.new.workspace.fromBranch": "ከ{{branch}}",
|
||||
"session.new.workspace.trigger.tooltip": "ክፍለ ጊዜው የት እንደሚሄድ ይምረጡ",
|
||||
"session.new.workspace.search.placeholder": "Workspace-ዎችን ይፈልጉ",
|
||||
"settings.tab.workspaces": "Workspace-ዎች",
|
||||
"settings.workspaces.filter.all": "ሁሉም ፕሮጀክቶች",
|
||||
"settings.workspaces.empty": "ምንም workspace የለም",
|
||||
"settings.workspaces.count.one": "{{count}} workspace",
|
||||
"settings.workspaces.count.other": "{{count}} workspace-ዎች",
|
||||
"settings.workspaces.sessions.one": "በ{{project}} ውስጥ {{count}} ክፍለ ጊዜ",
|
||||
"settings.workspaces.sessions.other": "በ{{project}} ውስጥ {{count}} ክፍለ ጊዜዎች",
|
||||
"settings.workspaces.lastActiveSession": "የመጨረሻው ንቁ ክፍለ ጊዜ",
|
||||
"settings.workspaces.deleteAll": "ሁሉንም workspace-ዎች ሰርዝ",
|
||||
"settings.workspaces.delete.warning": "የworkspace ማውጫው እና ቅርንጫፉ፣ ከዚህ በታች የሚታዩ ያልተዋሃዱ ለውጦችን ጨምሮ፣ እስከመጨረሻው ይወገዳሉ።",
|
||||
"settings.workspaces.deleteAll.warning": "ያልተዋሃዱ ለውጦች፣ የተገናኙ ክፍለ ጊዜዎች ወይም ንቁ አካባቢዎች ያሏቸው የሥራ ዛፎች ይቀመጣሉ።",
|
||||
"settings.workspaces.delete.blocked.active": "ንቁው workspace ሊሰረዝ አይችልም።",
|
||||
"settings.workspaces.delete.blocked.linked": "የተገናኙ ክፍለ ጊዜዎች ይቀራሉ፣ ነገር ግን የሥራ ማውጫቸው እስከመጨረሻው ይወገዳል።",
|
||||
"settings.workspaces.default.title": "ነባሪ አካባቢ",
|
||||
"settings.workspaces.default.description": "አዲስ ክፍለ ጊዜዎች የት እንደሚጀምሩ ይምረጡ",
|
||||
"settings.workspaces.default.lastUsed": "በእያንዳንዱ ፕሮጀክት ለመጨረሻ ጊዜ ያገለገለ",
|
||||
"settings.workspaces.default.local": "አካባቢያዊ ማውጫ",
|
||||
"settings.workspaces.default.new": "አዲስ workspace",
|
||||
"workspace.move.title": "ወደ workspace አንቀሳቅስ",
|
||||
"workspace.move.menu.title": "ክፍለ ጊዜን አንቀሳቅስ ወደ",
|
||||
"workspace.move.failed": "ክፍለ ጊዜን ማንቀሳቀስ አልተሳካም",
|
||||
"workspace.lifecycle.creating": "Workspace በመፍጠር ላይ",
|
||||
"workspace.lifecycle.created": "Workspace ተፈጥሯል",
|
||||
"workspace.lifecycle.starting": "ክፍለ ጊዜ በመጀመር ላይ",
|
||||
"workspace.onboarding.title": "ክፍለ ጊዜዎችን በworkspace-ዎች ለዩ",
|
||||
"workspace.onboarding.description": "እያንዳንዱ የራሱ checkout ስላለው በአካባቢያዊ ማከማቻዎ ላይ ምንም ነገር ጣልቃ አይገባም",
|
||||
"workspace.lifecycle.moving": "ወደ workspace በማንቀሳቀስ ላይ",
|
||||
"workspace.lifecycle.set": "Workspace ተዘጋጅቷል",
|
||||
"session.summary.title": "የክፍለ ጊዜ ዝርዝሮች",
|
||||
"session.summary.noBranch": "ቅርንጫፍ የለም",
|
||||
"session.summary.basedOn": "በ{{branch}} ላይ የተመሰረተ",
|
||||
"provider.disconnect.toast.noCredentials.description": "ለ{{provider}} ሊወገድ የሚችል የማረጋገጫ መረጃ አልተገኘም።",
|
||||
"provider.disconnect.toast.failed.description": "{{provider}}ን ማቋረጥ አልተሳካም።",
|
||||
"desktop.menu.installCli": "CLIን ጫን...",
|
||||
"desktop.cli.installed.title": "CLI ተጭኗል",
|
||||
"desktop.cli.installed.message": "CLI በ{{path}} ላይ ተጭኗል\n\nየ'opencode2' ትዕዛዝን ለመጠቀም ተርሚናልዎን ዳግም ያስጀምሩ።",
|
||||
"desktop.cli.failed.title": "መጫን አልተሳካም",
|
||||
"desktop.cli.failed.message": "CLIን መጫን አልተሳካም፦ {{error}}",
|
||||
"command.project.copyID": "የፕሮጀክት IDን ቅዳ",
|
||||
"command.session.copyID": "የክፍለ ጊዜ IDን ቅዳ",
|
||||
"server.row.incompatible":
|
||||
"ይህ አገልጋይ OpenCode {{version}}ን እያስኬደ ነው፣ ይህም ከዚህ መተግበሪያ ጋር ተኳሃኝ አይደለም። ለመቀጠል ወደ OpenCode V2 ያሻሽሉት።",
|
||||
"toast.session.copyID.failed.title": "የክፍለ ጊዜ IDን መቅዳት አልተሳካም",
|
||||
"toast.session.copyID.failed.description": "የክፍለ ጊዜ IDን ሲቀዳ ስህተት ተፈጥሯል",
|
||||
"toast.project.copyID.failed.title": "የፕሮጀክት IDን መቅዳት አልተሳካም",
|
||||
"toast.project.copyID.failed.description": "የፕሮጀክት IDን ሲቀዳ ስህተት ተፈጥሯል",
|
||||
"error.page.title.status": "የአገልጋይ ጥያቄ አልተሳካም",
|
||||
"error.page.description.status": "አገልጋዩ የHTTP {{status}} ምላሽ መልሷል።",
|
||||
"error.page.action.reload": "ዳግም ጫን",
|
||||
"session.error.incompatible": "ይህ የአገልጋይ ስሪት አይደገፍም",
|
||||
"session.error.incompatible.description":
|
||||
"{{server}} OpenCode {{version}}ን እያስኬደ ነው፣ ይህም ከዚህ መተግበሪያ ጋር ተኳሃኝ አይደለም። ለመቀጠል አገልጋዩን ወደ OpenCode V2 ያሻሽሉት።",
|
||||
"session.background.moveInline": "እየሄደ ያለውን ሥራ ወደ ዳራ ለማንቀሳቀስ {{keybind}}ን ይጫኑ",
|
||||
"session.background.running": "ሥራ በዳራ እየሄደ ነው",
|
||||
"session.background.runningCount.one": "{{count}} ንጥል በዳራ እየሄደ ነው",
|
||||
"session.background.runningCount.other": "{{count}} ንጥሎች በዳራ እየሄዱ ነው",
|
||||
"settings.general.row.terminalPlacement.title": "የተርሚናል አቀማመጥ",
|
||||
"settings.general.row.terminalPlacement.description": "ተርሚናሉ በክፍለ ጊዜዎች ውስጥ የት እንደሚከፈት ይምረጡ",
|
||||
"settings.general.row.terminalPlacement.side": "ጎን",
|
||||
"settings.general.row.terminalPlacement.bottom": "ታች",
|
||||
"session.location.unavailable": "የክፍለ ጊዜው ቦታ አይገኝም",
|
||||
"session.location.description": "ይህን ክፍለ ጊዜ ለመቀጠል ሌላ ማውጫ ይምረጡ።",
|
||||
"session.location.choose": "ማውጫ ይምረጡ",
|
||||
"session.location.worktree": "worktree ይምረጡ",
|
||||
"session.location.worktreesFailed": "worktree-ዎችን መጫን አልተሳካም",
|
||||
"session.location.moving": "ክፍለ ጊዜው እየተንቀሳቀሰ ነው…",
|
||||
"dialog.server.menu.hide": "ከፕሮጀክት ዝርዝር ደብቅ",
|
||||
"dialog.server.menu.show": "በፕሮጀክት ዝርዝር ውስጥ አሳይ",
|
||||
"session.queue.count.one": "{{count}} ወረፋ ላይ",
|
||||
"session.queue.count.other": "{{count}} ወረፋ ላይ",
|
||||
"session.queue.steer": "አቅጣጫ ስጥ",
|
||||
"session.queue.send": "ላክ",
|
||||
"session.queue.steerTooltip": "ሳያቋርጡ ይላኩ",
|
||||
"session.queue.remove": "አስወግድ",
|
||||
"session.queue.reorder": "ወረፋ ላይ ያለውን ፕሮምፕት እንደገና ደርድር",
|
||||
"session.new.worktree.creating": "worktree በመፍጠር ላይ",
|
||||
"settings.backToApp": "ወደ መተግበሪያው ተመለስ",
|
||||
"settings.appearance.section.experimental": "ሙከራዊ",
|
||||
"settings.appearance.row.tabs.title": "ትሮች",
|
||||
"settings.appearance.row.tabs.description": "የክፍለ ጊዜ ትሮች እንዴት እንደሚደረደሩ ይምረጡ",
|
||||
"settings.appearance.row.tabs.horizontal": "አግድም",
|
||||
"settings.appearance.row.tabs.vertical": "ቁመታዊ",
|
||||
"settings.general.row.followUpBehavior.title": "የተከታይ መልዕክት ባህሪ",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"ተከታይ መልዕክቶችን ወረፋ ላይ ለማስቀመጥ ወይም የአሁኑን ዙር ለመምራት ይምረጡ። ለመቀየር {{keybind}} ይጠቀሙ።",
|
||||
"settings.general.row.followUpBehavior.queue": "ወረፋ",
|
||||
"settings.general.row.followUpBehavior.steer": "አቅጣጫ ስጥ",
|
||||
"settings.general.row.reasoningMode.title": "የሞዴል ማመዛዘን",
|
||||
"settings.general.row.reasoningMode.description": "የሞዴሉ ማመዛዘን በጊዜ መስመሩ ላይ እንዴት እንደሚታይ ይምረጡ",
|
||||
"settings.general.row.reasoningMode.hidden": "የተደበቀ",
|
||||
"settings.general.row.reasoningMode.compact": "የታመቀ",
|
||||
"settings.general.row.reasoningMode.full": "ሙሉ",
|
||||
"session.new.workspace.createFrom": "ከዚህ ፍጠር",
|
||||
"session.new.workspace.branch.search.placeholder": "ቅርንጫፎችን ፈልግ",
|
||||
"toast.migration.progress.clearingOldEvents": "የቆዩ ክስተቶችን በማጽዳት ላይ",
|
||||
"toast.migration.progress.migratingSessions": "ክፍለ ጊዜዎችን በማዛወር ላይ",
|
||||
"session.new.workspace.existingLabel": "Git worktree",
|
||||
"desktop.onboarding.defaultProject": "ነባሪ ፕሮጀክት",
|
||||
"home.projects.all": "ሁሉም ፕሮጀክቶች",
|
||||
"session.tab.files": "ፋይሎች",
|
||||
"session.files.openTabs": "ክፍት ፋይሎች",
|
||||
"session.tab.usage": "አጠቃቀም",
|
||||
"session.view.select": "የክፍለ ጊዜ እይታ",
|
||||
"session.background.moveTasks": "{{tasks}}ን ወደ ዳራ አንቀሳቅስ",
|
||||
"session.background.moveRunning": "ወደ ዳራ አንቀሳቅስ",
|
||||
"session.background.inBackground": "{{tasks}} በዳራ እየሰሩ ነው",
|
||||
"session.background.tasksRunning.one": "{{count}} የዳራ ተግባር እየሰራ ነው",
|
||||
"session.background.tasksRunning.other": "{{count}} የዳራ ተግባራት እየሰሩ ናቸው",
|
||||
"session.background.combine": "{{first}} እና {{second}}",
|
||||
"session.background.shell.one": "{{count}} shell",
|
||||
"session.background.shell.other": "{{count}} shell-ዎች",
|
||||
"session.background.subagent.one": "{{count}} ንዑስ ወኪል",
|
||||
"session.background.subagent.other": "{{count}} ንዑስ ወኪሎች",
|
||||
"session.timeline.working": "በመስራት ላይ",
|
||||
"session.review.wrapLines": "መስመሮችን አጠፍ",
|
||||
"session.websearch.title": "የሶስተኛ ወገን ድር ፍለጋ",
|
||||
"session.websearch.description": "ወኪሎች ድሩን ለመፈለግ የሚጠቀሙበትን የፍለጋ አቅራቢ ይምረጡ",
|
||||
"session.websearch.provider": "የፍለጋ አቅራቢ",
|
||||
"session.websearch.any": "ማንኛውም",
|
||||
"session.websearch.disable": "ፍለጋን አትጠቀም",
|
||||
"session.websearch.enable": "አንቃ",
|
||||
"session.websearch.loadFailed": "የፍለጋ አቅራቢዎችን መጫን አልተቻለም።",
|
||||
"session.websearch.empty": "ምንም የፍለጋ አቅራቢ የለም።",
|
||||
"session.websearch.failed": "ምርጫዎን ማስቀመጥ አልተቻለም። እንደገና ይሞክሩ።",
|
||||
"session.websearch.retry": "እንደገና ሞክር",
|
||||
"session.new.worktree.draftPlaceholder": "worktree እየተዘጋጀ ሳለ ተከታይ መልዕክት ያርቅቁ…",
|
||||
"session.search.placeholder": "ፈልግ...",
|
||||
"session.search.noResults": "ምንም ተዛማጅ የለም",
|
||||
"titlebar.tabs": "ትሮች",
|
||||
"titlebar.channel.local": "አካባቢያዊ",
|
||||
"titlebar.channel.dev": "ልማት",
|
||||
"titlebar.channel.beta": "ቤታ",
|
||||
"titlebar.toggleDebugTools": "የማረሚያ መሳሪያዎችን ቀይር",
|
||||
"settings.tab.experimental": "ሙከራዊ",
|
||||
"settings.experimental.description": "ሙከራዊ ባህሪያትን ይሞክሩ",
|
||||
"settings.tab.about": "ስለ",
|
||||
"settings.about.version": "ስሪት {{version}}",
|
||||
"settings.about.devVersion": "ልማት",
|
||||
"settings.about.license": "በMIT ፈቃድ የተለቀቀ",
|
||||
"settings.about.writtenBy": "የተጻፈው በ",
|
||||
"settings.about.illustratedBy": "ምስሎች በ",
|
||||
"settings.about.and": "እና",
|
||||
"settings.about.otherContributor.one": "{{count}} ሌላ",
|
||||
"settings.about.otherContributor.other": "{{count}} ሌሎች",
|
||||
"settings.about.firstPublished": "መጀመሪያ የታተመው በሚዙሪ፣ አሜሪካ",
|
||||
"settings.about.firstIllustrated": "መጀመሪያ ምስል የተሰራለት በለንደን፣ እንግሊዝ",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode፣ ክፍት ምንጭ የኮድ ወኪል",
|
||||
"settings.about.trademark": "OpenCode የAnomaly Innovations, Inc. የተመዘገበ የንግድ ምልክት ነው።",
|
||||
"settings.about.typeset": "በInter እና IBM Plex Mono ተሰድሯል",
|
||||
"settings.about.tagline": "ያለ እርስዎ AI ምርጥ ሶፍትዌር መገንባት አይችልም",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "ፕሮጀክት አርትዕ",
|
||||
"settings.timeline.title": "የጊዜ መስመር",
|
||||
"settings.timeline.detail": "የጊዜ መስመር ዝርዝር",
|
||||
"settings.timeline.description": "በጊዜ መስመሩ ላይ ምን ያህል እንቅስቃሴ እንደሚታይ ይምረጡ። መልዕክቶች ይታያሉ።",
|
||||
"settings.timeline.preset.everything": "ሁሉም ነገር",
|
||||
"settings.timeline.preset.detailed": "ዝርዝር",
|
||||
"settings.timeline.preset.compact": "የታመቀ",
|
||||
"settings.timeline.preset.quiet": "ጸጥ ያለ",
|
||||
"settings.timeline.preset.text-only": "ጽሑፍ ብቻ",
|
||||
"settings.timeline.description.everything": "ሁሉንም እንቅስቃሴ ለየብቻ አሳይ። የshell ውጤትን፣ አርትዖቶችን እና ማመዛዘንን ዘርጋ።",
|
||||
"settings.timeline.description.detailed":
|
||||
"የshell ውጤትን እና አርትዖቶችን ዘርጋ። ንዑስ ወኪሎችን ለየብቻ አሳይ እና ሌላ እንቅስቃሴን በ«ጥቅም ላይ የዋለ» ውስጥ ሰብስብ።",
|
||||
"settings.timeline.description.compact": "ሁሉንም እንቅስቃሴ ዝርዝሮቹ ተደብቀው በ«ጥቅም ላይ የዋለ» ውስጥ ሰብስብ።",
|
||||
"settings.timeline.description.quiet": "አርትዖቶችን እና ንዑስ ወኪሎችን በ«ጥቅም ላይ የዋለ» ውስጥ ሰብስብ። ሌላ እንቅስቃሴን ደብቅ።",
|
||||
"settings.timeline.description.text-only": "ሁሉንም እንቅስቃሴ ደብቅ። መልዕክቶችን ብቻ አሳይ።",
|
||||
"settings.timeline.description.custom": "ለእያንዳንዱ የእንቅስቃሴ ምድብ የመረጡትን አቀማመጥ እና ዝርዝር ይጠቀሙ።",
|
||||
"settings.timeline.custom": "ብጁ",
|
||||
"settings.timeline.advanced": "የላቀ",
|
||||
"settings.timeline.advanced.description": "ለእያንዳንዱ የእንቅስቃሴ ምድብ አቀማመጥ እና ዝርዝር ያዘጋጁ።",
|
||||
"settings.timeline.category.shell": "Shell",
|
||||
"settings.timeline.category.edit": "አርትዖቶች",
|
||||
"settings.timeline.category.thinking": "ማሰብ",
|
||||
"settings.timeline.category.subagents": "ንዑስ ወኪሎች",
|
||||
"settings.timeline.category.notices": "ማሳወቂያዎች",
|
||||
"settings.timeline.category.tools": "ሌሎች መሳሪያዎች",
|
||||
"settings.general.row.mobileDiffWrap.description": "በአግድም ከማሸብለል ይልቅ በሞባይል diff ውስጥ ረጅም መስመሮችን አጠፍ",
|
||||
"provider.connect.error.unsupportedFields": "ይህ የማረጋገጫ ቅጽ የማይደገፉ መስኮችን ይዟል",
|
||||
"session.review.filesChangedCount.one": "{{count}} ፋይል ተቀይሯል",
|
||||
"session.review.filesChangedCount.other": "{{count}} ፋይሎች ተቀይረዋል",
|
||||
"settings.about.writtenByNames": "የተጻፈው በ{{names}}",
|
||||
"settings.about.illustratedByNames": "ምስሎች በ{{names}}",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline": "ከ{{host}} ጋር አልተገናኘም። ረቂቅዎ ተጠብቆ ይቆያል; የርቀት ስራ አሁንም እየሰራ ሊሆን ይችላል።",
|
||||
"ssh.placeholder": "ssh user@example.com",
|
||||
"ssh.add": "የSSH አገልጋይ ያክሉ",
|
||||
"ssh.server.menu.label": "SSH አገልጋይ",
|
||||
"ssh.target": "አስተናጋጅ ወይም የSSH ትዕዛዝ",
|
||||
"ssh.connect": "መገናኘት",
|
||||
"ssh.connectTo": "ከ{{host}} ጋር ይገናኙ",
|
||||
"ssh.authenticate": "SSH ማረጋገጫ",
|
||||
"ssh.action.authenticate": "ያረጋግጡ",
|
||||
"ssh.session.disconnected": "SSH ግንኙነት የቦዘነ",
|
||||
"ssh.session.connecting": "ከSSH አገልጋይ ጋር በመገናኘት ላይ",
|
||||
"ssh.session.reconnectDescription": "ይህን ክፍለ ጊዜ ለማየትና ሥራዎን ለመቀጠል እንደገና ይገናኙ። የርቀት ክፍለ ጊዜዎ ተጠብቆ ይቆያል።",
|
||||
"ssh.session.reconnect": "እንደገና ይገናኙ",
|
||||
"ssh.authenticationRequired": "ለ{{host}} ማረጋገጫ ያስፈልጋል",
|
||||
"ssh.trust": "ይመኑ እና ይገናኙ",
|
||||
"ssh.continue": "ቀጥል",
|
||||
"ssh.retry": "እንደገና ሞክር",
|
||||
"ssh.update": "ያዘምኑ እና እንደገና ያገናኙ",
|
||||
"ssh.openProject": "ክፍት ፕሮጀክት",
|
||||
"ssh.project": "በ{{host}} ላይ ፕሮጀክት ክፈት",
|
||||
"ssh.disconnect": "ግንኙነት አቋርጥ",
|
||||
"ssh.forget": "ግንኙነትን እርሳ",
|
||||
"ssh.stage.disconnected": "ግንኙነቱ ተቋርጧል። የርቀት አገልጋዩ እየሰራ ነው።",
|
||||
"ssh.stage.connecting": "በSSH በመገናኘት ላይ...",
|
||||
"ssh.stage.checking": "የOpenCode በመፈተሽ ላይ...",
|
||||
"ssh.stage.downloading": "አገልጋይ በማውረድ ላይ...",
|
||||
"ssh.stage.uploading": "አገልጋይን በመጫን ላይ...",
|
||||
"ssh.stage.starting": "ከOpenCode ጋር በመገናኘት ላይ...",
|
||||
"ssh.stage.ready": "ተገናኝቷል",
|
||||
"ssh.stage.authentication": "ማረጋገጫ ያስፈልጋል",
|
||||
"ssh.stage.incompatible": "የአገልጋይ ዝመና ያስፈልጋል",
|
||||
"ssh.stage.failed": "ግንኙነት አልተሳካም",
|
||||
"ssh.error.input": "የአስተናጋጅ ወይም የSSH ግንኙነት ትዕዛዝ ያስገቡ። የርቀት ትዕዛዞች እና የማይደገፉ የSSH አማራጮች አይፈቀዱም።",
|
||||
"ssh.error.connection": "የSSH ግንኙነት መመስረት አልተቻለም። የእርስዎን አውታረ መረብ እና የSSH ውቅር ያረጋግጡ።",
|
||||
"ssh.error.platform": "ይህ የርቀት መድረክ አይደገፍም። ራስ-ሰር ማዋቀር በአሁኑ ጊዜ Linux ወይም macOS በ x64 ወይም arm64 ያስፈልገዋል።",
|
||||
"ssh.error.version": "ከመገናኘትዎ በፊት የርቀት አገልግሎቱ ከዚህ የዴስክቶፕ ስሪት ጋር መዛመድ አለበት።",
|
||||
"ssh.error.install": "የርቀት አገልጋዩን መጫን አልተቻለም። ግንኙነትን፣ የዲስክ ቦታን ያረጋግጡ እና ያ ሬንጅ መጫኑን ያረጋግጡ።",
|
||||
"ssh.error.unpublished":
|
||||
"ይህ የዴስክቶፕ ስሪት የታተመ የርቀት አገልጋይ የለውም። ለልማት ግንባታዎች በአስተናጋጁ ላይ V2 ን ይጫኑ እና ያስጀምሩ እና ከዚያ እንደገና ይሞክሩ።",
|
||||
"ssh.error.service": "SSH ተገናኝቷል፣ ነገር ግን የOpenCode አገልጋዩ ዝግጁ አልሆነም።",
|
||||
"ssh.error.host-key": "የአስተናጋጁ ማንነት ሊረጋገጥ አልቻለም። የSSH የታወቁ አስተናጋጆችዎን ከማዘመንዎ በፊት የጣት አሻራውን ያረጋግጡ።",
|
||||
"ssh.error.ssh-missing": "OpenSSH አልተገኘም። የOpenSSH ደንበኛን ይጫኑ እና ssh በPATH ላይ መገኘቱን ያረጋግጡ።",
|
||||
"command.browser.open": "አሳሽ ክፈት",
|
||||
"command.browser.reload": "የአሳሽ ገጽን እንደገና ጫን",
|
||||
"command.session.summary.toggle": "ማጠቃለያ ቀያይር",
|
||||
"common.color.orange": "ብርቱካናማ",
|
||||
"common.color.yellow": "ቢጫ",
|
||||
"common.color.cyan": "ሳይያን",
|
||||
"common.color.green": "አረንጓዴ",
|
||||
"common.color.red": "ቀይ",
|
||||
"common.color.pink": "ሮዝ",
|
||||
"common.color.blue": "ሰማያዊ",
|
||||
"common.color.purple": "ሐምራዊ",
|
||||
"common.color.gray": "ግራጫ",
|
||||
"mcp.auth.interactiveForm": "MCP አገልጋይ {{name}} በይነተገናኝ የማረጋገጫ ቅጽ ያስፈልገዋል",
|
||||
"server.connect.title": "ከአገልጋይ ጋር ይገናኙ",
|
||||
"server.connect.description": "ለመጀመር የአገልጋይ አድራሻዎን እና የይለፍ ቃልዎን ያስገቡ።",
|
||||
"server.connect.button": "መገናኘት",
|
||||
"server.connect.address.invalid": "የሚሰራ የኤችቲቲፒ ወይም የኤችቲቲፒኤስ አገልጋይ አድራሻ ያስገቡ።",
|
||||
"server.connect.failed": "መገናኘት አልተቻለም። የአገልጋዩን አድራሻ እና የይለፍ ቃል ያረጋግጡ እና ከዚያ እንደገና ይሞክሩ።",
|
||||
"server.connect.pair.description": "የግንኙነት ዝርዝሮችዎን ለማግኘት ይህንን ትዕዛዝ በኮምፒተርዎ ላይ ያሂዱ።",
|
||||
"server.connect.scan": "QR ኮድ ይቃኙ",
|
||||
"server.connect.scan.description": "ካሜራዎን opencode pair ወደሚያሳየው QR ኮድ ያነጣጥሩ።",
|
||||
"server.connect.scan.invalid": "ይህ የOpenCode ማጣመሪያ ኮድ አይደለም። opencode pair የሚያሳየውን ኮድ ይቃኙ።",
|
||||
"server.connect.camera": "ማጣመር ካሜራ",
|
||||
"server.connect.camera.starting": "ካሜራ በመክፈት ላይ...",
|
||||
"server.connect.mixedContent": "ከዚህ ኤችቲቲፒኤስ አገልጋይ ጋር ከኤችቲቲፒኤስ ገጽ ጋር መገናኘት አልተቻለም። በምትኩ የኤችቲቲፒኤስ አገልጋይ አድራሻ ይጠቀሙ።",
|
||||
"server.connect.camera.insecure": "QR ቅኝት ይህንን ገጽ በኤችቲቲፒኤስ ወይም በአካባቢያዊ አስተናጋጅ መክፈት ይጠይቃል።",
|
||||
"server.connect.camera.unavailable": "ለዚህ አሳሽ ምንም ካሜራ አይገኝም። የግንኙነት ዝርዝሮችዎን እራስዎ ያስገቡ።",
|
||||
"server.connect.camera.error": "ካሜራውን መክፈት አልተቻለም። የካሜራ መዳረሻ ይፍቀዱ ወይም የግንኙነት ዝርዝሮችዎን እራስዎ ያስገቡ።",
|
||||
"dialog.server.menu.remove": "አስወግድ",
|
||||
"file.error.notFound": "ፋይል አልተገኘም {{name}}",
|
||||
"toast.migration.progress.migratingSessions.current": "ክፍለ ጊዜዎችን በማዛወር ላይ {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "ክፍለ ጊዜዎችን በማዛወር ላይ {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "ውሂብ በማዛወር ላይ",
|
||||
"toast.migration.progress.working.current": "ውሂብ በማዛወር ላይ {{current}}",
|
||||
"toast.migration.progress.working.progress": "ውሂብ በማዛወር ላይ {{current}}/{{total}}",
|
||||
"home.workspaceTip": "ለውጦችን ለብለል ለማቆየት ቀጣዩን ክፍለ ጊዜ በአዲስ የስራ ቦታ ይጀምሩ",
|
||||
"session.tab.browser": "አሳሽ",
|
||||
"session.tab.add": "ትር አክል",
|
||||
"session.queue.attachments.one": "ፕላስ {{count}} አባሪ",
|
||||
"session.queue.attachments.other": "ፕላስ {{count}} አባሪዎች",
|
||||
"session.browser.address": "የአሳሽ አድራሻ",
|
||||
"session.browser.replaced": "የአሳሽ መቆጣጠሪያ ወደ ሌላ የዴስክቶፕ መስኮት ተንቀሳቅሷል።",
|
||||
"session.browser.unsupported": "ይህ የዴስክቶፕ መተግበሪያ የአሳሽ ፓነሉን አይደግፍም።",
|
||||
"session.browser.suspended": "አሳሽ ታግዷል። እንደገና ለመገናኘት ከዚህ ክፍለ ጊዜ ጋር ይገናኙ።",
|
||||
"session.browser.address.placeholder": "URL ያስገቡ",
|
||||
"settings.backToSettings": "ወደ ቅንብሮች ተመለስ",
|
||||
"settings.backToProjects": "ወደ ፕሮጀክቶች ተመለስ",
|
||||
"settings.search.placeholder": "ፍለጋ",
|
||||
"settings.search.results": "ቅንብሮች ውጤቶች",
|
||||
"settings.search.group.pages": "ገጾች",
|
||||
"settings.search.group.settings": "ቅንብሮች",
|
||||
"settings.search.group.projects": "ፕሮጀክቶች",
|
||||
"settings.search.group.servers": "አገልጋዮች",
|
||||
"settings.search.result": "{{title}}፣ {{scope}}፣ {{page}}",
|
||||
"settings.search.page": "{{title}}፣ {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}፣ {{page}}",
|
||||
"settings.search.empty": "ለ{{query}} ምንም ውጤት የለም",
|
||||
"settings.search.empty.query": '"{{query}}"',
|
||||
"settings.search.refine": "የበለጠ የተወሰኑ ውጤቶችን ለማየት ፍለጋዎን ያጥቡ።",
|
||||
"settings.server.description": "የዚህን አገልጋይ ግንኙነት እና ምርጫዎች ያስተዳድሩ",
|
||||
"settings.server.section.connection": "ግንኙነት",
|
||||
"settings.server.preferences.websearch.title": "የሶስተኛ ወገን ፍለጋ",
|
||||
"settings.server.preferences.websearch.description": "ድሩን ለመፈለግ ወኪሎች የሚጠቀሙበትን የፍለጋ አቅራቢ ይምረጡ",
|
||||
"settings.projects.search.placeholder": "ፍለጋ ፕሮጀክቶች",
|
||||
"project.settings.name.title": "የፕሮጀክት ስም",
|
||||
"project.settings.name.description": "በመላው OpenCode ውስጥ ለዚህ ፕሮጀክት የሚታየው ስም",
|
||||
"project.settings.icon.description": "የሚመከር 128×128 ፒክስል. ምስል ለመስቀል ጠቅ ያድርጉ ወይም ይጎትቱ።",
|
||||
"project.settings.color.description": "ምንም ብጁ ምስል በማይዘጋጅበት ጊዜ ለፕሮጀክት አዶ ጥቅም ላይ ይውላል",
|
||||
"project.settings.worktree.startup.description": "አዲስ የስራ ዛፍ ከፈጠረ በኋላ አንድ ጊዜ ይሰራል",
|
||||
"project.settings.worktree.startup.hint.base": "$OPENCODE_WORKTREE_BASE ለ መሰረታዊ የስራ ዛፍ ይጠቀሙ።",
|
||||
"project.settings.worktree.startup.hint.new": "ለአዲሱ የስራ ዛፍ $OPENCODE_WORKTREE_PATH ይጠቀሙ።",
|
||||
"project.settings.extensions.empty.mcps.title": "እስካሁን ምንም MCPs የሉም\nለOpenCode የሚገኙ",
|
||||
"project.settings.extensions.empty.mcps.description": "ለOpenCode የሚገኙ MCP-ዎች እዚህ ይታያሉ",
|
||||
"project.settings.extensions.empty.plugins.title": "እስካሁን ምንም ተሰኪዎች የሉም\nለOpenCode የሚገኙ",
|
||||
"project.settings.extensions.empty.plugins.description": "ለOpenCode የሚገኙ ተሰኪዎች እዚህ ይታያሉ",
|
||||
"project.settings.extensions.empty.skills.title": "እስካሁን ምንም ችሎታ የለም\nለOpenCode የሚገኙ",
|
||||
"project.settings.extensions.empty.skills.description": "ለOpenCode የሚገኙ ክህሎቶች እዚህ ይታያሉ",
|
||||
"project.settings.extensions.lsp.configured": "የተዋቀሩ የቋንቋ አገልጋዮች",
|
||||
"project.settings.extensions.lsp.status.enabled": "በማዋቀር ውስጥ ነቅቷል",
|
||||
"project.settings.extensions.lsp.status.disabled": "በማዋቀር ውስጥ ተሰናክሏል",
|
||||
"project.settings.extensions.lsp.empty.title": "ምንም የቋንቋ አገልጋዮች አልተዋቀሩም\nለዚህ ፕሮጀክት የተዋቀሩ",
|
||||
"project.settings.extensions.lsp.empty.description": "የቋንቋ አገልጋዮች እዚህ ይታያሉ",
|
||||
"project.settings.extensions.lsp.disabled.title": "ቋንቋ አገልጋዮች ተሰናክለዋል",
|
||||
"project.settings.extensions.lsp.disabled.description": "LSP በዚህ ፕሮጀክት ውቅር ውስጥ ተሰናክሏል",
|
||||
"project.settings.extensions.lsp.loadFailed": "የቋንቋ አገልጋይ ውቅር መጫን አልተቻለም",
|
||||
"project.settings.extensions.lsp.retry": "እንደገና ሞክር",
|
||||
"settings.timeline.summary": "{{preset}}",
|
||||
"settings.timeline.group": "ቡድን",
|
||||
"settings.timeline.collapse": "ውድቅ",
|
||||
"settings.timeline.visibility.show": "አሳይ",
|
||||
"settings.timeline.visibility.hide": "ደብቅ",
|
||||
"settings.timeline.visibility.label": "{{activity}} ታይነት",
|
||||
"settings.timeline.grouped.label": "{{activity}} ተቧቧል",
|
||||
"settings.timeline.collapsed.label": "{{activity}} ወድቋል",
|
||||
"session.new.workspace.search.empty": "ምንም ተዛማጅ የስራ ዛፎች የሉም",
|
||||
"settings.workspaces.description": "የስራ ዛፎችን ይገምግሙ እና የዲስክ አጠቃቀምን ያስተዳድሩ",
|
||||
"settings.workspaces.empty.description": "በOpenCode የተፈጠሩ የሥራ ዛፎች እዚህ ይታያሉ",
|
||||
"settings.workspaces.sessions.filtered.one": "{{count}} ክፍለ ጊዜ",
|
||||
"settings.workspaces.sessions.filtered.other": "{{count}} ክፍለ ጊዜዎች",
|
||||
"settings.workspaces.deleteAll.confirm.one": "ይህ የተመረጠውን የስራ ዛፍ {{count}} በቋሚነት ይሰርዛል።",
|
||||
"settings.workspaces.deleteAll.confirm.other": "ይህ {{count}} የተመረጡ የስራ ዛፎችን በቋሚነት ይሰርዛል።",
|
||||
"settings.workspaces.deleteWithoutSessions": "ያለ ክፍለ ጊዜዎች የስራ ዛፎችን ሰርዝ",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one": "ይህ ያለ ተገናኙ ክፍለ ጊዜዎች {{count}} worktreeን በቋሚነት ይሰርዛል።",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other": "ይህ ያለ ተገናኙ ክፍለ ጊዜዎች {{count}} የስራ ዛፎችን በቋሚነት ይሰርዛል።",
|
||||
"settings.workspaces.deleteWithoutSessions.warning": "ያልተዋሃዱ ለውጦች ወይም ንቁ ቦታዎች ያሏቸው የስራ ዛፎች ይቀመጣሉ።",
|
||||
"settings.workspaces.delete.button": "የስራ ዛፎችን ሰርዝ",
|
||||
"workspace.lifecycle.deleting": "በመሰረዝ ላይ ...",
|
||||
"session.summary.tooltip": "ማጠቃለያ",
|
||||
"session.summary.server": "ቅጥያዎች",
|
||||
"session.summary.chooseProject": "ፕሮጀክት ይምረጡ",
|
||||
"session.summary.mcp.onCreation": "የስራ ዛፉ ሲፈጠር ተፈጻሚ ይሆናል",
|
||||
"session.summary.mcp.prepareFailed": "የMCP አገልጋዮችን ማዘጋጀት አልተቻለም",
|
||||
"session.summary.mcp.unavailable": "MCP አገልጋይ {{name}} በዚህ የስራ ዛፍ ውስጥ አይገኝም።",
|
||||
"session.summary.mcp.signInBeforeSend": "ጥያቄውን ከመላክዎ በፊት ወደ {{name}} ይግቡ።",
|
||||
"session.summary.mcp.notReady": "MCP አገልጋይ {{name}} ዝግጁ አይደለም። ጥያቄውን ከመላክዎ በፊት ግንኙነቱን ይፍቱ።",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "የተዋቀሩ MCP አገልጋዮች",
|
||||
"session.summary.plugins": "ተሰኪዎች",
|
||||
"session.summary.plugins.configured": "የተዋቀሩ ተሰኪዎች",
|
||||
"session.summary.skills": "ችሎታ",
|
||||
"session.summary.skills.configured": "የተዋቀሩ ክህሎቶች",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "አልተሳካም",
|
||||
"session.summary.retry": "እንደገና ሞክር",
|
||||
"session.summary.connecting": "በመገናኘት ላይ ...",
|
||||
"session.summary.needsAuth": "ይግቡ ያስፈልጋል",
|
||||
"session.summary.configure": "ውቅር ፋይል",
|
||||
"session.summary.copyConfigPath": "የውቅረት ፋይል ዱካ ይቅዱ",
|
||||
"session.summary.configFileMissing": "ምንም የውቅር ፋይል አልተገኘም",
|
||||
"session.summary.mcp.empty": "ምንም የMCP አገልጋዮች አልተዋቀሩም",
|
||||
"session.summary.mcp.add": "በ opencode.json ውስጥ አገልጋዮችን ያክሉ",
|
||||
"session.summary.plugins.manage": "በ opencode.json ውስጥ ተሰኪዎችን ያስተዳድሩ",
|
||||
"session.summary.plugins.empty": "ምንም ተሰኪዎች አልተዋቀሩ",
|
||||
"session.summary.plugins.add": "በ opencode.json ውስጥ ተሰኪዎችን ያክሉ",
|
||||
"session.summary.skills.manage": "በ opencode.json ውስጥ ክህሎቶችን ያስተዳድሩ",
|
||||
"session.summary.skills.empty": "ምንም ችሎታዎች አልተዋቀሩም",
|
||||
"session.summary.skills.add": "በ opencode.json ውስጥ ክህሎቶችን ያክሉ",
|
||||
"session.summary.lsp.configured": "የተዋቀሩ LSPs",
|
||||
"session.summary.lsp.empty": "ምንም የLSP አገልጋዮች አልተዋቀሩም።",
|
||||
"session.summary.lsp.manage": "በ opencode.json ውስጥ LSPን ያስተዳድሩ",
|
||||
"workspace.delete.location": "አካባቢ",
|
||||
"command.debugBar.toggle": "የማረሚያ አሞሌን ቀይር",
|
||||
"command.session.location.cycle": "የክፍለ ጊዜውን መገኛ ቀይር",
|
||||
"dialog.provider.anthropic.note": "የAPI ቁልፍ በመጠቀም ወደ Claude ሞዴሎች ቀጥተኛ መዳረሻ",
|
||||
"provider.connect.title.anthropicProMax": "በAnthropic ግባ",
|
||||
"prompt.toast.uploading.cancel": "ስቀላን ሰርዝ",
|
||||
"prompt.toast.uploading.cancelFile": "የ{{filename}} ስቀላን ሰርዝ",
|
||||
"prompt.toast.uploadFailed.title": "ስቀላው አልተሳካም",
|
||||
"session.browser.empty.title": "URL ያስገቡ",
|
||||
"session.browser.empty.description": "ወይም «በመተግበሪያው አሳሽ ክፈት» ብለው ይጠይቁ",
|
||||
"session.browser.failed.title": "URL ላይ መድረስ አልተቻለም",
|
||||
"session.browser.failed.description": "URL-ውን እና ግንኙነትዎን ይፈትሹ፣ ከዚያ እንደገና ይሞክሩ።",
|
||||
"debugBar.providerAriaLabel": "የአቅራቢ አፈጻጸም ምርመራ",
|
||||
"debugBar.ttft.tip": "የአቅራቢው ጥያቄ ከተላከበት ጊዜ እስከ ሞዴሉ የመጀመሪያ ውጤት ድረስ ያለው ጊዜ።",
|
||||
"debugBar.ttfa.tip": "የአቅራቢው ጥያቄ ከተላከበት ጊዜ እስከ የመጀመሪያው የመልስ ጽሑፍ ድረስ ያለው ጊዜ።",
|
||||
"debugBar.tps.tip": "ከሞዴሉ የመጀመሪያ ውጤት በኋላ በሰከንድ የሚወጡ ቶከኖች።",
|
||||
"debugBar.e2e.tip": "የአቅራቢው ጥያቄ ከተላከበት ጊዜ እስከ የምላሽ ዥረቱ መጨረሻ ድረስ ያለው ጊዜ።",
|
||||
"settings.updates.action.download": "OpenCodeን አውርድ",
|
||||
"settings.updates.migration.title": "ከBeta ወደ Stable ይዛወሩ",
|
||||
"settings.updates.migration.description":
|
||||
"ለጊዜው OpenCode Beta ወደ OpenCode Stable እየተዛወረ ነው። ዝማኔዎችን መቀበልዎን ለመቀጠል ስሪት {{version}}ን ያውርዱ፣ ከዚያ OpenCodeን ከዲስክ ምስሉ ይጫኑ።",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
}
|
||||
|
||||
@@ -315,6 +315,15 @@ export const dict = {
|
||||
"common.loading.ellipsis": "…",
|
||||
"common.cancel": "إلغاء",
|
||||
"common.clear": "مسح",
|
||||
"common.color.orange": "برتقالي",
|
||||
"common.color.yellow": "أصفر",
|
||||
"common.color.cyan": "سماوي",
|
||||
"common.color.green": "أخضر",
|
||||
"common.color.red": "أحمر",
|
||||
"common.color.pink": "وردي",
|
||||
"common.color.blue": "أزرق",
|
||||
"common.color.purple": "أرجواني",
|
||||
"common.color.gray": "رمادي",
|
||||
"common.connect": "اتصال",
|
||||
"common.disconnect": "قطع الاتصال",
|
||||
"common.continue": "متابعة",
|
||||
@@ -1098,4 +1107,504 @@ export const dict = {
|
||||
"error.childStore.persistedProjectIconCreateFailed": "فشل إنشاء أيقونة المشروع الدائمة",
|
||||
"error.childStore.storeCreateFailed": "فشل إنشاء المخزن",
|
||||
"terminal.connectionLost.abnormalClose": "تم إغلاق WebSocket بشكل غير طبيعي: {{code}}",
|
||||
"toast.migration.failed.title": "فشل ترحيل البيانات",
|
||||
"command.session.background": "نقل إلى الخلفية",
|
||||
"session.timeline.notice.finished": "انتهى \u2068{{actor}}\u2069",
|
||||
"session.timeline.notice.failed": "فشل \u2068{{actor}}\u2069",
|
||||
"session.timeline.notice.cancelled": "أُلغي \u2068{{actor}}\u2069",
|
||||
"settings.tab.preferences": "التفضيلات",
|
||||
"settings.tab.notifications": "الإشعارات",
|
||||
"settings.tab.projects": "المشاريع",
|
||||
"settings.tab.extensions": "الملحقات",
|
||||
"settings.preferences.description": "تخصيص التفضيلات والسمة والسلوك الافتراضي",
|
||||
"settings.appearance.description": "تخصيص السمة والخطوط",
|
||||
"settings.notifications.description": "اختر متى تتلقى الإشعارات وتسمع الأصوات",
|
||||
"settings.shortcuts.description": "تخصيص اختصارات الإجراءات الشائعة",
|
||||
"settings.servers.description": "إدارة اتصالات الخوادم",
|
||||
"settings.projects.title": "المشاريع",
|
||||
"settings.projects.description": "إدارة إعدادات المشاريع على هذا الخادم",
|
||||
"settings.projects.empty": "لم يتم العثور على مشاريع",
|
||||
"settings.projects.server.all": "كل الخوادم",
|
||||
"settings.mcps.description": "إدارة خوادم وأدوات بروتوكول سياق النموذج (MCP)",
|
||||
"settings.extensions.description": "إدارة الملحقات المتاحة على هذا الخادم",
|
||||
"settings.extensions.tab.mcps": "خوادم MCP",
|
||||
"settings.extensions.tab.skills": "المهارات",
|
||||
"settings.extensions.availableAll": "متاحة لكل المشاريع",
|
||||
"settings.extensions.manageConfig": "إدارة في opencode.json",
|
||||
"settings.extensions.addSkills": "كيفية إضافة المهارات",
|
||||
"dialog.server.authenticate.title": "المصادقة",
|
||||
"project.settings.general.description": "إدارة اسم المشروع ومظهره",
|
||||
"project.settings.scripts": "البرامج النصية",
|
||||
"project.settings.scripts.description": "تكوين البرامج النصية لهذا المشروع",
|
||||
"project.settings.extensions.description": "عرض الملحقات المتاحة لهذا المشروع",
|
||||
"project.settings.extensions.tab.lsps": "خوادم LSP",
|
||||
"project.settings.extensions.added": "مضافة إلى هذا المشروع",
|
||||
"project.settings.extensions.shared": "مشتركة مع كل المشاريع",
|
||||
"project.settings.extensions.lsp.detected": "خوادم اللغة المكتشفة",
|
||||
"project.settings.extensions.lsp.description": "تُكتشف تلقائيًا من أنواع الملفات",
|
||||
"project.settings.extensions.setupRequired": "الإعداد مطلوب",
|
||||
"settings.general.section.general": "عام",
|
||||
"common.viewAll": "عرض الكل",
|
||||
"session.new.workspace.local.tooltip": "استخدام نسخة العمل الحالية",
|
||||
"session.new.workspace.new.tooltip": "إنشاء نسخة عمل معزولة",
|
||||
"session.new.workspace.fromBranch": "من \u2068{{branch}}\u2069",
|
||||
"session.new.workspace.trigger.tooltip": "حدد مكان تشغيل الجلسة",
|
||||
"session.new.workspace.search.placeholder": "البحث في مساحات العمل",
|
||||
"settings.tab.workspaces": "مساحات العمل",
|
||||
"settings.workspaces.filter.all": "كل المشاريع",
|
||||
"settings.workspaces.empty": "لا توجد مساحات عمل",
|
||||
"settings.workspaces.count.zero": "مساحات العمل: {{count}}",
|
||||
"settings.workspaces.count.one": "{{count}} مساحة عمل",
|
||||
"settings.workspaces.count.two": "عدد مساحات العمل: {{count}}",
|
||||
"settings.workspaces.count.few": "{{count}} مساحات عمل",
|
||||
"settings.workspaces.count.many": "{{count}} مساحة عمل",
|
||||
"settings.workspaces.count.other": "مساحات العمل: {{count}}",
|
||||
"settings.workspaces.sessions.zero": "الجلسات في \u2068{{project}}\u2069: {{count}}",
|
||||
"settings.workspaces.sessions.one": "{{count}} جلسة في \u2068{{project}}\u2069",
|
||||
"settings.workspaces.sessions.two": "عدد الجلسات في \u2068{{project}}\u2069: {{count}}",
|
||||
"settings.workspaces.sessions.few": "{{count}} جلسات في \u2068{{project}}\u2069",
|
||||
"settings.workspaces.sessions.many": "{{count}} جلسة في \u2068{{project}}\u2069",
|
||||
"settings.workspaces.sessions.other": "الجلسات في \u2068{{project}}\u2069: {{count}}",
|
||||
"settings.workspaces.lastActiveSession": "آخر جلسة نشطة",
|
||||
"settings.workspaces.deleteAll": "حذف كل مساحات العمل",
|
||||
"settings.workspaces.delete.warning":
|
||||
"سيُحذف دليل مساحة العمل وفرعها نهائيًا، بما في ذلك أي تغييرات غير مدمجة موضحة أدناه.",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"سيُحتفظ بأشجار العمل ذات التغييرات غير المدمجة أو الجلسات المرتبطة أو المواقع النشطة.",
|
||||
"settings.workspaces.delete.blocked.active": "لا يمكن حذف مساحة العمل النشطة.",
|
||||
"settings.workspaces.delete.blocked.linked": "ستبقى الجلسات المرتبطة، لكن دليل عملها سيُحذف نهائيًا.",
|
||||
"settings.workspaces.default.title": "البيئة الافتراضية",
|
||||
"settings.workspaces.default.description": "اختر مكان بدء الجلسات الجديدة",
|
||||
"settings.workspaces.default.lastUsed": "آخر استخدام لكل مشروع",
|
||||
"settings.workspaces.default.local": "الدليل المحلي",
|
||||
"settings.workspaces.default.new": "مساحة عمل جديدة",
|
||||
"workspace.move.title": "نقل إلى مساحة عمل",
|
||||
"workspace.move.menu.title": "نقل الجلسة إلى",
|
||||
"workspace.move.failed": "فشل نقل الجلسة",
|
||||
"workspace.lifecycle.creating": "جارٍ إنشاء مساحة العمل",
|
||||
"workspace.lifecycle.created": "تم إنشاء مساحة العمل",
|
||||
"workspace.lifecycle.starting": "جارٍ بدء الجلسة",
|
||||
"workspace.onboarding.title": "عزل الجلسات باستخدام مساحات العمل",
|
||||
"workspace.onboarding.description": "تحصل كل جلسة على نسخة عمل خاصة بها، فلا يتداخل شيء مع مستودعك المحلي",
|
||||
"workspace.lifecycle.moving": "جارٍ النقل إلى مساحة العمل",
|
||||
"workspace.lifecycle.set": "تم تعيين مساحة العمل",
|
||||
"session.summary.title": "تفاصيل الجلسة",
|
||||
"session.summary.noBranch": "لا يوجد فرع",
|
||||
"session.summary.basedOn": "استنادًا إلى \u2068{{branch}}\u2069",
|
||||
"provider.disconnect.toast.noCredentials.description":
|
||||
"لم يتم العثور على بيانات اعتماد قابلة للإزالة لـ \u2068{{provider}}\u2069.",
|
||||
"provider.disconnect.toast.failed.description": "فشل قطع الاتصال بـ \u2068{{provider}}\u2069.",
|
||||
"command.project.copyID": "نسخ معرّف المشروع",
|
||||
"command.session.copyID": "نسخ معرّف الجلسة",
|
||||
"server.row.incompatible":
|
||||
"يعمل هذا الخادم بإصدار OpenCode \u2068{{version}}\u2069، وهو غير متوافق مع هذا التطبيق. رقِّه إلى OpenCode V2 للمتابعة.",
|
||||
"toast.session.copyID.failed.title": "فشل نسخ معرّف الجلسة",
|
||||
"toast.session.copyID.failed.description": "حدث خطأ أثناء نسخ معرّف الجلسة",
|
||||
"toast.project.copyID.failed.title": "فشل نسخ معرّف المشروع",
|
||||
"toast.project.copyID.failed.description": "حدث خطأ أثناء نسخ معرّف المشروع",
|
||||
"error.page.title.status": "فشل طلب الخادم",
|
||||
"error.page.description.status": "أعاد الخادم استجابة HTTP بالحالة \u2068{{status}}\u2069.",
|
||||
"error.page.action.reload": "إعادة التحميل",
|
||||
"session.error.incompatible": "إصدار هذا الخادم غير مدعوم",
|
||||
"session.error.incompatible.description":
|
||||
"يعمل \u2068{{server}}\u2069 بإصدار OpenCode \u2068{{version}}\u2069، وهو غير متوافق مع هذا التطبيق. رقِّ الخادم إلى OpenCode V2 للمتابعة.",
|
||||
"session.background.moveInline": "اضغط على \u2068{{keybind}}\u2069 لنقل العمل الجاري إلى الخلفية",
|
||||
"session.background.running": "العمل جارٍ في الخلفية",
|
||||
"session.background.runningCount.zero": "العناصر قيد التشغيل في الخلفية: {{count}}",
|
||||
"session.background.runningCount.one": "{{count}} عنصر قيد التشغيل في الخلفية",
|
||||
"session.background.runningCount.two": "عدد العناصر قيد التشغيل في الخلفية: {{count}}",
|
||||
"session.background.runningCount.few": "{{count}} عناصر قيد التشغيل في الخلفية",
|
||||
"session.background.runningCount.many": "{{count}} عنصرًا قيد التشغيل في الخلفية",
|
||||
"session.background.runningCount.other": "العناصر قيد التشغيل في الخلفية: {{count}}",
|
||||
"settings.general.row.terminalPlacement.title": "موضع المحطة الطرفية",
|
||||
"settings.general.row.terminalPlacement.description": "اختر مكان فتح المحطة الطرفية في الجلسات",
|
||||
"settings.general.row.terminalPlacement.side": "الجانب",
|
||||
"settings.general.row.terminalPlacement.bottom": "الأسفل",
|
||||
"desktop.menu.installCli": "تثبيت CLI...",
|
||||
"desktop.cli.installed.title": "تم تثبيت CLI",
|
||||
"desktop.cli.installed.message":
|
||||
"تم تثبيت CLI في \u2068{{path}}\u2069\n\nأعد تشغيل المحطة الطرفية لاستخدام الأمر 'opencode2'.",
|
||||
"desktop.cli.failed.title": "فشل التثبيت",
|
||||
"desktop.cli.failed.message": "فشل تثبيت CLI: \u2068{{error}}\u2069",
|
||||
"session.location.unavailable": "موقع الجلسة غير متاح",
|
||||
"session.location.description": "اختر دليلاً آخر لمتابعة هذه الجلسة.",
|
||||
"session.location.choose": "اختيار دليل",
|
||||
"session.location.worktree": "اختيار شجرة عمل",
|
||||
"session.location.worktreesFailed": "فشل تحميل أشجار العمل",
|
||||
"session.location.moving": "جارٍ نقل الجلسة…",
|
||||
"dialog.server.menu.hide": "إخفاء من قائمة المشاريع",
|
||||
"dialog.server.menu.show": "إظهار في قائمة المشاريع",
|
||||
"session.queue.count.zero": "{{count}} عناصر في قائمة الانتظار",
|
||||
"session.queue.count.one": "{{count}} عنصر في قائمة الانتظار",
|
||||
"session.queue.count.two": "{{count}} عنصران في قائمة الانتظار",
|
||||
"session.queue.count.few": "{{count}} عناصر في قائمة الانتظار",
|
||||
"session.queue.count.many": "{{count}} عنصرًا في قائمة الانتظار",
|
||||
"session.queue.count.other": "{{count}} عنصر في قائمة الانتظار",
|
||||
"session.queue.steer": "توجيه",
|
||||
"session.queue.send": "إرسال",
|
||||
"session.queue.steerTooltip": "إرسال دون مقاطعة",
|
||||
"session.queue.remove": "إزالة",
|
||||
"session.queue.reorder": "إعادة ترتيب الموجّه في قائمة الانتظار",
|
||||
"session.review.change.zero": "تغييرات",
|
||||
"session.review.change.two": "تغييران",
|
||||
"session.review.change.few": "تغييرات",
|
||||
"session.review.change.many": "تغييرًا",
|
||||
"session.new.worktree.creating": "جارٍ إنشاء شجرة العمل",
|
||||
"settings.backToApp": "العودة إلى التطبيق",
|
||||
"settings.appearance.section.experimental": "تجريبي",
|
||||
"settings.appearance.row.tabs.title": "علامات التبويب",
|
||||
"settings.appearance.row.tabs.description": "اختر كيفية ترتيب علامات تبويب الجلسات",
|
||||
"settings.appearance.row.tabs.horizontal": "أفقي",
|
||||
"settings.appearance.row.tabs.vertical": "عمودي",
|
||||
"settings.general.row.followUpBehavior.title": "سلوك المتابعة",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"اختر وضع رسائل المتابعة في قائمة الانتظار أو توجيه الدور الحالي. استخدم \u2068{{keybind}}\u2069 للتبديل.",
|
||||
"settings.general.row.followUpBehavior.queue": "وضع في قائمة الانتظار",
|
||||
"settings.general.row.followUpBehavior.steer": "توجيه",
|
||||
"settings.general.row.reasoningMode.title": "استدلال النموذج",
|
||||
"settings.general.row.reasoningMode.description": "اختر كيفية عرض استدلال النموذج في المخطط الزمني",
|
||||
"settings.general.row.reasoningMode.hidden": "مخفي",
|
||||
"settings.general.row.reasoningMode.compact": "موجز",
|
||||
"settings.general.row.reasoningMode.full": "كامل",
|
||||
"session.new.workspace.createFrom": "إنشاء من فرع",
|
||||
"session.new.workspace.branch.search.placeholder": "البحث في الفروع",
|
||||
"toast.migration.progress.clearingOldEvents": "جارٍ مسح الأحداث القديمة",
|
||||
"toast.migration.progress.migratingSessions": "جارٍ ترحيل الجلسات",
|
||||
"toast.migration.progress.migratingSessions.current": "جارٍ ترحيل الجلسات \u2068{{current}}\u2069",
|
||||
"toast.migration.progress.migratingSessions.progress":
|
||||
"جارٍ ترحيل الجلسات \u2068{{current}}\u2069/\u2068{{total}}\u2069",
|
||||
"toast.migration.progress.working": "جارٍ ترحيل البيانات",
|
||||
"toast.migration.progress.working.current": "جارٍ ترحيل البيانات \u2068{{current}}\u2069",
|
||||
"toast.migration.progress.working.progress": "جارٍ ترحيل البيانات \u2068{{current}}\u2069/\u2068{{total}}\u2069",
|
||||
"session.new.workspace.existingLabel": "شجرة عمل",
|
||||
"home.projects.all": "كل المشاريع",
|
||||
"session.tab.files": "الملفات",
|
||||
"session.files.openTabs": "الملفات المفتوحة",
|
||||
"session.tab.usage": "الاستخدام",
|
||||
"session.view.select": "عرض الجلسة",
|
||||
"session.background.moveTasks": "نقل \u2068{{tasks}}\u2069 إلى الخلفية",
|
||||
"session.background.moveRunning": "نقل العمل إلى الخلفية",
|
||||
"session.background.inBackground": "تشغيل \u2068{{tasks}}\u2069 في الخلفية",
|
||||
"session.background.tasksRunning.zero": "{{count}} مهمة تعمل في الخلفية",
|
||||
"session.background.tasksRunning.one": "{{count}} مهمة تعمل في الخلفية",
|
||||
"session.background.tasksRunning.two": "{{count}} مهمتان تعملان في الخلفية",
|
||||
"session.background.tasksRunning.few": "{{count}} مهام تعمل في الخلفية",
|
||||
"session.background.tasksRunning.many": "{{count}} مهمة تعمل في الخلفية",
|
||||
"session.background.tasksRunning.other": "{{count}} مهمة تعمل في الخلفية",
|
||||
"session.background.combine": "\u2068{{first}}\u2069 و\u2068{{second}}\u2069",
|
||||
"session.background.shell.zero": "{{count}} عملية \u2068shell\u2069",
|
||||
"session.background.shell.one": "{{count}} عملية \u2068shell\u2069",
|
||||
"session.background.shell.two": "{{count}} عمليتا \u2068shell\u2069",
|
||||
"session.background.shell.few": "{{count}} عمليات \u2068shell\u2069",
|
||||
"session.background.shell.many": "{{count}} عملية \u2068shell\u2069",
|
||||
"session.background.shell.other": "{{count}} عملية \u2068shell\u2069",
|
||||
"session.background.subagent.zero": "{{count}} وكيل فرعي",
|
||||
"session.background.subagent.one": "{{count}} وكيل فرعي",
|
||||
"session.background.subagent.two": "{{count}} وكيلان فرعيان",
|
||||
"session.background.subagent.few": "{{count}} وكلاء فرعيين",
|
||||
"session.background.subagent.many": "{{count}} وكيلًا فرعيًا",
|
||||
"session.background.subagent.other": "{{count}} وكيل فرعي",
|
||||
"session.timeline.working": "جارٍ العمل",
|
||||
"session.review.wrapLines": "التفاف الأسطر",
|
||||
"session.websearch.title": "بحث على الويب عبر جهة خارجية",
|
||||
"session.websearch.description": "اختر موفر البحث الذي تستخدمه الوكلاء للبحث على الويب",
|
||||
"session.websearch.provider": "موفر البحث",
|
||||
"session.websearch.any": "أي موفر",
|
||||
"session.websearch.disable": "عدم استخدام البحث",
|
||||
"session.websearch.enable": "تمكين",
|
||||
"session.websearch.loadFailed": "تعذر تحميل موفري البحث.",
|
||||
"session.websearch.empty": "لا يتوفر أي موفر بحث.",
|
||||
"session.websearch.failed": "تعذر حفظ اختيارك. يُرجى المحاولة مرة أخرى.",
|
||||
"session.websearch.retry": "إعادة المحاولة",
|
||||
"session.new.worktree.draftPlaceholder": "اكتب متابعة أثناء تجهيز شجرة العمل…",
|
||||
"session.search.placeholder": "بحث...",
|
||||
"session.search.noResults": "لا توجد مطابقات",
|
||||
"titlebar.tabs": "علامات التبويب",
|
||||
"titlebar.channel.local": "محلي",
|
||||
"titlebar.channel.dev": "تطوير",
|
||||
"titlebar.channel.beta": "تجريبي",
|
||||
"titlebar.toggleDebugTools": "إظهار أدوات التصحيح أو إخفاؤها",
|
||||
"settings.tab.experimental": "تجريبي",
|
||||
"settings.experimental.description": "جرّب الميزات التجريبية",
|
||||
"settings.tab.about": "حول",
|
||||
"settings.about.version": "الإصدار \u2068{{version}}\u2069",
|
||||
"settings.about.devVersion": "إصدار تطوير",
|
||||
"settings.about.license": "صدر بموجب ترخيص \u2068MIT\u2069",
|
||||
"settings.about.writtenBy": "كتبه",
|
||||
"settings.about.illustratedBy": "رسوم من",
|
||||
"settings.about.and": "و",
|
||||
"settings.about.otherContributor.zero": "{{count}} مساهمين آخرين",
|
||||
"settings.about.otherContributor.one": "{{count}} مساهم آخر",
|
||||
"settings.about.otherContributor.two": "{{count}} مساهمان آخران",
|
||||
"settings.about.otherContributor.few": "{{count}} مساهمين آخرين",
|
||||
"settings.about.otherContributor.many": "{{count}} مساهمًا آخر",
|
||||
"settings.about.otherContributor.other": "{{count}} مساهم آخر",
|
||||
"settings.about.firstPublished": "نُشر أول مرة في \u2068Missouri, USA\u2069",
|
||||
"settings.about.firstIllustrated": "رُسم أول مرة في \u2068London, England\u2069",
|
||||
"settings.about.website": "\u2068www.opencode.ai\u2069",
|
||||
"settings.about.description": "\u2068OpenCode\u2069، وكيل البرمجة مفتوح المصدر",
|
||||
"settings.about.trademark": "\u2068OpenCode\u2069 علامة تجارية مسجلة لشركة \u2068Anomaly Innovations, Inc.\u2069",
|
||||
"settings.about.typeset": "منضّد بخطي \u2068Inter\u2069 و\u2068IBM Plex Mono\u2069",
|
||||
"settings.about.tagline": "لا يستطيع الذكاء الاصطناعي بناء برمجيات رائعة من دونك",
|
||||
"settings.about.copyright": "© \u2068Anomaly Innovations, Inc.\u2069",
|
||||
"project.settings.title": "تحرير المشروع",
|
||||
"settings.timeline.title": "المخطط الزمني",
|
||||
"settings.timeline.detail": "تفاصيل المخطط الزمني",
|
||||
"settings.timeline.description": "اختر مقدار النشاط الذي يظهر في المخطط الزمني. تظل الرسائل ظاهرة.",
|
||||
"settings.timeline.preset.everything": "كل شيء",
|
||||
"settings.timeline.preset.detailed": "مفصّل",
|
||||
"settings.timeline.preset.compact": "موجز",
|
||||
"settings.timeline.preset.quiet": "هادئ",
|
||||
"settings.timeline.preset.text-only": "النص فقط",
|
||||
"settings.timeline.description.everything":
|
||||
"إظهار كل نشاط على حدة. توسيع مخرجات \u2068shell\u2069 والتعديلات والتفكير.",
|
||||
"settings.timeline.description.detailed":
|
||||
"توسيع مخرجات \u2068shell\u2069 والتعديلات. إظهار الوكلاء الفرعيين على حدة وتجميع بقية النشاط ضمن «الأدوات المستخدمة».",
|
||||
"settings.timeline.description.compact": "تجميع كل النشاط ضمن «الأدوات المستخدمة» مع طي التفاصيل.",
|
||||
"settings.timeline.description.quiet":
|
||||
"تجميع التعديلات والوكلاء الفرعيين ضمن «الأدوات المستخدمة». إخفاء بقية النشاط.",
|
||||
"settings.timeline.description.text-only": "إخفاء كل النشاط. إظهار الرسائل فقط.",
|
||||
"settings.timeline.description.custom": "استخدام الموضع والتفاصيل اللذين حددتهما لكل فئة نشاط.",
|
||||
"settings.timeline.custom": "مخصص",
|
||||
"settings.timeline.advanced": "متقدم",
|
||||
"settings.timeline.advanced.description": "تعيين الموضع والتفاصيل لكل فئة نشاط.",
|
||||
"settings.timeline.category.shell": "\u2068Shell\u2069",
|
||||
"settings.timeline.category.edit": "التعديلات",
|
||||
"settings.timeline.category.thinking": "التفكير",
|
||||
"settings.timeline.category.subagents": "الوكلاء الفرعيون",
|
||||
"settings.timeline.category.notices": "الإشعارات",
|
||||
"settings.timeline.category.tools": "أدوات أخرى",
|
||||
"settings.general.row.mobileDiffWrap.description": "التفاف الأسطر الطويلة في فروقات الهاتف بدلًا من تمريرها أفقيًا",
|
||||
"provider.connect.error.unsupportedFields": "يحتوي نموذج المصادقة هذا على حقول غير مدعومة",
|
||||
"session.review.filesChangedCount.zero": "تم تغيير {{count}} ملف",
|
||||
"session.review.filesChangedCount.one": "تم تغيير {{count}} ملف",
|
||||
"session.review.filesChangedCount.two": "تم تغيير ملفين ({{count}})",
|
||||
"session.review.filesChangedCount.few": "تم تغيير {{count}} ملفات",
|
||||
"session.review.filesChangedCount.many": "تم تغيير {{count}} ملفًا",
|
||||
"session.review.filesChangedCount.other": "تم تغيير {{count}} ملف",
|
||||
"settings.about.writtenByNames": "كتبه \u2068{{names}}\u2069",
|
||||
"settings.about.illustratedByNames": "رسوم \u2068{{names}}\u2069",
|
||||
"desktop.onboarding.defaultProject": "المشروع الافتراضي",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline": "غير متصل بـ \u2068{{host}}\u2069. حُفظت مسودة رسالتك، وقد يستمر العمل البعيد.",
|
||||
"ssh.placeholder": "ssh user@example.com",
|
||||
"ssh.add": "إضافة خادم SSH",
|
||||
"ssh.server.menu.label": "خادم SSH",
|
||||
"ssh.target": "المضيف أو أمر SSH",
|
||||
"ssh.connect": "اتصال",
|
||||
"ssh.connectTo": "الاتصال بـ \u2068{{host}}\u2069",
|
||||
"ssh.authenticate": "مصادقة SSH",
|
||||
"ssh.action.authenticate": "مصادقة",
|
||||
"ssh.session.disconnected": "اتصال SSH غير نشط",
|
||||
"ssh.session.connecting": "جارٍ الاتصال بخادم SSH",
|
||||
"ssh.session.reconnectDescription": "أعِد الاتصال لعرض هذه الجلسة ومتابعة العمل. جلستك البعيدة محفوظة.",
|
||||
"ssh.session.reconnect": "إعادة الاتصال",
|
||||
"ssh.authenticationRequired": "المصادقة مطلوبة لـ \u2068{{host}}\u2069",
|
||||
"ssh.trust": "الثقة والاتصال",
|
||||
"ssh.continue": "متابعة",
|
||||
"ssh.retry": "إعادة المحاولة",
|
||||
"ssh.update": "التحديث وإعادة الاتصال",
|
||||
"ssh.openProject": "فتح مشروع",
|
||||
"ssh.project": "فتح مشروع على \u2068{{host}}\u2069",
|
||||
"ssh.disconnect": "قطع الاتصال",
|
||||
"ssh.forget": "نسيان الاتصال",
|
||||
"ssh.stage.disconnected": "قُطع الاتصال. سيظل الخادم البعيد قيد التشغيل.",
|
||||
"ssh.stage.connecting": "جارٍ الاتصال عبر SSH…",
|
||||
"ssh.stage.checking": "جارٍ التحقق من OpenCode…",
|
||||
"ssh.stage.downloading": "جارٍ تنزيل الخادم…",
|
||||
"ssh.stage.uploading": "جارٍ رفع الخادم…",
|
||||
"ssh.stage.starting": "جارٍ الاتصال بـ OpenCode…",
|
||||
"ssh.stage.ready": "متصل",
|
||||
"ssh.stage.authentication": "المصادقة مطلوبة",
|
||||
"ssh.stage.incompatible": "يلزم تحديث الخادم",
|
||||
"ssh.stage.failed": "فشل الاتصال",
|
||||
"ssh.error.input": "أدخل مضيفًا أو أمر اتصال SSH. لا يُسمح بالأوامر البعيدة وخيارات SSH غير المدعومة.",
|
||||
"ssh.error.connection": "تعذر إنشاء اتصال SSH. تحقق من الشبكة وإعدادات SSH.",
|
||||
"ssh.error.platform":
|
||||
"هذه المنصة البعيدة غير مدعومة. يتطلب الإعداد التلقائي حاليًا Linux أو macOS بمعمارية x64 أو arm64.",
|
||||
"ssh.error.version": "يجب أن يتطابق إصدار الخدمة البعيدة مع إصدار تطبيق سطح المكتب هذا قبل الاتصال.",
|
||||
"ssh.error.install": "تعذر تثبيت الخادم البعيد. تحقق من الاتصال ومساحة القرص ومن تثبيت tar.",
|
||||
"ssh.error.unpublished":
|
||||
"لا يتوفر خادم بعيد منشور لإصدار تطبيق سطح المكتب هذا. لبنى التطوير، ثبّت V2 وشغّله على المضيف، ثم أعد المحاولة.",
|
||||
"ssh.error.service": "اتصل SSH، لكن خادم OpenCode لم يصبح جاهزًا.",
|
||||
"ssh.error.host-key": "تعذر التحقق من هوية المضيف. تحقق من بصمته قبل تحديث قائمة مضيفي SSH المعروفين.",
|
||||
"ssh.error.ssh-missing": "لم يُعثر على OpenSSH. ثبّت عميل OpenSSH وتأكد من توفر ssh في PATH.",
|
||||
"command.browser.open": "فتح المتصفح",
|
||||
"command.browser.reload": "إعادة تحميل صفحة المتصفح",
|
||||
"command.session.summary.toggle": "إظهار الملخص أو إخفاؤه",
|
||||
"mcp.auth.interactiveForm": "يتطلب خادم MCP المسمى \u2068{{name}}\u2069 نموذج مصادقة تفاعليًا",
|
||||
"server.connect.title": "الاتصال بخادم",
|
||||
"server.connect.description": "أدخل عنوان الخادم وكلمة المرور للبدء.",
|
||||
"server.connect.button": "اتصال",
|
||||
"server.connect.address.invalid": "أدخل عنوان خادم HTTP أو HTTPS صالحًا.",
|
||||
"server.connect.failed": "تعذر الاتصال. تحقق من عنوان الخادم وكلمة المرور، ثم أعد المحاولة.",
|
||||
"server.connect.pair.description": "نفّذ هذا الأمر على حاسوبك للحصول على تفاصيل الاتصال.",
|
||||
"server.connect.scan": "مسح رمز QR",
|
||||
"server.connect.scan.description": "وجّه الكاميرا نحو رمز QR الذي يعرضه opencode pair.",
|
||||
"server.connect.scan.invalid": "هذا ليس رمز إقران OpenCode. امسح الرمز الذي يعرضه opencode pair.",
|
||||
"server.connect.camera": "كاميرا الإقران",
|
||||
"server.connect.camera.starting": "جارٍ فتح الكاميرا…",
|
||||
"server.connect.mixedContent": "تعذر الاتصال بخادم HTTP هذا من صفحة HTTPS. استخدم عنوان خادم HTTPS بدلًا منه.",
|
||||
"server.connect.camera.insecure": "يتطلب مسح رمز QR فتح هذه الصفحة عبر HTTPS أو على localhost.",
|
||||
"server.connect.camera.unavailable": "لا تتوفر كاميرا لهذا المتصفح. أدخل تفاصيل الاتصال يدويًا.",
|
||||
"server.connect.camera.error": "تعذر فتح الكاميرا. اسمح بالوصول إليها أو أدخل تفاصيل الاتصال يدويًا.",
|
||||
"dialog.server.menu.remove": "إزالة",
|
||||
"file.error.notFound": "الملف غير موجود: \u2068{{name}}\u2069",
|
||||
"home.workspaceTip": "ابدأ الجلسة التالية في شجرة عمل جديدة لإبقاء التغييرات معزولة",
|
||||
"session.tab.browser": "المتصفح",
|
||||
"session.tab.add": "إضافة علامة تبويب",
|
||||
"session.queue.attachments.one": "بالإضافة إلى {{count}} مرفق",
|
||||
"session.queue.attachments.other": "بالإضافة إلى \u2068{{count}}\u2069 مرفقات",
|
||||
"session.browser.address": "عنوان المتصفح",
|
||||
"session.browser.replaced": "انتقل التحكم بالمتصفح إلى نافذة سطح مكتب أخرى.",
|
||||
"session.browser.unsupported": "لا يدعم تطبيق سطح المكتب هذا لوحة المتصفح.",
|
||||
"session.browser.suspended": "عُلّق المتصفح. تفاعل مع هذه الجلسة لإعادة الاتصال.",
|
||||
"session.browser.address.placeholder": "أدخل URL",
|
||||
"settings.backToSettings": "العودة إلى الإعدادات",
|
||||
"settings.backToProjects": "العودة إلى المشاريع",
|
||||
"settings.search.placeholder": "بحث",
|
||||
"settings.search.results": "نتائج الإعدادات",
|
||||
"settings.search.group.pages": "الصفحات",
|
||||
"settings.search.group.settings": "الإعدادات",
|
||||
"settings.search.group.projects": "المشاريع",
|
||||
"settings.search.group.servers": "الخوادم",
|
||||
"settings.search.result": "\u2068{{title}}\u2069، \u2068{{scope}}\u2069، \u2068{{page}}\u2069",
|
||||
"settings.search.page": "\u2068{{title}}\u2069، \u2068{{scope}}\u2069",
|
||||
"settings.search.result.unscoped": "\u2068{{title}}\u2069، \u2068{{page}}\u2069",
|
||||
"settings.search.empty": "لا نتائج لـ \u2068{{query}}\u2069",
|
||||
"settings.search.empty.query": "«\u2068{{query}}\u2069»",
|
||||
"settings.search.refine": "ضيّق نطاق البحث لرؤية نتائج أكثر تحديدًا.",
|
||||
"settings.server.description": "إدارة اتصال هذا الخادم وتفضيلاته",
|
||||
"settings.server.section.connection": "الاتصال",
|
||||
"settings.server.preferences.websearch.title": "بحث عبر جهة خارجية",
|
||||
"settings.server.preferences.websearch.description": "حدد موفر البحث الذي تستخدمه الوكلاء للبحث في الويب",
|
||||
"settings.projects.search.placeholder": "البحث في المشاريع",
|
||||
"project.settings.name.title": "اسم المشروع",
|
||||
"project.settings.name.description": "الاسم المعروض لهذا المشروع في جميع أنحاء OpenCode",
|
||||
"project.settings.icon.description": "يوصى بـ 128×128 بكسل. انقر أو اسحب لرفع صورة.",
|
||||
"project.settings.color.description": "يُستخدم لأيقونة المشروع عند عدم تعيين صورة مخصصة",
|
||||
"project.settings.worktree.startup.description": "يُشغّل مرة واحدة بعد إنشاء شجرة عمل جديدة",
|
||||
"project.settings.worktree.startup.hint.base": "استخدم $OPENCODE_WORKTREE_BASE لشجرة العمل الأساسية.",
|
||||
"project.settings.worktree.startup.hint.new": "استخدم $OPENCODE_WORKTREE_PATH لشجرة العمل الجديدة.",
|
||||
"project.settings.extensions.empty.mcps.title": "لا توجد خوادم MCP بعد",
|
||||
"project.settings.extensions.empty.mcps.description": "ستظهر هنا خوادم MCP المتاحة لـ OpenCode",
|
||||
"project.settings.extensions.empty.plugins.title": "لا توجد ملحقات بعد",
|
||||
"project.settings.extensions.empty.plugins.description": "ستظهر هنا الملحقات المتاحة لـ OpenCode",
|
||||
"project.settings.extensions.empty.skills.title": "لا توجد مهارات بعد",
|
||||
"project.settings.extensions.empty.skills.description": "ستظهر هنا المهارات المتاحة لـ OpenCode",
|
||||
"project.settings.extensions.lsp.configured": "خوادم اللغة المكوّنة",
|
||||
"project.settings.extensions.lsp.status.enabled": "مفعّل في ملف الإعداد",
|
||||
"project.settings.extensions.lsp.status.disabled": "معطّل في ملف الإعداد",
|
||||
"project.settings.extensions.lsp.empty.title": "لم تُكوّن خوادم لغة",
|
||||
"project.settings.extensions.lsp.empty.description": "ستظهر هنا خوادم اللغة المكوّنة لهذا المشروع",
|
||||
"project.settings.extensions.lsp.disabled.title": "خوادم اللغة معطّلة",
|
||||
"project.settings.extensions.lsp.disabled.description": "LSP معطّل في إعدادات هذا المشروع",
|
||||
"project.settings.extensions.lsp.loadFailed": "تعذر تحميل إعدادات خادم اللغة",
|
||||
"project.settings.extensions.lsp.retry": "إعادة المحاولة",
|
||||
"settings.timeline.summary": "\u2068{{preset}}\u2069:",
|
||||
"settings.timeline.group": "تجميع",
|
||||
"settings.timeline.collapse": "طي",
|
||||
"settings.timeline.visibility.show": "إظهار",
|
||||
"settings.timeline.visibility.hide": "إخفاء",
|
||||
"settings.timeline.visibility.label": "رؤية \u2068{{activity}}\u2069",
|
||||
"settings.timeline.grouped.label": "\u2068{{activity}}\u2069 مجمّع",
|
||||
"settings.timeline.collapsed.label": "\u2068{{activity}}\u2069 مطوي",
|
||||
"session.new.workspace.search.empty": "لا توجد أشجار عمل مطابقة",
|
||||
"settings.workspaces.description": "مراجعة أشجار العمل وإدارة استخدام القرص",
|
||||
"settings.workspaces.empty.description": "ستظهر هنا أشجار العمل المنشأة في OpenCode",
|
||||
"settings.workspaces.sessions.filtered.one": "{{count}} جلسة",
|
||||
"settings.workspaces.sessions.filtered.other": "\u2068{{count}}\u2069 جلسات",
|
||||
"settings.workspaces.deleteAll.confirm.one": "سيؤدي هذا إلى حذف {{count}} شجرة عمل محددة نهائيًا.",
|
||||
"settings.workspaces.deleteAll.confirm.other":
|
||||
"سيؤدي هذا إلى حذف \u2068{{count}}\u2069 من أشجار العمل المحددة نهائيًا.",
|
||||
"settings.workspaces.deleteWithoutSessions": "حذف أشجار العمل التي لا تحتوي على جلسات",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"سيؤدي هذا إلى حذف {{count}} شجرة عمل لا ترتبط بجلسات نهائيًا.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"سيؤدي هذا إلى حذف \u2068{{count}}\u2069 من أشجار العمل التي لا ترتبط بجلسات نهائيًا.",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"سيُحتفظ بأشجار العمل ذات التغييرات غير المدمجة أو المواقع النشطة.",
|
||||
"settings.workspaces.delete.button": "حذف أشجار العمل",
|
||||
"workspace.lifecycle.deleting": "جارٍ الحذف…",
|
||||
"session.summary.tooltip": "الملخص",
|
||||
"session.summary.server": "الملحقات",
|
||||
"session.summary.chooseProject": "اختيار مشروع",
|
||||
"session.summary.mcp.onCreation": "يُطبّق عند إنشاء شجرة العمل",
|
||||
"session.summary.mcp.prepareFailed": "تعذر إعداد خوادم MCP",
|
||||
"session.summary.mcp.unavailable": "خادم MCP المسمى \u2068{{name}}\u2069 غير متاح في شجرة العمل هذه.",
|
||||
"session.summary.mcp.signInBeforeSend": "سجّل الدخول إلى \u2068{{name}}\u2069 قبل إرسال المطالبة.",
|
||||
"session.summary.mcp.notReady": "خادم MCP المسمى \u2068{{name}}\u2069 غير جاهز. أصلح اتصاله قبل إرسال المطالبة.",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "خوادم MCP المكوّنة",
|
||||
"session.summary.plugins": "الملحقات",
|
||||
"session.summary.plugins.configured": "الملحقات المكوّنة",
|
||||
"session.summary.skills": "المهارات",
|
||||
"session.summary.skills.configured": "المهارات المكوّنة",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "فشل",
|
||||
"session.summary.retry": "إعادة المحاولة",
|
||||
"session.summary.connecting": "جارٍ الاتصال…",
|
||||
"session.summary.needsAuth": "تسجيل الدخول مطلوب",
|
||||
"session.summary.configure": "ملف الإعداد",
|
||||
"session.summary.copyConfigPath": "نسخ مسار ملف الإعداد",
|
||||
"session.summary.configFileMissing": "لم يُعثر على ملف إعداد",
|
||||
"session.summary.mcp.empty": "لم تُكوّن خوادم MCP",
|
||||
"session.summary.mcp.add": "إضافة خوادم في opencode.json",
|
||||
"session.summary.plugins.manage": "إدارة الملحقات في opencode.json",
|
||||
"session.summary.plugins.empty": "لم تُكوّن ملحقات",
|
||||
"session.summary.plugins.add": "إضافة ملحقات في opencode.json",
|
||||
"session.summary.skills.manage": "إدارة المهارات في opencode.json",
|
||||
"session.summary.skills.empty": "لم تُكوّن مهارات",
|
||||
"session.summary.skills.add": "إضافة مهارات في opencode.json",
|
||||
"session.summary.lsp.configured": "خوادم LSP المكوّنة",
|
||||
"session.summary.lsp.empty": "لم تُكوّن خوادم LSP",
|
||||
"session.summary.lsp.manage": "إدارة LSP في opencode.json",
|
||||
"workspace.delete.location": "الموقع",
|
||||
"session.queue.attachments.zero": "بالإضافة إلى {{count}} مرفقات",
|
||||
"session.queue.attachments.two": "بالإضافة إلى {{count}} مرفقين",
|
||||
"session.queue.attachments.few": "بالإضافة إلى {{count}} مرفقات",
|
||||
"session.queue.attachments.many": "بالإضافة إلى {{count}} مرفقًا",
|
||||
"settings.workspaces.sessions.filtered.zero": "{{count}} جلسات",
|
||||
"settings.workspaces.sessions.filtered.two": "{{count}} جلستان",
|
||||
"settings.workspaces.sessions.filtered.few": "{{count}} جلسات",
|
||||
"settings.workspaces.sessions.filtered.many": "{{count}} جلسة",
|
||||
"settings.workspaces.deleteAll.confirm.zero":
|
||||
"سيؤدي هذا إلى حذف \u2068{{count}}\u2069 من أشجار العمل المحددة نهائيًا.",
|
||||
"settings.workspaces.deleteAll.confirm.two": "سيؤدي هذا إلى حذف {{count}} شجرتي عمل محددتين نهائيًا.",
|
||||
"settings.workspaces.deleteAll.confirm.few": "سيؤدي هذا إلى حذف {{count}} من أشجار العمل المحددة نهائيًا.",
|
||||
"settings.workspaces.deleteAll.confirm.many": "سيؤدي هذا إلى حذف {{count}} شجرة عمل محددة نهائيًا.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.zero":
|
||||
"سيؤدي هذا إلى حذف \u2068{{count}}\u2069 من أشجار العمل التي لا ترتبط بجلسات نهائيًا.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.two":
|
||||
"سيؤدي هذا إلى حذف {{count}} شجرتي عمل لا ترتبطان بجلسات نهائيًا.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.few":
|
||||
"سيؤدي هذا إلى حذف {{count}} من أشجار العمل التي لا ترتبط بجلسات نهائيًا.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.many":
|
||||
"سيؤدي هذا إلى حذف {{count}} شجرة عمل لا ترتبط بجلسات نهائيًا.",
|
||||
|
||||
"command.debugBar.toggle": "تبديل إظهار شريط تصحيح الأخطاء",
|
||||
"command.session.location.cycle": "التنقل بين مواقع الجلسة",
|
||||
"dialog.provider.anthropic.note": "وصول مباشر إلى نماذج Claude عبر مفتاح API",
|
||||
"provider.connect.title.anthropicProMax": "تسجيل الدخول باستخدام Anthropic",
|
||||
"prompt.toast.uploading.percent": "\u2068{{percent}}\u2069%",
|
||||
"prompt.toast.uploading.cancelFile": "إلغاء رفع \u2068{{filename}}\u2069",
|
||||
"prompt.toast.uploading.cancel": "إلغاء الرفع",
|
||||
"prompt.toast.uploadFailed.title": "فشل الرفع",
|
||||
"session.browser.empty.title": "أدخل عنوان URL",
|
||||
"session.browser.empty.description": "أو اكتب الطلب «افتح في متصفح التطبيق»",
|
||||
"session.browser.failed.title": "يتعذر الوصول إلى عنوان URL",
|
||||
"session.browser.failed.description": "تحقق من عنوان URL واتصالك، ثم حاول مرة أخرى.",
|
||||
"debugBar.providerAriaLabel": "تشخيص أداء المزوّد",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttft.tip": "الوقت من إرسال طلب المزوّد إلى أول مخرجات للنموذج.",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.ttfa.tip": "الوقت من إرسال طلب المزوّد إلى أول نص في الإجابة.",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.tps.tip": "رموز الإخراج في الثانية بعد أول مخرجات للنموذج.",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
"debugBar.e2e.tip": "الوقت من إرسال طلب المزوّد حتى انتهاء تدفق استجابته.",
|
||||
"settings.updates.action.download": "تنزيل OpenCode",
|
||||
"settings.updates.migration.title": "الانتقال من الإصدار التجريبي إلى المستقر",
|
||||
"settings.updates.migration.description":
|
||||
"ينتقل OpenCode Beta حاليًا إلى OpenCode Stable. نزّل الإصدار \u2068{{version}}\u2069، ثم ثبّت OpenCode من صورة القرص للاستمرار في تلقي التحديثات.",
|
||||
}
|
||||
|
||||
@@ -1101,4 +1101,464 @@ export const dict = {
|
||||
"workspace.reset.archived.one": "1 sessiya arxivlənəcək.",
|
||||
"workspace.reset.archived.many": "{{count}} sessiya arxivlənəcək.",
|
||||
"workspace.reset.note": "Bu iş sahəsini standart branch ilə uyğunlaşdırmaq üçün sıfırlayacaq.",
|
||||
"toast.migration.failed.title": "Məlumat miqrasiyası uğursuz oldu",
|
||||
"command.session.background": "Arxa plana keçir",
|
||||
"session.timeline.notice.finished": "{{actor}} tamamlandı",
|
||||
"session.timeline.notice.failed": "{{actor}} uğursuz oldu",
|
||||
"session.timeline.notice.cancelled": "{{actor}} ləğv edildi",
|
||||
"settings.tab.preferences": "Tərcihlər",
|
||||
"settings.tab.notifications": "Bildirişlər",
|
||||
"settings.tab.projects": "Layihələr",
|
||||
"settings.tab.extensions": "Genişləndirmələr",
|
||||
"settings.preferences.description": "Tərcihləri, mövzunu və standart davranışı fərdiləşdirin",
|
||||
"settings.appearance.description": "Mövzunu və şriftləri fərdiləşdirin",
|
||||
"settings.notifications.description": "Bildirişlərin nə vaxt alınacağını və səslərin nə vaxt səslənəcəyini seçin",
|
||||
"settings.shortcuts.description": "Ümumi əməliyyatlar üçün qısayolları fərdiləşdirin",
|
||||
"settings.servers.description": "Server bağlantılarını idarə edin",
|
||||
"settings.projects.title": "Layihələr",
|
||||
"settings.projects.description": "Bu serverdə layihə tənzimləmələrini idarə edin",
|
||||
"settings.projects.empty": "Layihə tapılmadı",
|
||||
"settings.projects.server.all": "Bütün serverlər",
|
||||
"settings.mcps.description": "Model Context Protocol (MCP) serverlərini və alətlərini idarə edin",
|
||||
"settings.extensions.description": "Bu serverdə mövcud olan genişləndirmələri idarə edin",
|
||||
"settings.extensions.tab.mcps": "MCP-lər",
|
||||
"settings.extensions.tab.skills": "Bacarıqlar",
|
||||
"settings.extensions.availableAll": "Bütün layihələr üçün mövcuddur",
|
||||
"settings.extensions.manageConfig": "opencode.json-da idarə edin",
|
||||
"settings.extensions.addSkills": "Bacarıqları necə əlavə etməli",
|
||||
"dialog.server.authenticate.title": "Autentifikasiya",
|
||||
"project.settings.general.description": "Layihənin adını və görünüşünü idarə edin",
|
||||
"project.settings.scripts": "Skriptlər",
|
||||
"project.settings.scripts.description": "Bu layihə üçün skriptləri konfiqurasiya edin",
|
||||
"project.settings.extensions.description": "Bu layihə üçün mövcud genişləndirmələrə baxın",
|
||||
"project.settings.extensions.tab.lsps": "LSP-lər",
|
||||
"project.settings.extensions.added": "Bu layihəyə əlavə edilib",
|
||||
"project.settings.extensions.shared": "Bütün layihələrlə paylaşılıb",
|
||||
"project.settings.extensions.lsp.detected": "Aşkarlanmış dil serverləri",
|
||||
"project.settings.extensions.lsp.description": "Fayl növlərindən avtomatik aşkarlanır",
|
||||
"project.settings.extensions.setupRequired": "Quraşdırma tələb olunur",
|
||||
"settings.general.section.general": "Ümumi",
|
||||
"common.viewAll": "Hamısına bax",
|
||||
"session.new.workspace.local.tooltip": "Cari checkout-dan istifadə et",
|
||||
"session.new.workspace.new.tooltip": "Təcrid olunmuş checkout yarat",
|
||||
"session.new.workspace.fromBranch": "{{branch}} branch-indən",
|
||||
"session.new.workspace.trigger.tooltip": "Sessiyanın harada işləyəcəyini seçin",
|
||||
"session.new.workspace.search.placeholder": "İş sahələrini axtar",
|
||||
"settings.tab.workspaces": "İş sahələri",
|
||||
"settings.workspaces.filter.all": "Bütün layihələr",
|
||||
"settings.workspaces.empty": "İş sahəsi yoxdur",
|
||||
"settings.workspaces.count.one": "{{count}} iş sahəsi",
|
||||
"settings.workspaces.count.other": "{{count}} iş sahəsi",
|
||||
"settings.workspaces.sessions.one": "{{project}} layihəsində {{count}} sessiya",
|
||||
"settings.workspaces.sessions.other": "{{project}} layihəsində {{count}} sessiya",
|
||||
"settings.workspaces.lastActiveSession": "Son aktiv sessiya",
|
||||
"settings.workspaces.deleteAll": "Bütün iş sahələrini sil",
|
||||
"settings.workspaces.delete.warning":
|
||||
"İş sahəsi qovluğu və branch, aşağıda göstərilən birləşdirilməmiş dəyişikliklər də daxil olmaqla, həmişəlik silinəcək.",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"Birləşdirilməmiş dəyişiklikləri, əlaqəli sessiyaları və ya aktiv məkanları olan iş ağacları saxlanılacaq.",
|
||||
"settings.workspaces.delete.blocked.active": "Aktiv iş sahəsi silinə bilməz.",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"Əlaqəli sessiyalar qalacaq, lakin onların iş qovluğu həmişəlik silinəcək.",
|
||||
"settings.workspaces.default.title": "Standart mühit",
|
||||
"settings.workspaces.default.description": "Yeni sessiyaların harada başlayacağını seçin",
|
||||
"settings.workspaces.default.lastUsed": "Hər layihə üzrə son istifadə edilən",
|
||||
"settings.workspaces.default.local": "Yerli qovluq",
|
||||
"settings.workspaces.default.new": "Yeni iş sahəsi",
|
||||
"workspace.move.title": "İş sahəsinə köçür",
|
||||
"workspace.move.menu.title": "Sessiyanı buraya köçür",
|
||||
"workspace.move.failed": "Sessiyanı köçürmək mümkün olmadı",
|
||||
"workspace.lifecycle.creating": "İş sahəsi yaradılır",
|
||||
"workspace.lifecycle.created": "İş sahəsi yaradıldı",
|
||||
"workspace.lifecycle.starting": "Sessiya başladılır",
|
||||
"workspace.onboarding.title": "Sessiyaları iş sahələri ilə təcrid edin",
|
||||
"workspace.onboarding.description":
|
||||
"Hər birinin öz checkout-u var, buna görə heç nə yerli repozitoriyanıza müdaxilə etmir",
|
||||
"workspace.lifecycle.moving": "İş sahəsinə köçürülür",
|
||||
"workspace.lifecycle.set": "İş sahəsi təyin edildi",
|
||||
"session.summary.title": "Sessiya detalları",
|
||||
"session.summary.noBranch": "Branch yoxdur",
|
||||
"session.summary.basedOn": "{{branch}} əsasında",
|
||||
"provider.disconnect.toast.noCredentials.description": "{{provider}} üçün silinə bilən giriş məlumatı tapılmadı.",
|
||||
"provider.disconnect.toast.failed.description": "{{provider}} bağlantısını kəsmək mümkün olmadı.",
|
||||
"desktop.menu.installCli": "CLI quraşdır...",
|
||||
"desktop.cli.installed.title": "CLI quraşdırıldı",
|
||||
"desktop.cli.installed.message":
|
||||
"CLI {{path}} ünvanına quraşdırıldı\n\n'opencode2' əmrindən istifadə etmək üçün terminalı yenidən başladın.",
|
||||
"desktop.cli.failed.title": "Quraşdırma uğursuz oldu",
|
||||
"desktop.cli.failed.message": "CLI quraşdırmaq mümkün olmadı: {{error}}",
|
||||
"command.project.copyID": "Layihə ID-sini kopyala",
|
||||
"command.session.copyID": "Sessiya ID-sini kopyala",
|
||||
"server.row.incompatible":
|
||||
"Bu server bu tətbiqlə uyğun olmayan OpenCode {{version}} versiyasını işlədir. Davam etmək üçün onu OpenCode V2-yə yeniləyin.",
|
||||
"toast.session.copyID.failed.title": "Sessiya ID-sini kopyalamaq mümkün olmadı",
|
||||
"toast.session.copyID.failed.description": "Sessiya ID-si kopyalanarkən xəta baş verdi",
|
||||
"toast.project.copyID.failed.title": "Layihə ID-sini kopyalamaq mümkün olmadı",
|
||||
"toast.project.copyID.failed.description": "Layihə ID-si kopyalanarkən xəta baş verdi",
|
||||
"error.page.title.status": "Server sorğusu uğursuz oldu",
|
||||
"error.page.description.status": "Server HTTP {{status}} cavabı qaytardı.",
|
||||
"error.page.action.reload": "Yenidən yüklə",
|
||||
"session.error.incompatible": "Bu server versiyası dəstəklənmir",
|
||||
"session.error.incompatible.description":
|
||||
"{{server}} bu tətbiqlə uyğun olmayan OpenCode {{version}} versiyasını işlədir. Davam etmək üçün serveri OpenCode V2-yə yeniləyin.",
|
||||
"session.background.moveInline": "İşləyən işi arxa plana keçirmək üçün {{keybind}} basın",
|
||||
"session.background.running": "İş arxa planda davam edir",
|
||||
"session.background.runningCount.one": "{{count}} element arxa planda işləyir",
|
||||
"session.background.runningCount.other": "{{count}} element arxa planda işləyir",
|
||||
"settings.general.row.terminalPlacement.title": "Terminalın yerləşməsi",
|
||||
"settings.general.row.terminalPlacement.description": "Sessiyalarda terminalın harada açılacağını seçin",
|
||||
"settings.general.row.terminalPlacement.side": "Yan tərəf",
|
||||
"settings.general.row.terminalPlacement.bottom": "Aşağı",
|
||||
"session.location.unavailable": "Sessiyanın yeri əlçatan deyil",
|
||||
"session.location.description": "Bu sessiyanı davam etdirmək üçün başqa qovluq seçin.",
|
||||
"session.location.choose": "Qovluq seç",
|
||||
"session.location.worktree": "Worktree seç",
|
||||
"session.location.worktreesFailed": "Worktree-lər yüklənə bilmədi",
|
||||
"session.location.moving": "Sessiya köçürülür…",
|
||||
"dialog.server.menu.hide": "Layihə siyahısından gizlət",
|
||||
"dialog.server.menu.show": "Layihə siyahısında göstər",
|
||||
"session.queue.count.one": "{{count}} növbədədir",
|
||||
"session.queue.count.other": "{{count}} növbədədir",
|
||||
"session.queue.steer": "İstiqamətləndir",
|
||||
"session.queue.send": "Göndər",
|
||||
"session.queue.steerTooltip": "Dayandırmadan göndər",
|
||||
"session.queue.remove": "Sil",
|
||||
"session.queue.reorder": "Növbədəki promptun sırasını dəyiş",
|
||||
"session.new.worktree.creating": "Worktree yaradılır",
|
||||
"settings.backToApp": "Tətbiqə qayıt",
|
||||
"settings.appearance.section.experimental": "Eksperimental",
|
||||
"settings.appearance.row.tabs.title": "Tablar",
|
||||
"settings.appearance.row.tabs.description": "Sessiya tablarının necə düzüləcəyini seçin",
|
||||
"settings.appearance.row.tabs.horizontal": "Üfüqi",
|
||||
"settings.appearance.row.tabs.vertical": "Şaquli",
|
||||
"settings.general.row.followUpBehavior.title": "Davam mesajlarının davranışı",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"Davam mesajlarını növbəyə əlavə etməyi və ya cari gedişi istiqamətləndirməyi seçin. Dəyişmək üçün {{keybind}} istifadə edin.",
|
||||
"settings.general.row.followUpBehavior.queue": "Növbəyə əlavə et",
|
||||
"settings.general.row.followUpBehavior.steer": "İstiqamətləndir",
|
||||
"settings.general.row.reasoningMode.title": "Modelin düşünməsi",
|
||||
"settings.general.row.reasoningMode.description": "Modelin düşünməsinin zaman xəttində necə göstəriləcəyini seçin",
|
||||
"settings.general.row.reasoningMode.hidden": "Gizli",
|
||||
"settings.general.row.reasoningMode.compact": "Yığcam",
|
||||
"settings.general.row.reasoningMode.full": "Tam",
|
||||
"session.new.workspace.createFrom": "Buradan yarat",
|
||||
"session.new.workspace.branch.search.placeholder": "Branch-ləri axtar",
|
||||
"toast.migration.progress.clearingOldEvents": "Köhnə hadisələr təmizlənir",
|
||||
"toast.migration.progress.migratingSessions": "Sessiyalar miqrasiya edilir",
|
||||
"session.new.workspace.existingLabel": "Worktree",
|
||||
"desktop.onboarding.defaultProject": "Standart Layihə",
|
||||
"home.projects.all": "Bütün layihələr",
|
||||
"session.tab.files": "Fayllar",
|
||||
"session.files.openTabs": "Açıq fayllar",
|
||||
"session.tab.usage": "İstifadə",
|
||||
"session.view.select": "Sessiya görünüşü",
|
||||
"session.background.moveTasks": "{{tasks}} tapşırıqlarını arxa plana keçir",
|
||||
"session.background.moveRunning": "Arxa plana keçir",
|
||||
"session.background.inBackground": "{{tasks}} arxa planda işləyir",
|
||||
"session.background.tasksRunning.one": "{{count}} arxa plan tapşırığı işləyir",
|
||||
"session.background.tasksRunning.other": "{{count}} arxa plan tapşırığı işləyir",
|
||||
"session.background.combine": "{{first}} və {{second}}",
|
||||
"session.background.shell.one": "{{count}} shell",
|
||||
"session.background.shell.other": "{{count}} shell",
|
||||
"session.background.subagent.one": "{{count}} alt-agent",
|
||||
"session.background.subagent.other": "{{count}} alt-agent",
|
||||
"session.timeline.working": "İşləyir",
|
||||
"session.review.wrapLines": "Sətirləri bük",
|
||||
"session.websearch.title": "Üçüncü tərəf veb axtarışı",
|
||||
"session.websearch.description": "Agentlərin vebdə axtarış üçün istifadə edəcəyi axtarış provayderini seçin",
|
||||
"session.websearch.provider": "Axtarış provayderi",
|
||||
"session.websearch.any": "İstənilən",
|
||||
"session.websearch.disable": "Axtarışdan istifadə etmə",
|
||||
"session.websearch.enable": "Aktivləşdir",
|
||||
"session.websearch.loadFailed": "Axtarış provayderlərini yükləmək mümkün olmadı.",
|
||||
"session.websearch.empty": "Əlçatan axtarış provayderi yoxdur.",
|
||||
"session.websearch.failed": "Seçiminizi saxlamaq mümkün olmadı. Yenidən cəhd edin.",
|
||||
"session.websearch.retry": "Yenidən cəhd et",
|
||||
"session.new.worktree.draftPlaceholder": "Worktree hazırlanarkən növbəti mesajın qaralamasını yazın…",
|
||||
"session.search.placeholder": "Tap...",
|
||||
"session.search.noResults": "Uyğun nəticə yoxdur",
|
||||
"titlebar.tabs": "Tablar",
|
||||
"titlebar.channel.local": "Yerli",
|
||||
"titlebar.channel.dev": "Tərtibat",
|
||||
"titlebar.channel.beta": "Beta",
|
||||
"titlebar.toggleDebugTools": "Sazlama alətlərini göstər/gizlət",
|
||||
"settings.tab.experimental": "Eksperimental",
|
||||
"settings.experimental.description": "Eksperimental funksiyaları sınayın",
|
||||
"settings.tab.about": "Haqqında",
|
||||
"settings.about.version": "Versiya {{version}}",
|
||||
"settings.about.devVersion": "tərtibat",
|
||||
"settings.about.license": "MIT Lisenziyası ilə yayımlanıb",
|
||||
"settings.about.writtenBy": "Müəllif",
|
||||
"settings.about.illustratedBy": "İllüstrasiyalar",
|
||||
"settings.about.and": "və",
|
||||
"settings.about.otherContributor.one": "{{count}} digər",
|
||||
"settings.about.otherContributor.other": "{{count}} digər",
|
||||
"settings.about.firstPublished": "İlk dəfə Missuri, ABŞ-da nəşr olunub",
|
||||
"settings.about.firstIllustrated": "İlk dəfə London, İngiltərədə illüstrasiya olunub",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode, açıq mənbəli kodlaşdırma agenti",
|
||||
"settings.about.trademark": "OpenCode, Anomaly Innovations, Inc. şirkətinin qeydiyyatdan keçmiş ticarət nişanıdır.",
|
||||
"settings.about.typeset": "Inter və IBM Plex Mono şriftləri ilə tərtib olunub",
|
||||
"settings.about.tagline": "Siz olmadan AI möhtəşəm proqram təminatı yarada bilməz",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "Layihəni redaktə et",
|
||||
"settings.timeline.title": "Zaman xətti",
|
||||
"settings.timeline.detail": "Zaman xəttinin təfərrüatı",
|
||||
"settings.timeline.description": "Zaman xəttində nə qədər fəaliyyət göstəriləcəyini seçin. Mesajlar görünən qalır.",
|
||||
"settings.timeline.preset.everything": "Hər şey",
|
||||
"settings.timeline.preset.detailed": "Ətraflı",
|
||||
"settings.timeline.preset.compact": "Yığcam",
|
||||
"settings.timeline.preset.quiet": "Sakit",
|
||||
"settings.timeline.preset.text-only": "Yalnız mətn",
|
||||
"settings.timeline.description.everything":
|
||||
"Bütün fəaliyyəti ayrı-ayrılıqda göstər. Shell çıxışını, redaktələri və düşünməni genişləndir.",
|
||||
"settings.timeline.description.detailed":
|
||||
"Shell çıxışını və redaktələri genişləndir. Alt-agentləri ayrıca göstər, digər fəaliyyəti «İstifadə edildi» bölməsində qruplaşdır.",
|
||||
"settings.timeline.description.compact":
|
||||
"Bütün fəaliyyəti təfərrüatlar yığılmış halda «İstifadə edildi» bölməsində qruplaşdır.",
|
||||
"settings.timeline.description.quiet":
|
||||
"Redaktələri və alt-agentləri «İstifadə edildi» bölməsində qruplaşdır. Digər fəaliyyəti gizlət.",
|
||||
"settings.timeline.description.text-only": "Bütün fəaliyyəti gizlət. Yalnız mesajları göstər.",
|
||||
"settings.timeline.description.custom":
|
||||
"Hər fəaliyyət kateqoriyası üçün seçdiyiniz yerləşdirmə və təfərrüatlardan istifadə et.",
|
||||
"settings.timeline.custom": "Fərdi",
|
||||
"settings.timeline.advanced": "Qabaqcıl",
|
||||
"settings.timeline.advanced.description": "Hər fəaliyyət kateqoriyası üçün yerləşdirmə və təfərrüatları təyin edin.",
|
||||
"settings.timeline.category.shell": "Shell",
|
||||
"settings.timeline.category.edit": "Redaktələr",
|
||||
"settings.timeline.category.thinking": "Düşünmə",
|
||||
"settings.timeline.category.subagents": "Alt-agentlər",
|
||||
"settings.timeline.category.notices": "Bildirişlər",
|
||||
"settings.timeline.category.tools": "Digər alətlər",
|
||||
"settings.general.row.mobileDiffWrap.description": "Mobil diff-lərdə üfüqi sürüşdürmək əvəzinə uzun sətirləri bük",
|
||||
"provider.connect.error.unsupportedFields": "Bu autentifikasiya formasında dəstəklənməyən sahələr var",
|
||||
"session.review.filesChangedCount.one": "{{count}} fayl dəyişdi",
|
||||
"session.review.filesChangedCount.other": "{{count}} fayl dəyişdi",
|
||||
"settings.about.writtenByNames": "Müəllif: {{names}}",
|
||||
"settings.about.illustratedByNames": "İllüstrasiyalar: {{names}}",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline": "{{host}} ilə qoşulmayıb. Sizin layihə saxlanıldı; uzaq iş hələ də işləyə bilər.",
|
||||
"ssh.placeholder": "ssh user@example.com",
|
||||
"ssh.add": "SSH server əlavə et",
|
||||
"ssh.server.menu.label": "SSH server",
|
||||
"ssh.target": "Host və ya SSH komandası",
|
||||
"ssh.connect": "Qoşul",
|
||||
"ssh.connectTo": "{{host}} ilə qoşul",
|
||||
"ssh.authenticate": "SSH autentifikasiyası",
|
||||
"ssh.action.authenticate": "Autentifikasiya et",
|
||||
"ssh.session.disconnected": "SSH bağlantısı aktiv deyil",
|
||||
"ssh.session.connecting": "SSH serverinə qoşulur",
|
||||
"ssh.session.reconnectDescription":
|
||||
"Bu sessiyanı görmək və işləməyə davam etmək üçün yenidən qoşulun. Uzaq sessiyanız qorunur.",
|
||||
"ssh.session.reconnect": "Yenidən qoşul",
|
||||
"ssh.authenticationRequired": "{{host}} üçün autentifikasiya tələb olunur",
|
||||
"ssh.trust": "Etibar et və qoşul",
|
||||
"ssh.continue": "Davam et",
|
||||
"ssh.retry": "Təkrar cəhd et",
|
||||
"ssh.update": "Yenilə və yenidən qoşul",
|
||||
"ssh.openProject": "Layihəni aç",
|
||||
"ssh.project": "Layihəni {{host}} üzərində aç",
|
||||
"ssh.disconnect": "Bağlan",
|
||||
"ssh.forget": "Əlaqəni unut",
|
||||
"ssh.stage.disconnected": "Bağlantı kəsildi. Uzaq server işləməyə davam edir.",
|
||||
"ssh.stage.connecting": "SSH üzərindən qoşulur…",
|
||||
"ssh.stage.checking": "OpenCode yoxlanılır…",
|
||||
"ssh.stage.downloading": "Server yüklənir…",
|
||||
"ssh.stage.uploading": "Server yüklənir…",
|
||||
"ssh.stage.starting": "OpenCode-a qoşulur…",
|
||||
"ssh.stage.ready": "Qoşuldu",
|
||||
"ssh.stage.authentication": "Doğrulama tələb olunur",
|
||||
"ssh.stage.incompatible": "Server yeniləməsi tələb olunur",
|
||||
"ssh.stage.failed": "Bağlantı uğursuz oldu",
|
||||
"ssh.error.input":
|
||||
"Bir host və ya SSH bağlantı əmri daxil edin. Uzaq əmrlər və dəstəklənməyən SSH seçimlərinə icazə verilmir.",
|
||||
"ssh.error.connection": "SSH bağlantısı qurula bilmədi. Şəbəkə və SSH tənzimləmələrinizi yoxlayın.",
|
||||
"ssh.error.platform":
|
||||
"Bu uzaq platforma dəstəklənmir. Avtomatik quraşdırma hazırda x64 və ya arm64 üzərində Linux və ya macOS tələb edir.",
|
||||
"ssh.error.version": "Bağlantıdan əvvəl uzaq xidmət bu Desktop versiyası ilə uyğun olmalıdır.",
|
||||
"ssh.error.install":
|
||||
"Uzaq server quraşdırıla bilmədi. Bağlantını, disk boşluğunu və tar proqramının quraşdırıldığını yoxlayın.",
|
||||
"ssh.error.unpublished":
|
||||
"Bu Desktop versiyasının yayımlanmış uzaq serveri yoxdur. İnkişaf üçün olan build-lərdə hostda V2-ni quraşdırıb işə salın, sonra yenidən cəhd edin.",
|
||||
"ssh.error.service": "SSH bağlantısı quruldu, lakin OpenCode serveri hazır vəziyyətə gəlmədi.",
|
||||
"ssh.error.host-key":
|
||||
"Serverin kimliyi təsdiqlənə bilmədi. SSH məlum hostlarını yeniləməzdən əvvəl onun barmaq izini təsdiqləyin.",
|
||||
"ssh.error.ssh-missing":
|
||||
"OpenSSH tapılmadı. OpenSSH müştərisini quraşdırın və ssh-nin PATH-də mövcud olduğundan əmin olun.",
|
||||
"command.browser.open": "Brauzeri açın",
|
||||
"command.browser.reload": "Brauzer səhifəsini yeniləyin",
|
||||
"command.session.summary.toggle": "Xülasəni dəyişdirin",
|
||||
"common.color.orange": "narıncı",
|
||||
"common.color.yellow": "sarı",
|
||||
"common.color.cyan": "firuzəyi",
|
||||
"common.color.green": "yaşıl",
|
||||
"common.color.red": "qırmızı",
|
||||
"common.color.pink": "çəhrayı",
|
||||
"common.color.blue": "mavi",
|
||||
"common.color.purple": "bənövşəyi",
|
||||
"common.color.gray": "boz",
|
||||
"mcp.auth.interactiveForm": "MCP server {{name}} interaktiv autentifikasiya forması tələb edir",
|
||||
"server.connect.title": "Serverə qoşulun",
|
||||
"server.connect.description": "Başlamaq üçün server ünvanınızı və şifrənizi daxil edin.",
|
||||
"server.connect.button": "Qoşulun",
|
||||
"server.connect.address.invalid": "Etibarlı HTTP və ya HTTPS server ünvanını daxil edin.",
|
||||
"server.connect.failed": "Bağlana bilmədik. Server ünvanını və şifrəni yoxlayın, sonra yenidən cəhd edin.",
|
||||
"server.connect.pair.description": "Bağlantı məlumatlarınızı almaq üçün bu əmri kompüterinizdə işlədin.",
|
||||
"server.connect.scan": "QR kodu skan edin",
|
||||
"server.connect.scan.description": "Kameranızı opencode pair tərəfindən göstərilən QR koda yönəldin.",
|
||||
"server.connect.scan.invalid": "Bu, OpenCode qoşulma kodu deyil. opencode pair tərəfindən göstərilən kodu skan edin.",
|
||||
"server.connect.camera": "Kamera cütləşdirilir",
|
||||
"server.connect.camera.starting": "Kamera açılır…",
|
||||
"server.connect.mixedContent":
|
||||
"Bu HTTPS səhifəsindən bu HTTP serverinə qoşulmaq mümkün olmadı. Bunun əvəzinə HTTPS server ünvanından istifadə edin.",
|
||||
"server.connect.camera.insecure":
|
||||
"QR skan edilməsi üçün bu səhifəni HTTPS üzərindən və ya localhost-da açmaq tələb olunur.",
|
||||
"server.connect.camera.unavailable":
|
||||
"Bu brauzer üçün heç bir kamera mövcud deyil. Bağlantı məlumatlarınızı əl ilə daxil edin.",
|
||||
"server.connect.camera.error":
|
||||
"Kameranı aça bilmədi. Kameraya giriş icazəsi verin və ya əlaqə məlumatlarınızı əllə daxil edin.",
|
||||
"dialog.server.menu.remove": "Sil",
|
||||
"file.error.notFound": "Fayl tapılmadı: {{name}}",
|
||||
"toast.migration.progress.migratingSessions.current": "Sessiyalar köçürülür {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "Sessiyalar köçürülür {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "Məlumatlar köçürülür",
|
||||
"toast.migration.progress.working.current": "Məlumatlar köçürülür {{current}}",
|
||||
"toast.migration.progress.working.progress": "Məlumatlar köçürülür {{current}}/{{total}}",
|
||||
"home.workspaceTip": "Dəyişiklikləri izolə etmək üçün növbəti sessiyanı yeni iş sahəsində başlayın",
|
||||
"session.tab.browser": "Brauzer",
|
||||
"session.tab.add": "Tab əlavə et",
|
||||
"session.queue.attachments.one": "{{count}} əlavə əlavə et",
|
||||
"session.queue.attachments.other": "{{count}} əlavə əlavələr əlavə et",
|
||||
"session.browser.address": "Brauzer ünvanı",
|
||||
"session.browser.replaced": "Brauzer idarəsi başqa masaüstü pəncərəsinə köçürüldü.",
|
||||
"session.browser.unsupported": "Bu masaüstü tətbiq brauzer panelini dəstəkləmir.",
|
||||
"session.browser.suspended": "Brauzer dayandırıldı. Təkrar qoşulmaq üçün bu sessiya ilə qarşılıqlı əlaqə qurun.",
|
||||
"session.browser.address.placeholder": "URL daxil edin",
|
||||
"settings.backToSettings": "Parametrlərə qayıt",
|
||||
"settings.backToProjects": "Layihələrə qayıt",
|
||||
"settings.search.placeholder": "Axtarış",
|
||||
"settings.search.results": "Parametrlər nəticələri",
|
||||
"settings.search.group.pages": "Səhifələr",
|
||||
"settings.search.group.settings": "Parametrlər",
|
||||
"settings.search.group.projects": "Layihələr",
|
||||
"settings.search.group.servers": "Serverlər",
|
||||
"settings.search.result": "{{title}}, {{scope}}, {{page}}",
|
||||
"settings.search.page": "{{title}}, {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}, {{page}}",
|
||||
"settings.search.empty": "{{query}} üçün nəticə yoxdur",
|
||||
"settings.search.empty.query": '"{{query}}"',
|
||||
"settings.search.refine": "Daha spesifik nəticələr görmək üçün axtarışınızı daraldın.",
|
||||
"settings.server.description": "Bu serverin əlaqəsini və seçimlərini idarə edin",
|
||||
"settings.server.section.connection": "Əlaqə",
|
||||
"settings.server.preferences.websearch.title": "Üçüncü tərəf axtarışı",
|
||||
"settings.server.preferences.websearch.description":
|
||||
"Agentlərin vebi axtarmaq üçün istifadə etdiyi axtarış təminatçısını seçin",
|
||||
"settings.projects.search.placeholder": "Layihələri axtarın",
|
||||
"project.settings.name.title": "Layihə adı",
|
||||
"project.settings.name.description": "Bu layihə üçün OpenCode boyunca göstərilən ad",
|
||||
"project.settings.icon.description": "Tövsiyə olunur: 128×128px. Şəkil yükləmək üçün klikləyin və ya sürükləyin.",
|
||||
"project.settings.color.description": "Özəl şəkil təyin olunmadıqda layihə ikonunda istifadə olunur",
|
||||
"project.settings.worktree.startup.description": "Yeni iş ağacı yaradıldıqdan sonra bir dəfə işləyir",
|
||||
"project.settings.worktree.startup.hint.base": "Əsas iş ağacı üçün $OPENCODE_WORKTREE_BASE istifadə edin.",
|
||||
"project.settings.worktree.startup.hint.new": "Yeni iş ağacı üçün $OPENCODE_WORKTREE_PATH istifadə edin.",
|
||||
"project.settings.extensions.empty.mcps.title": "Hələ MCP yoxdur",
|
||||
"project.settings.extensions.empty.mcps.description": "OpenCode üçün mövcud MCP-lər burada görünəcək",
|
||||
"project.settings.extensions.empty.plugins.title": "Hələ plagin yoxdur",
|
||||
"project.settings.extensions.empty.plugins.description": "OpenCode üçün mövcud plaginlər burada görünəcək",
|
||||
"project.settings.extensions.empty.skills.title": "Hələ bacarıq yoxdur",
|
||||
"project.settings.extensions.empty.skills.description": "OpenCode üçün mövcud bacarıqlar burada görünəcək",
|
||||
"project.settings.extensions.lsp.configured": "Konfiqurasiya edilmiş dil serverləri",
|
||||
"project.settings.extensions.lsp.status.enabled": "Konfiqurasiyada aktivdir",
|
||||
"project.settings.extensions.lsp.status.disabled": "Konfiqurasiyada deaktivdir",
|
||||
"project.settings.extensions.lsp.empty.title": "Hələ dil serverləri konfiqurasiya olunmayıb",
|
||||
"project.settings.extensions.lsp.empty.description":
|
||||
"Bu layihə üçün konfiqurasiya edilmiş dil serverləri burada görünəcək",
|
||||
"project.settings.extensions.lsp.disabled.title": "Dil serverləri deaktivdir",
|
||||
"project.settings.extensions.lsp.disabled.description": "LSP bu layihənin konfiqurasiyasında deaktiv edilmişdir",
|
||||
"project.settings.extensions.lsp.loadFailed": "Dil serverinin konfiqurasiyasını yükləmək mümkün olmadı",
|
||||
"project.settings.extensions.lsp.retry": "Yenidən cəhd et",
|
||||
"settings.timeline.summary": "{{preset}}:",
|
||||
"settings.timeline.group": "Qrup",
|
||||
"settings.timeline.collapse": "Yığı",
|
||||
"settings.timeline.visibility.show": "Göstər",
|
||||
"settings.timeline.visibility.hide": "Gizlət",
|
||||
"settings.timeline.visibility.label": "{{activity}} görünüşü",
|
||||
"settings.timeline.grouped.label": "{{activity}} qruplaşdırılmış",
|
||||
"settings.timeline.collapsed.label": "{{activity}} çöktü",
|
||||
"session.new.workspace.search.empty": "Uyğun iş ağacları yoxdur",
|
||||
"settings.workspaces.description": "İş ağaclarını nəzərdən keçirin və disk istifadəsini idarə edin",
|
||||
"settings.workspaces.empty.description": "OpenCode-da yaradılan iş ağacları burada görünəcək",
|
||||
"settings.workspaces.sessions.filtered.one": "{{count}} sessiya",
|
||||
"settings.workspaces.sessions.filtered.other": "{{count}} sessiyalar",
|
||||
"settings.workspaces.deleteAll.confirm.one": "Bu, seçilmiş {{count}} iş ağacını daimi olaraq siləcək.",
|
||||
"settings.workspaces.deleteAll.confirm.other": "Bu, seçilmiş {{count}} iş ağaclarını daimi olaraq siləcək.",
|
||||
"settings.workspaces.deleteWithoutSessions": "Sessiyasız iş ağaclarını silmək",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"Bu, {{count}} sessiya ilə əlaqəsi olmayan iş ağacını daimi olaraq siləcək.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"Bu, {{count}} sessiya ilə əlaqəsi olmayan iş ağaclarını daimi olaraq siləcək.",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"Birləşdirilməmiş dəyişiklikləri və ya aktiv yerləri olan iş ağacları saxlanılacaq.",
|
||||
"settings.workspaces.delete.button": "İş ağaclarını silmək",
|
||||
"workspace.lifecycle.deleting": "Silinir…",
|
||||
"session.summary.tooltip": "Xülasə",
|
||||
"session.summary.server": "Genişlənmələr",
|
||||
"session.summary.chooseProject": "Layihə seçin",
|
||||
"session.summary.mcp.onCreation": "İş ağacı yaradıldıqda tətbiq olunur",
|
||||
"session.summary.mcp.prepareFailed": "MCP serverlərini hazırlamaq mümkün olmadı",
|
||||
"session.summary.mcp.unavailable": "MCP serveri {{name}} bu iş ağacında mövcud deyil.",
|
||||
"session.summary.mcp.signInBeforeSend": "Promtu göndərmədən əvvəl {{name}} hesabınıza daxil olun.",
|
||||
"session.summary.mcp.notReady":
|
||||
"MCP serveri {{name}} hazır deyil. Promtu göndərmədən əvvəl onun bağlantısını həll edin.",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "Konfiqurasiya edilmiş MCP serverləri",
|
||||
"session.summary.plugins": "Pluginlər",
|
||||
"session.summary.plugins.configured": "Konfiqurasiya edilmiş pluginlər",
|
||||
"session.summary.skills": "Bacarıqlar",
|
||||
"session.summary.skills.configured": "Konfiqurasiya edilmiş bacarıqlar",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "Uğursuz oldu",
|
||||
"session.summary.retry": "Təkrar cəhd et",
|
||||
"session.summary.connecting": "Qoşulur…",
|
||||
"session.summary.needsAuth": "Giriş tələb olunur",
|
||||
"session.summary.configure": "Konfiqurasiya faylı",
|
||||
"session.summary.copyConfigPath": "Konfiqurasiya faylı yolunu kopyala",
|
||||
"session.summary.configFileMissing": "Konfiqurasiya faylı tapılmadı",
|
||||
"session.summary.mcp.empty": "MCP serverləri konfiqurasiya edilməyib",
|
||||
"session.summary.mcp.add": "opencode.json faylında serverləri əlavə et",
|
||||
"session.summary.plugins.manage": "opencode.json-da plaginləri idarə et",
|
||||
"session.summary.plugins.empty": "Heç bir plagin qurulmayıb",
|
||||
"session.summary.plugins.add": "opencode.json-da plagin əlavə et",
|
||||
"session.summary.skills.manage": "opencode.json-da bacarıqları idarə et",
|
||||
"session.summary.skills.empty": "Heç bir bacarıq qurulmayıb",
|
||||
"session.summary.skills.add": "opencode.json-da bacarıq əlavə et",
|
||||
"session.summary.lsp.configured": "Qurulmuş LSP-lər",
|
||||
"session.summary.lsp.empty": "Heç bir LSP serveri qurulmayıb",
|
||||
"session.summary.lsp.manage": "opencode.json-da LSP-ni idarə et",
|
||||
"workspace.delete.location": "Yer",
|
||||
"command.debugBar.toggle": "Sazlama panelini göstər/gizlət",
|
||||
"command.session.location.cycle": "Sessiyanın yerini dəyiş",
|
||||
"dialog.provider.anthropic.note": "API açarı ilə Claude modellərinə birbaşa giriş",
|
||||
"provider.connect.title.anthropicProMax": "Anthropic ilə daxil olun",
|
||||
"prompt.toast.uploading.cancel": "Yükləməni ləğv et",
|
||||
"prompt.toast.uploading.cancelFile": "{{filename}} faylının yüklənməsini ləğv et",
|
||||
"prompt.toast.uploadFailed.title": "Yükləmə alınmadı",
|
||||
"session.browser.empty.title": "URL daxil edin",
|
||||
"session.browser.empty.description": "Və ya “Tətbiq brauzerində aç” sorğusunu göndərin",
|
||||
"session.browser.failed.title": "URL əlçatan deyil",
|
||||
"session.browser.failed.description": "URL-i və bağlantınızı yoxlayın, sonra yenidən cəhd edin.",
|
||||
"debugBar.providerAriaLabel": "Provayder performansının diaqnostikası",
|
||||
"debugBar.ttft.tip": "Provayder sorğusunun göndərilməsindən modelin ilk çıxışına qədər olan vaxt.",
|
||||
"debugBar.ttfa.tip": "Provayder sorğusunun göndərilməsindən cavabın ilk mətninə qədər olan vaxt.",
|
||||
"debugBar.tps.tip": "Modelin ilk çıxışından sonra saniyədə çıxış tokenlərinin sayı.",
|
||||
"debugBar.e2e.tip": "Provayder sorğusunun göndərilməsindən cavab axınının bitməsinə qədər olan vaxt.",
|
||||
"settings.updates.action.download": "OpenCode-u endir",
|
||||
"settings.updates.migration.title": "Beta-dan Stable-a keçin",
|
||||
"settings.updates.migration.description":
|
||||
"Hələlik OpenCode Beta, OpenCode Stable-a keçir. Yeniləmələri almağa davam etmək üçün {{version}} versiyasını endirin, sonra OpenCode-u disk obrazından quraşdırın.",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
}
|
||||
|
||||
@@ -1103,4 +1103,467 @@ export const dict = {
|
||||
"workspace.reset.archived.many": "{{count}} сесии ще бъдат архивирани.",
|
||||
"workspace.reset.note": "Това ще нулира работното пространство, за да съответства на клона по подразбиране.",
|
||||
"dialog.usageExceeded.dontShowAgain": "Не показвай отново",
|
||||
"provider.disconnect.toast.noCredentials.description":
|
||||
"Няма намерени подвижни идентификационни данни за {{provider}}.",
|
||||
"provider.disconnect.toast.failed.description": "Неуспешно прекъсване на връзката {{provider}}.",
|
||||
"toast.migration.failed.title": "Мигрирането на данни не бе успешно",
|
||||
"command.session.background": "Преместване на заден план",
|
||||
"session.timeline.notice.finished": "{{actor}} приключи",
|
||||
"session.timeline.notice.failed": "{{actor}} неуспешно",
|
||||
"session.timeline.notice.cancelled": "{{actor}} отменен",
|
||||
"settings.tab.preferences": "Предпочитания",
|
||||
"settings.tab.notifications": "Известия",
|
||||
"settings.tab.projects": "Проекти",
|
||||
"settings.tab.extensions": "Разширения",
|
||||
"settings.preferences.description": "Персонализирайте предпочитанията и темата и поведението по подразбиране",
|
||||
"settings.appearance.description": "Персонализирайте темата и шрифтовете",
|
||||
"settings.notifications.description": "Изберете кога да получавате известия и да чувате звуци",
|
||||
"settings.shortcuts.description": "Персонализирайте преки пътища за обичайни действия",
|
||||
"settings.servers.description": "Управлявайте връзките със сървъра",
|
||||
"settings.projects.title": "Проекти",
|
||||
"settings.projects.description": "Управление на настройките на проекта на този сървър",
|
||||
"settings.projects.empty": "Няма намерени проекти",
|
||||
"settings.projects.server.all": "Всички сървъри",
|
||||
"settings.mcps.description": "Управление на сървъри и инструменти на протокола за контекст на модела (MCP).",
|
||||
"settings.extensions.description": "Управление на разширенията, налични на този сървър",
|
||||
"settings.extensions.tab.mcps": "MCPs",
|
||||
"settings.extensions.tab.skills": "Умения",
|
||||
"settings.extensions.availableAll": "Предлага се за всички проекти",
|
||||
"settings.extensions.manageConfig": "Управление в opencode.json",
|
||||
"settings.extensions.addSkills": "Как да добавите умения",
|
||||
"dialog.server.authenticate.title": "Удостоверяване",
|
||||
"project.settings.general.description": "Управлявайте името и външния вид на проекта",
|
||||
"project.settings.scripts": "Скриптове",
|
||||
"project.settings.scripts.description": "Конфигуриране на скриптове за този проект",
|
||||
"project.settings.extensions.description": "Вижте разширенията, налични за този проект",
|
||||
"project.settings.extensions.tab.lsps": "LSPs",
|
||||
"project.settings.extensions.added": "Добавен към този проект",
|
||||
"project.settings.extensions.shared": "Споделено с всички проекти",
|
||||
"project.settings.extensions.lsp.detected": "Открити езикови сървъри",
|
||||
"project.settings.extensions.lsp.description": "Автоматично разпознаване от типове файлове",
|
||||
"project.settings.extensions.setupRequired": "Изисква се настройка",
|
||||
"settings.general.section.general": "Общи",
|
||||
"common.viewAll": "Вижте всички",
|
||||
"session.new.workspace.local.tooltip": "Използвайте текущото работно копие",
|
||||
"session.new.workspace.new.tooltip": "Създайте изолирано работно копие",
|
||||
"session.new.workspace.fromBranch": "от {{branch}}",
|
||||
"session.new.workspace.trigger.tooltip": "Изберете къде да стартирате сесията",
|
||||
"session.new.workspace.search.placeholder": "Търсете работни пространства",
|
||||
"settings.tab.workspaces": "Работни пространства",
|
||||
"settings.workspaces.filter.all": "Всички проекти",
|
||||
"settings.workspaces.empty": "Няма работни пространства",
|
||||
"settings.workspaces.count.one": "{{count}} работно пространство",
|
||||
"settings.workspaces.count.other": "{{count}} работни пространства",
|
||||
"settings.workspaces.sessions.one": "{{count}} сесия в {{project}}",
|
||||
"settings.workspaces.sessions.other": "{{count}} сесии в {{project}}",
|
||||
"settings.workspaces.lastActiveSession": "Последна активна сесия",
|
||||
"settings.workspaces.deleteAll": "Изтрийте всички работни области",
|
||||
"settings.workspaces.delete.warning":
|
||||
"Директорията и клонът на работното пространство ще бъдат премахнати за постоянно, включително всички необединени промени, показани по-долу.",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"Работните дървета с неслети промени, свързани сесии или активни местоположения ще бъдат запазени.",
|
||||
"settings.workspaces.delete.blocked.active": "Активното работно пространство не може да бъде изтрито.",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"Свързаните сесии ще останат, но тяхната работна директория ще бъде премахната за постоянно.",
|
||||
"settings.workspaces.default.title": "Среда по подразбиране",
|
||||
"settings.workspaces.default.description": "Изберете къде започват новите сесии",
|
||||
"settings.workspaces.default.lastUsed": "Последно използвано за проект",
|
||||
"settings.workspaces.default.local": "Локален указател",
|
||||
"settings.workspaces.default.new": "Ново работно пространство",
|
||||
"workspace.move.title": "Преместете се в работното пространство",
|
||||
"workspace.move.menu.title": "Преместване на сесията към",
|
||||
"workspace.move.failed": "Преместването на сесията не бе успешно",
|
||||
"workspace.lifecycle.creating": "Създаване на работно пространство",
|
||||
"workspace.lifecycle.created": "Работното пространство е създадено",
|
||||
"workspace.lifecycle.starting": "Начална сесия",
|
||||
"workspace.onboarding.title": "Изолирайте сесиите с работни пространства",
|
||||
"workspace.onboarding.description":
|
||||
"Всяко получава собствено работно копие, така че нищо да не пречи на локалното ви хранилище",
|
||||
"workspace.lifecycle.moving": "Преминаване към работното пространство",
|
||||
"workspace.lifecycle.set": "Работното пространство е зададено",
|
||||
"session.summary.title": "Подробности за сесията",
|
||||
"session.summary.noBranch": "Няма клон",
|
||||
"session.summary.basedOn": "Въз основа на {{branch}}",
|
||||
"desktop.menu.installCli": "Инсталиране на CLI...",
|
||||
"desktop.cli.installed.title": "CLI е инсталиран",
|
||||
"desktop.cli.installed.message":
|
||||
"CLI е инсталиран в {{path}}\n\nРестартирайте терминала, за да използвате командата 'opencode2'.",
|
||||
"desktop.cli.failed.title": "Неуспешна инсталация",
|
||||
"desktop.cli.failed.message": "CLI не можа да бъде инсталиран: {{error}}",
|
||||
"command.project.copyID": "Копиране на идентификатора на проекта",
|
||||
"command.session.copyID": "Копиране на идентификатора на сесията",
|
||||
"server.row.incompatible":
|
||||
"Този сървър работи с OpenCode {{version}}, който не е съвместим с приложението. Надстройте го до OpenCode V2, за да продължите.",
|
||||
"toast.session.copyID.failed.title": "Идентификаторът на сесията не можа да бъде копиран",
|
||||
"toast.session.copyID.failed.description": "Възникна грешка при копирането на идентификатора на сесията",
|
||||
"toast.project.copyID.failed.title": "Идентификаторът на проекта не можа да бъде копиран",
|
||||
"toast.project.copyID.failed.description": "Възникна грешка при копирането на идентификатора на проекта",
|
||||
"error.page.title.status": "Заявката към сървъра е неуспешна",
|
||||
"error.page.description.status": "Сървърът върна HTTP отговор {{status}}.",
|
||||
"error.page.action.reload": "Презареждане",
|
||||
"session.error.incompatible": "Тази версия на сървъра не се поддържа",
|
||||
"session.error.incompatible.description":
|
||||
"{{server}} работи с OpenCode {{version}}, който не е съвместим с приложението. Надстройте сървъра до OpenCode V2, за да продължите.",
|
||||
"session.background.moveInline": "Натиснете {{keybind}}, за да преместите текущата работа във фонов режим",
|
||||
"session.background.running": "Работата се изпълнява във фонов режим",
|
||||
"session.background.runningCount.one": "{{count}} задача се изпълнява във фонов режим",
|
||||
"session.background.runningCount.other": "{{count}} задачи се изпълняват във фонов режим",
|
||||
"settings.general.row.terminalPlacement.title": "Разположение на терминала",
|
||||
"settings.general.row.terminalPlacement.description": "Изберете къде да се отваря терминалът в сесиите",
|
||||
"settings.general.row.terminalPlacement.side": "Отстрани",
|
||||
"settings.general.row.terminalPlacement.bottom": "Отдолу",
|
||||
"session.location.unavailable": "Местоположението на сесията не е достъпно",
|
||||
"session.location.description": "Изберете друга директория, за да продължите тази сесия.",
|
||||
"session.location.choose": "Изберете директория",
|
||||
"session.location.worktree": "Изберете работно дърво",
|
||||
"session.location.worktreesFailed": "Работните дървета не можаха да се заредят",
|
||||
"session.location.moving": "Преместване на сесията…",
|
||||
"dialog.server.menu.hide": "Скриване от списъка с проекти",
|
||||
"dialog.server.menu.show": "Показване в списъка с проекти",
|
||||
"session.queue.count.one": "{{count}} заявка на опашката",
|
||||
"session.queue.count.other": "{{count}} заявки на опашката",
|
||||
"session.queue.steer": "Насочи",
|
||||
"session.queue.send": "Изпрати",
|
||||
"session.queue.steerTooltip": "Изпращане без прекъсване",
|
||||
"session.queue.remove": "Премахни",
|
||||
"session.queue.reorder": "Пренареждане на заявката в опашката",
|
||||
"session.new.worktree.creating": "Създаване на работно дърво",
|
||||
"settings.backToApp": "Назад към приложението",
|
||||
"settings.appearance.section.experimental": "Експериментални",
|
||||
"settings.appearance.row.tabs.title": "Раздели",
|
||||
"settings.appearance.row.tabs.description": "Изберете как да бъдат подредени разделите на сесиите",
|
||||
"settings.appearance.row.tabs.horizontal": "Хоризонтално",
|
||||
"settings.appearance.row.tabs.vertical": "Вертикално",
|
||||
"settings.general.row.followUpBehavior.title": "Поведение на последващите съобщения",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"Изберете дали последващите съобщения да се поставят на опашка, или да насочват текущия ход. Използвайте {{keybind}} за превключване.",
|
||||
"settings.general.row.followUpBehavior.queue": "Поставяне на опашка",
|
||||
"settings.general.row.followUpBehavior.steer": "Насочване",
|
||||
"settings.general.row.reasoningMode.title": "Разсъждение на модела",
|
||||
"settings.general.row.reasoningMode.description":
|
||||
"Изберете как да се показва разсъждението на модела във времевата линия",
|
||||
"settings.general.row.reasoningMode.hidden": "Скрито",
|
||||
"settings.general.row.reasoningMode.compact": "Компактно",
|
||||
"settings.general.row.reasoningMode.full": "Пълно",
|
||||
"session.new.workspace.createFrom": "Създаване от клон",
|
||||
"session.new.workspace.branch.search.placeholder": "Търсене на клонове",
|
||||
"desktop.onboarding.defaultProject": "Проект по подразбиране",
|
||||
"toast.migration.progress.clearingOldEvents": "Изчистване на стари събития",
|
||||
"toast.migration.progress.migratingSessions": "Мигриране на сесии",
|
||||
"session.new.workspace.existingLabel": "Работно дърво",
|
||||
"home.projects.all": "Всички проекти",
|
||||
"session.tab.files": "Файлове",
|
||||
"session.files.openTabs": "Отворени файлове",
|
||||
"session.tab.usage": "Използване",
|
||||
"session.view.select": "Изглед на сесията",
|
||||
"session.background.moveTasks": "Преместете {{tasks}} на заден план",
|
||||
"session.background.moveRunning": "Преместване на заден план",
|
||||
"session.background.inBackground": "Работи {{tasks}} във фонов режим",
|
||||
"session.background.tasksRunning.one": "{{count}} фонова задача се изпълнява",
|
||||
"session.background.tasksRunning.other": "{{count}} фонови задачи се изпълняват",
|
||||
"session.background.combine": "{{first}} и {{second}}",
|
||||
"session.background.shell.one": "{{count}} обвивка",
|
||||
"session.background.shell.other": "{{count}} обвивки",
|
||||
"session.background.subagent.one": "{{count}} подагент",
|
||||
"session.background.subagent.other": "{{count}} подагенти",
|
||||
"session.timeline.working": "Работи",
|
||||
"session.review.wrapLines": "Пренасяне на редовете",
|
||||
"session.websearch.title": "Уеб търсене на трети страни",
|
||||
"session.websearch.description": "Изберете доставчика на търсене, който агентите използват за търсене в мрежата",
|
||||
"session.websearch.provider": "Доставчик на търсене",
|
||||
"session.websearch.any": "Всеки",
|
||||
"session.websearch.disable": "Не използвайте търсене",
|
||||
"session.websearch.enable": "Активиране",
|
||||
"session.websearch.loadFailed": "Не можа да зареди доставчиците на търсене.",
|
||||
"session.websearch.empty": "Няма налични доставчици на търсене.",
|
||||
"session.websearch.failed": "Не можах да запазя вашия избор. Моля, опитайте отново.",
|
||||
"session.websearch.retry": "Опитайте отново",
|
||||
"session.new.worktree.draftPlaceholder": "Напишете последващо съобщение, докато работното дърво се подготвя…",
|
||||
"session.search.placeholder": "Намери...",
|
||||
"session.search.noResults": "Няма съвпадения",
|
||||
"titlebar.tabs": "Раздели",
|
||||
"titlebar.channel.local": "Локално",
|
||||
"titlebar.channel.dev": "Dev",
|
||||
"titlebar.channel.beta": "Beta",
|
||||
"titlebar.toggleDebugTools": "Превключване на инструментите за отстраняване на грешки",
|
||||
"settings.tab.experimental": "Експериментален",
|
||||
"settings.experimental.description": "Опитайте експериментални функции",
|
||||
"settings.tab.about": "Относно",
|
||||
"settings.about.version": "Версия {{version}}",
|
||||
"settings.about.devVersion": "развитие",
|
||||
"settings.about.license": "Издаден под MIT License",
|
||||
"settings.about.writtenBy": "Написано от",
|
||||
"settings.about.illustratedBy": "Илюстрирано от",
|
||||
"settings.about.and": "и",
|
||||
"settings.about.otherContributor.one": "{{count}} друг",
|
||||
"settings.about.otherContributor.other": "{{count}} други",
|
||||
"settings.about.firstPublished": "Първо публикувано в Мисури, САЩ",
|
||||
"settings.about.firstIllustrated": "Първо илюстрирано в Лондон, Англия",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode, агентът за кодиране с отворен код",
|
||||
"settings.about.trademark": "OpenCode е регистрирана търговска марка на Anomaly Innovations, Inc.",
|
||||
"settings.about.typeset": "Набор в Inter и IBM Plex Mono",
|
||||
"settings.about.tagline": "AI не може да създаде страхотен софтуер без вас",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "Редактиране на проект",
|
||||
"settings.timeline.title": "Хронология",
|
||||
"settings.timeline.detail": "Подробности за времевата линия",
|
||||
"settings.timeline.description":
|
||||
"Изберете колко активност да се показва във времевата линия. Съобщенията остават видими.",
|
||||
"settings.timeline.preset.everything": "Всичко",
|
||||
"settings.timeline.preset.detailed": "Подробно",
|
||||
"settings.timeline.preset.compact": "Компактен",
|
||||
"settings.timeline.preset.quiet": "Тихо",
|
||||
"settings.timeline.preset.text-only": "Само текст",
|
||||
"settings.timeline.description.everything":
|
||||
"Покажи цялата дейност отделно. Разширете изхода на shell, редакциите и мисленето.",
|
||||
"settings.timeline.description.detailed":
|
||||
"Разширете изхода и редакциите на обвивката. Покажете подагенти отделно и групирайте друга дейност в Използвани.",
|
||||
"settings.timeline.description.compact": "Групирайте цялата активност в Използвани със свити подробности.",
|
||||
"settings.timeline.description.quiet": "Групови редакции и подагенти в Използвани. Скриване на друга дейност.",
|
||||
"settings.timeline.description.text-only": "Скриване на цялата активност. Показване само на съобщения.",
|
||||
"settings.timeline.description.custom":
|
||||
"Използвайте избраното от вас разположение и подробности за всяка категория дейност.",
|
||||
"settings.timeline.custom": "Персонализирано",
|
||||
"settings.timeline.advanced": "Разширено",
|
||||
"settings.timeline.advanced.description": "Задайте разположение и подробности за всяка категория дейност.",
|
||||
"settings.timeline.category.shell": "Черупка",
|
||||
"settings.timeline.category.edit": "Редакции",
|
||||
"settings.timeline.category.thinking": "Мислене",
|
||||
"settings.timeline.category.subagents": "Субагенти",
|
||||
"settings.timeline.category.notices": "Бележки",
|
||||
"settings.timeline.category.tools": "Други инструменти",
|
||||
"settings.general.row.mobileDiffWrap.description":
|
||||
"Увийте дълги редове в мобилни разлики, вместо да превъртате хоризонтално",
|
||||
"provider.connect.error.unsupportedFields": "Този формуляр за удостоверяване съдържа неподдържани полета",
|
||||
"session.review.filesChangedCount.one": "{{count}} файл е променен",
|
||||
"session.review.filesChangedCount.other": "{{count}} файла са променени",
|
||||
"settings.about.writtenByNames": "Написано от {{names}}",
|
||||
"settings.about.illustratedByNames": "Илюстрирано от {{names}}",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline":
|
||||
"Няма връзка с {{host}}. Черновата ви е запазена; работата на отдалечения сървър може все още да се изпълнява.",
|
||||
"ssh.placeholder": "ssh user@example.com",
|
||||
"ssh.add": "Добавяне на SSH сървър",
|
||||
"ssh.server.menu.label": "SSH сървър",
|
||||
"ssh.target": "Хост или SSH команда",
|
||||
"ssh.connect": "Свързване",
|
||||
"ssh.connectTo": "Свързване с {{host}}",
|
||||
"ssh.authenticate": "SSH удостоверяване",
|
||||
"ssh.action.authenticate": "Удостоверяване",
|
||||
"ssh.session.disconnected": "SSH връзката не е активна",
|
||||
"ssh.session.connecting": "Свързване с SSH сървъра",
|
||||
"ssh.session.reconnectDescription":
|
||||
"Свържете се отново, за да видите тази сесия и да продължите работа. Отдалечената ви сесия е запазена.",
|
||||
"ssh.session.reconnect": "Повторно свързване",
|
||||
"ssh.authenticationRequired": "Изисква се удостоверяване за {{host}}",
|
||||
"ssh.trust": "Доверяване и свързване",
|
||||
"ssh.continue": "Продължаване",
|
||||
"ssh.retry": "Повторен опит",
|
||||
"ssh.update": "Актуализиране и повторно свързване",
|
||||
"ssh.openProject": "Отваряне на проект",
|
||||
"ssh.project": "Отваряне на проект на {{host}}",
|
||||
"ssh.disconnect": "Прекъсване на връзката",
|
||||
"ssh.forget": "Забравяне на връзката",
|
||||
"ssh.stage.disconnected": "Връзката е прекъсната. Отдалеченият сървър продължава да работи.",
|
||||
"ssh.stage.connecting": "Свързване чрез SSH…",
|
||||
"ssh.stage.checking": "Проверка на OpenCode…",
|
||||
"ssh.stage.downloading": "Изтегляне на сървъра…",
|
||||
"ssh.stage.uploading": "Качване на сървъра…",
|
||||
"ssh.stage.starting": "Свързване с OpenCode…",
|
||||
"ssh.stage.ready": "Свързано",
|
||||
"ssh.stage.authentication": "Изисква се удостоверяване",
|
||||
"ssh.stage.incompatible": "Изисква се актуализация на сървъра",
|
||||
"ssh.stage.failed": "Неуспешно свързване",
|
||||
"ssh.error.input":
|
||||
"Въведете хост или команда за SSH връзка. Не се допускат отдалечени команди и неподдържани SSH опции.",
|
||||
"ssh.error.connection": "SSH връзката не можа да бъде установена. Проверете мрежата и SSH конфигурацията си.",
|
||||
"ssh.error.platform":
|
||||
"Тази отдалечена платформа не се поддържа. Автоматичната настройка в момента изисква Linux или macOS на x64 или arm64.",
|
||||
"ssh.error.version":
|
||||
"Отдалечената услуга трябва да съответства на тази версия на настолното приложение, преди да се свържете.",
|
||||
"ssh.error.install":
|
||||
"Отдалеченият сървър не можа да бъде инсталиран. Проверете свързаността, свободното място и дали tar е инсталиран.",
|
||||
"ssh.error.unpublished":
|
||||
"За тази версия на настолното приложение няма публикуван отдалечен сървър. За развойни компилации инсталирайте и стартирайте V2 на хоста, след което опитайте отново.",
|
||||
"ssh.error.service": "SSH връзката е установена, но сървърът на OpenCode не е готов.",
|
||||
"ssh.error.host-key":
|
||||
"Самоличността на хоста не можа да бъде потвърдена. Проверете отпечатъка му, преди да актуализирате познатите SSH хостове.",
|
||||
"ssh.error.ssh-missing": "OpenSSH не е намерен. Инсталирайте OpenSSH клиент и се уверете, че ssh е наличен в PATH.",
|
||||
"command.browser.open": "Отваряне на браузъра",
|
||||
"command.browser.reload": "Презареждане на страницата в браузъра",
|
||||
"command.session.summary.toggle": "Превключване на обобщението",
|
||||
"common.color.orange": "оранжево",
|
||||
"common.color.yellow": "жълто",
|
||||
"common.color.cyan": "циан",
|
||||
"common.color.green": "зелено",
|
||||
"common.color.red": "червено",
|
||||
"common.color.pink": "розово",
|
||||
"common.color.blue": "синьо",
|
||||
"common.color.purple": "лилаво",
|
||||
"common.color.gray": "сиво",
|
||||
"mcp.auth.interactiveForm": "MCP сървърът {{name}} изисква интерактивен формуляр за удостоверяване",
|
||||
"server.connect.title": "Свързване със сървър",
|
||||
"server.connect.description": "Въведете адреса и паролата на сървъра, за да започнете.",
|
||||
"server.connect.button": "Свързване",
|
||||
"server.connect.address.invalid": "Въведете валиден HTTP или HTTPS адрес на сървър.",
|
||||
"server.connect.failed": "Свързването е неуспешно. Проверете адреса и паролата на сървъра и опитайте отново.",
|
||||
"server.connect.pair.description": "Изпълнете тази команда на компютъра си, за да получите данните за връзка.",
|
||||
"server.connect.scan": "Сканиране на QR код",
|
||||
"server.connect.scan.description": "Насочете камерата към QR кода, показан от opencode pair.",
|
||||
"server.connect.scan.invalid": "Това не е код за сдвояване с OpenCode. Сканирайте кода, показан от opencode pair.",
|
||||
"server.connect.camera": "Камера за сдвояване",
|
||||
"server.connect.camera.starting": "Отваряне на камерата…",
|
||||
"server.connect.mixedContent":
|
||||
"Не може да се осъществи връзка с този HTTP сървър от HTTPS страница. Използвайте HTTPS адрес на сървъра.",
|
||||
"server.connect.camera.insecure":
|
||||
"Сканирането на QR код изисква тази страница да е отворена чрез HTTPS или на localhost.",
|
||||
"server.connect.camera.unavailable": "Няма достъпна камера за този браузър. Въведете ръчно данните за връзка.",
|
||||
"server.connect.camera.error":
|
||||
"Камерата не можа да бъде отворена. Разрешете достъпа до нея или въведете ръчно данните за връзка.",
|
||||
"dialog.server.menu.remove": "Премахване",
|
||||
"file.error.notFound": "Файлът не е намерен: {{name}}",
|
||||
"toast.migration.progress.migratingSessions.current": "Мигриране на сесии {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "Мигриране на сесии {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "Мигриране на данни",
|
||||
"toast.migration.progress.working.current": "Мигриране на данни {{current}}",
|
||||
"toast.migration.progress.working.progress": "Мигриране на данни {{current}}/{{total}}",
|
||||
"home.workspaceTip": "Започнете следващата сесия в ново работно пространство, за да запазите промените изолирани",
|
||||
"session.tab.browser": "Браузър",
|
||||
"session.tab.add": "Добавяне на раздел",
|
||||
"session.queue.attachments.one": "Плюс {{count}} прикачен файл",
|
||||
"session.queue.attachments.other": "Плюс {{count}} прикачени файла",
|
||||
"session.browser.address": "Адрес на браузъра",
|
||||
"session.browser.replaced": "Управлението на браузъра е преместено в друг прозорец на настолното приложение.",
|
||||
"session.browser.unsupported": "Това настолно приложение не поддържа панела на браузъра.",
|
||||
"session.browser.suspended": "Браузърът е спрян временно. Взаимодействайте с тази сесия, за да се свържете отново.",
|
||||
"session.browser.address.placeholder": "Въведете URL адрес",
|
||||
"settings.backToSettings": "Назад към настройките",
|
||||
"settings.backToProjects": "Назад към проектите",
|
||||
"settings.search.placeholder": "Търсене",
|
||||
"settings.search.results": "Резултати от настройките",
|
||||
"settings.search.group.pages": "Страници",
|
||||
"settings.search.group.settings": "Настройки",
|
||||
"settings.search.group.projects": "Проекти",
|
||||
"settings.search.group.servers": "Сървъри",
|
||||
"settings.search.result": "{{title}}, {{scope}}, {{page}}",
|
||||
"settings.search.page": "{{title}}, {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}, {{page}}",
|
||||
"settings.search.empty": "Няма резултати за {{query}}",
|
||||
"settings.search.empty.query": "„{{query}}“",
|
||||
"settings.search.refine": "Стеснете търсенето, за да видите по-конкретни резултати.",
|
||||
"settings.server.description": "Управление на връзката и предпочитанията на този сървър",
|
||||
"settings.server.section.connection": "Връзка",
|
||||
"settings.server.preferences.websearch.title": "Търсене чрез трета страна",
|
||||
"settings.server.preferences.websearch.description":
|
||||
"Изберете доставчика, който агентите използват за търсене в уеб пространството",
|
||||
"settings.projects.search.placeholder": "Търсене на проекти",
|
||||
"project.settings.name.title": "Име на проекта",
|
||||
"project.settings.name.description": "Името, което се показва за този проект в OpenCode",
|
||||
"project.settings.icon.description": "Препоръчително: 128×128 px. Щракнете или плъзнете, за да качите изображение.",
|
||||
"project.settings.color.description":
|
||||
"Използва се за иконата на проекта, когато няма зададено персонализирано изображение",
|
||||
"project.settings.worktree.startup.description": "Изпълнява се веднъж след създаването на ново работно дърво",
|
||||
"project.settings.worktree.startup.hint.base": "Използвайте $OPENCODE_WORKTREE_BASE за основното работно дърво.",
|
||||
"project.settings.worktree.startup.hint.new": "Използвайте $OPENCODE_WORKTREE_PATH за новото работно дърво.",
|
||||
"project.settings.extensions.empty.mcps.title": "Все още няма MCP сървъри",
|
||||
"project.settings.extensions.empty.mcps.description": "Наличните за OpenCode MCP сървъри ще се показват тук",
|
||||
"project.settings.extensions.empty.plugins.title": "Все още няма добавки",
|
||||
"project.settings.extensions.empty.plugins.description": "Наличните за OpenCode добавки ще се показват тук",
|
||||
"project.settings.extensions.empty.skills.title": "Все още няма умения",
|
||||
"project.settings.extensions.empty.skills.description": "Наличните за OpenCode умения ще се показват тук",
|
||||
"project.settings.extensions.lsp.configured": "Конфигурирани езикови сървъри",
|
||||
"project.settings.extensions.lsp.status.enabled": "Активиран в конфигурацията",
|
||||
"project.settings.extensions.lsp.status.disabled": "Деактивиран в конфигурацията",
|
||||
"project.settings.extensions.lsp.empty.title": "Няма конфигурирани езикови сървъри",
|
||||
"project.settings.extensions.lsp.empty.description":
|
||||
"Езиковите сървъри, конфигурирани за този проект, ще се показват тук",
|
||||
"project.settings.extensions.lsp.disabled.title": "Езиковите сървъри са деактивирани",
|
||||
"project.settings.extensions.lsp.disabled.description": "LSP е деактивиран в конфигурацията на този проект",
|
||||
"project.settings.extensions.lsp.loadFailed": "Конфигурацията на езиковите сървъри не можа да бъде заредена",
|
||||
"project.settings.extensions.lsp.retry": "Повторен опит",
|
||||
"settings.timeline.summary": "{{preset}}:",
|
||||
"settings.timeline.group": "Групиране",
|
||||
"settings.timeline.collapse": "Свиване",
|
||||
"settings.timeline.visibility.show": "Показване",
|
||||
"settings.timeline.visibility.hide": "Скриване",
|
||||
"settings.timeline.visibility.label": "Видимост на {{activity}}",
|
||||
"settings.timeline.grouped.label": "{{activity}} е групирано",
|
||||
"settings.timeline.collapsed.label": "{{activity}} е свито",
|
||||
"session.new.workspace.search.empty": "Няма съответстващи работни дървета",
|
||||
"settings.workspaces.description": "Преглед на работните дървета и управление на дисковото пространство",
|
||||
"settings.workspaces.empty.description": "Създадените в OpenCode работни дървета ще се показват тук",
|
||||
"settings.workspaces.sessions.filtered.one": "{{count}} сесия",
|
||||
"settings.workspaces.sessions.filtered.other": "{{count}} сесии",
|
||||
"settings.workspaces.deleteAll.confirm.one": "Това ще изтрие окончателно {{count}} избрано работно дърво.",
|
||||
"settings.workspaces.deleteAll.confirm.other": "Това ще изтрие окончателно {{count}} избрани работни дървета.",
|
||||
"settings.workspaces.deleteWithoutSessions": "Изтриване на работни дървета без сесии",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"Това ще изтрие окончателно {{count}} работно дърво без свързани сесии.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"Това ще изтрие окончателно {{count}} работни дървета без свързани сесии.",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"Работните дървета с неслети промени или активни местоположения ще бъдат запазени.",
|
||||
"settings.workspaces.delete.button": "Изтриване на работните дървета",
|
||||
"workspace.lifecycle.deleting": "Изтриване…",
|
||||
"session.summary.tooltip": "Обобщение",
|
||||
"session.summary.server": "Разширения",
|
||||
"session.summary.chooseProject": "Изберете проект",
|
||||
"session.summary.mcp.onCreation": "Прилага се при създаването на работното дърво",
|
||||
"session.summary.mcp.prepareFailed": "MCP сървърите не можаха да бъдат подготвени",
|
||||
"session.summary.mcp.unavailable": "MCP сървърът {{name}} не е наличен в това работно дърво.",
|
||||
"session.summary.mcp.signInBeforeSend": "Влезте в {{name}}, преди да изпратите подканата.",
|
||||
"session.summary.mcp.notReady":
|
||||
"MCP сървърът {{name}} не е готов. Отстранете проблема с връзката му, преди да изпратите подканата.",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "Конфигурирани MCP сървъри",
|
||||
"session.summary.plugins": "Добавки",
|
||||
"session.summary.plugins.configured": "Конфигурирани добавки",
|
||||
"session.summary.skills": "Умения",
|
||||
"session.summary.skills.configured": "Конфигурирани умения",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "Неуспешно",
|
||||
"session.summary.retry": "Повторен опит",
|
||||
"session.summary.connecting": "Свързване…",
|
||||
"session.summary.needsAuth": "Изисква се влизане",
|
||||
"session.summary.configure": "Конфигурационен файл",
|
||||
"session.summary.copyConfigPath": "Копиране на пътя до конфигурационния файл",
|
||||
"session.summary.configFileMissing": "Не е намерен конфигурационен файл",
|
||||
"session.summary.mcp.empty": "Няма конфигурирани MCP сървъри",
|
||||
"session.summary.mcp.add": "Добавете сървъри в opencode.json",
|
||||
"session.summary.plugins.manage": "Управление на добавките в opencode.json",
|
||||
"session.summary.plugins.empty": "Няма конфигурирани добавки",
|
||||
"session.summary.plugins.add": "Добавете добавки в opencode.json",
|
||||
"session.summary.skills.manage": "Управление на уменията в opencode.json",
|
||||
"session.summary.skills.empty": "Няма конфигурирани умения",
|
||||
"session.summary.skills.add": "Добавете умения в opencode.json",
|
||||
"session.summary.lsp.configured": "Конфигурирани LSP сървъри",
|
||||
"session.summary.lsp.empty": "Няма конфигурирани LSP сървъри",
|
||||
"session.summary.lsp.manage": "Управление на LSP в opencode.json",
|
||||
"workspace.delete.location": "Местоположение",
|
||||
"command.debugBar.toggle": "Превключване на лентата за отстраняване на грешки",
|
||||
"command.session.location.cycle": "Смяна на местоположението на сесията",
|
||||
"dialog.provider.anthropic.note": "Директен достъп до моделите Claude чрез API ключ",
|
||||
"provider.connect.title.anthropicProMax": "Вход с Anthropic",
|
||||
"prompt.toast.uploading.cancel": "Отказ от качването",
|
||||
"prompt.toast.uploading.cancelFile": "Отказ от качването на {{filename}}",
|
||||
"prompt.toast.uploadFailed.title": "Качването е неуспешно",
|
||||
"session.browser.empty.title": "Въведете URL адрес",
|
||||
"session.browser.empty.description": "Или подайте подкана „Отвори в браузъра на приложението“",
|
||||
"session.browser.failed.title": "URL адресът не е достъпен",
|
||||
"session.browser.failed.description": "Проверете URL адреса и връзката си, след което опитайте отново.",
|
||||
"debugBar.providerAriaLabel": "Диагностика на производителността на доставчика",
|
||||
"debugBar.ttft.tip": "Време от изпращането на заявката към доставчика до първия изход от модела.",
|
||||
"debugBar.ttfa.tip": "Време от изпращането на заявката към доставчика до първия текст на отговора.",
|
||||
"debugBar.tps.tip": "Изходни токени в секунда след първия изход от модела.",
|
||||
"debugBar.e2e.tip": "Време от изпращането на заявката към доставчика до края на потока с отговора.",
|
||||
"settings.updates.action.download": "Изтегляне на OpenCode",
|
||||
"settings.updates.migration.title": "Преминаване от Beta към Stable",
|
||||
"settings.updates.migration.description":
|
||||
"Засега OpenCode Beta преминава към OpenCode Stable. Изтеглете версия {{version}}, след което инсталирайте OpenCode от дисковия образ, за да продължите да получавате актуализации.",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
}
|
||||
|
||||
@@ -1086,4 +1086,461 @@ export const dict: Record<string, string> = {
|
||||
"workspace.reset.archived.many": "{{count}} সেশন আর্কাইভ করা হবে।",
|
||||
"workspace.reset.note": "এটি ডিফল্ট শাখার সাথে মেলে ওয়ার্কস্পেস রিসেট করবে।",
|
||||
"dialog.usageExceeded.dontShowAgain": "আবার দেখাবেন না",
|
||||
"toast.migration.failed.title": "ডেটা মাইগ্রেশন ব্যর্থ হয়েছে",
|
||||
"command.session.background": "ব্যাকগ্রাউন্ডে সরান",
|
||||
"session.timeline.notice.finished": "{{actor}} শেষ করেছে",
|
||||
"session.timeline.notice.failed": "{{actor}} ব্যর্থ হয়েছে",
|
||||
"session.timeline.notice.cancelled": "{{actor}} বাতিল হয়েছে",
|
||||
"settings.tab.preferences": "পছন্দসমূহ",
|
||||
"settings.tab.notifications": "বিজ্ঞপ্তি",
|
||||
"settings.tab.projects": "প্রকল্প",
|
||||
"settings.tab.extensions": "এক্সটেনশন",
|
||||
"settings.preferences.description": "পছন্দ, থিম এবং ডিফল্ট আচরণ কাস্টমাইজ করুন",
|
||||
"settings.appearance.description": "থিম এবং ফন্ট কাস্টমাইজ করুন",
|
||||
"settings.notifications.description": "কখন বিজ্ঞপ্তি পাবেন ও শব্দ শুনবেন তা বেছে নিন",
|
||||
"settings.shortcuts.description": "সাধারণ কাজের শর্টকাট কাস্টমাইজ করুন",
|
||||
"settings.servers.description": "সার্ভার সংযোগ পরিচালনা করুন",
|
||||
"settings.projects.title": "প্রকল্প",
|
||||
"settings.projects.description": "এই সার্ভারের প্রকল্প সেটিংস পরিচালনা করুন",
|
||||
"settings.projects.empty": "কোনো প্রকল্প পাওয়া যায়নি",
|
||||
"settings.projects.server.all": "সব সার্ভার",
|
||||
"settings.mcps.description": "Model Context Protocol (MCP) সার্ভার ও টুল পরিচালনা করুন",
|
||||
"settings.extensions.description": "এই সার্ভারে উপলভ্য এক্সটেনশন পরিচালনা করুন",
|
||||
"settings.extensions.tab.mcps": "MCPs",
|
||||
"settings.extensions.tab.skills": "স্কিল",
|
||||
"settings.extensions.availableAll": "সব প্রকল্পে উপলভ্য",
|
||||
"settings.extensions.manageConfig": "opencode.json-এ পরিচালনা করুন",
|
||||
"settings.extensions.addSkills": "স্কিল যোগ করার নিয়ম",
|
||||
"dialog.server.authenticate.title": "প্রমাণীকরণ",
|
||||
"project.settings.general.description": "প্রকল্পের নাম ও চেহারা পরিচালনা করুন",
|
||||
"project.settings.scripts": "স্ক্রিপ্ট",
|
||||
"project.settings.scripts.description": "এই প্রকল্পের স্ক্রিপ্ট কনফিগার করুন",
|
||||
"project.settings.extensions.description": "এই প্রকল্পে উপলভ্য এক্সটেনশন দেখুন",
|
||||
"project.settings.extensions.tab.lsps": "LSPs",
|
||||
"project.settings.extensions.added": "এই প্রকল্পে যোগ করা হয়েছে",
|
||||
"project.settings.extensions.shared": "সব প্রকল্পের সঙ্গে শেয়ার করা",
|
||||
"project.settings.extensions.lsp.detected": "শনাক্ত করা ল্যাঙ্গুয়েজ সার্ভার",
|
||||
"project.settings.extensions.lsp.description": "ফাইলের ধরন থেকে স্বয়ংক্রিয়ভাবে শনাক্ত করা",
|
||||
"project.settings.extensions.setupRequired": "সেটআপ প্রয়োজন",
|
||||
"settings.general.section.general": "সাধারণ",
|
||||
"common.viewAll": "সব দেখুন",
|
||||
"session.new.workspace.local.tooltip": "বর্তমান চেকআউট ব্যবহার করুন",
|
||||
"session.new.workspace.new.tooltip": "আলাদা চেকআউট তৈরি করুন",
|
||||
"session.new.workspace.fromBranch": "{{branch}} থেকে",
|
||||
"session.new.workspace.trigger.tooltip": "সেশন কোথায় চলবে তা নির্বাচন করুন",
|
||||
"session.new.workspace.search.placeholder": "ওয়ার্কস্পেস খুঁজুন",
|
||||
"settings.tab.workspaces": "ওয়ার্কস্পেস",
|
||||
"settings.workspaces.filter.all": "সব প্রকল্প",
|
||||
"settings.workspaces.empty": "কোনো ওয়ার্কস্পেস নেই",
|
||||
"settings.workspaces.count.one": "{{count}}টি ওয়ার্কস্পেস",
|
||||
"settings.workspaces.count.other": "{{count}}টি ওয়ার্কস্পেস",
|
||||
"settings.workspaces.sessions.one": "{{project}}-এ {{count}}টি সেশন",
|
||||
"settings.workspaces.sessions.other": "{{project}}-এ {{count}}টি সেশন",
|
||||
"settings.workspaces.lastActiveSession": "সর্বশেষ সক্রিয় সেশন",
|
||||
"settings.workspaces.deleteAll": "সব ওয়ার্কস্পেস মুছুন",
|
||||
"settings.workspaces.delete.warning":
|
||||
"নিচে দেখানো একীভূত না হওয়া পরিবর্তনসহ ওয়ার্কস্পেস ডিরেক্টরি ও ব্রাঞ্চ স্থায়ীভাবে মুছে যাবে।",
|
||||
"settings.workspaces.delete.blocked.active": "সক্রিয় ওয়ার্কস্পেস মোছা যাবে না।",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"যুক্ত সেশনগুলো থাকবে, তবে তাদের কার্যকরী ডিরেক্টরি স্থায়ীভাবে মুছে যাবে।",
|
||||
"settings.workspaces.default.title": "ডিফল্ট পরিবেশ",
|
||||
"settings.workspaces.default.description": "নতুন সেশন কোথায় শুরু হবে তা বেছে নিন",
|
||||
"settings.workspaces.default.lastUsed": "প্রতি প্রকল্পে সর্বশেষ ব্যবহৃত",
|
||||
"settings.workspaces.default.local": "স্থানীয় ডিরেক্টরি",
|
||||
"settings.workspaces.default.new": "নতুন ওয়ার্কস্পেস",
|
||||
"workspace.move.title": "ওয়ার্কস্পেসে সরান",
|
||||
"workspace.move.menu.title": "সেশন এখানে সরান",
|
||||
"workspace.move.failed": "সেশন সরানো ব্যর্থ হয়েছে",
|
||||
"workspace.lifecycle.creating": "ওয়ার্কস্পেস তৈরি হচ্ছে",
|
||||
"workspace.lifecycle.created": "ওয়ার্কস্পেস তৈরি হয়েছে",
|
||||
"workspace.lifecycle.starting": "সেশন শুরু হচ্ছে",
|
||||
"workspace.onboarding.title": "ওয়ার্কস্পেস দিয়ে সেশন আলাদা রাখুন",
|
||||
"workspace.onboarding.description":
|
||||
"প্রতিটি নিজস্ব চেকআউট পায়, তাই আপনার স্থানীয় রিপোজিটরিতে কোনো হস্তক্ষেপ হয় না",
|
||||
"workspace.lifecycle.moving": "ওয়ার্কস্পেসে সরানো হচ্ছে",
|
||||
"workspace.lifecycle.set": "ওয়ার্কস্পেস সেট করা হয়েছে",
|
||||
"session.summary.title": "সেশনের বিবরণ",
|
||||
"session.summary.noBranch": "কোনো ব্রাঞ্চ নেই",
|
||||
"session.summary.basedOn": "{{branch}}-এর ভিত্তিতে",
|
||||
"provider.disconnect.toast.noCredentials.description":
|
||||
"{{provider}}-এর জন্য অপসারণযোগ্য কোনো শংসাপত্র পাওয়া যায়নি।",
|
||||
"provider.disconnect.toast.failed.description": "{{provider}}-এর সংযোগ বিচ্ছিন্ন করা যায়নি।",
|
||||
"desktop.menu.installCli": "CLI ইনস্টল করুন...",
|
||||
"desktop.cli.installed.title": "CLI ইনস্টল হয়েছে",
|
||||
"desktop.cli.installed.message":
|
||||
"CLI {{path}}-এ ইনস্টল হয়েছে\n\n'opencode2' কমান্ড ব্যবহার করতে টার্মিনাল পুনরায় চালু করুন।",
|
||||
"desktop.cli.failed.title": "ইনস্টলেশন ব্যর্থ হয়েছে",
|
||||
"desktop.cli.failed.message": "CLI ইনস্টল করা যায়নি: {{error}}",
|
||||
"command.project.copyID": "প্রকল্পের ID কপি করুন",
|
||||
"command.session.copyID": "সেশনের ID কপি করুন",
|
||||
"server.row.incompatible":
|
||||
"এই সার্ভারে OpenCode {{version}} চলছে, যা এই অ্যাপের সঙ্গে সামঞ্জস্যপূর্ণ নয়। চালিয়ে যেতে এটিকে OpenCode V2-এ আপগ্রেড করুন।",
|
||||
"toast.session.copyID.failed.title": "সেশন ID কপি করা যায়নি",
|
||||
"toast.session.copyID.failed.description": "সেশন ID কপি করার সময় একটি ত্রুটি ঘটেছে",
|
||||
"toast.project.copyID.failed.title": "প্রকল্প ID কপি করা যায়নি",
|
||||
"toast.project.copyID.failed.description": "প্রকল্প ID কপি করার সময় একটি ত্রুটি ঘটেছে",
|
||||
"error.page.title.status": "সার্ভারের অনুরোধ ব্যর্থ হয়েছে",
|
||||
"error.page.description.status": "সার্ভারটি HTTP {{status}} প্রতিক্রিয়া দিয়েছে।",
|
||||
"error.page.action.reload": "পুনরায় লোড করুন",
|
||||
"session.error.incompatible": "এই সার্ভার সংস্করণটি সমর্থিত নয়",
|
||||
"session.error.incompatible.description":
|
||||
"{{server}}-এ OpenCode {{version}} চলছে, যা এই অ্যাপের সঙ্গে সামঞ্জস্যপূর্ণ নয়। চালিয়ে যেতে সার্ভারটি OpenCode V2-এ আপগ্রেড করুন।",
|
||||
"session.background.moveInline": "চলমান কাজটি পটভূমিতে সরাতে {{keybind}} চাপুন",
|
||||
"session.background.running": "পটভূমিতে কাজ চলছে",
|
||||
"session.background.runningCount.one": "পটভূমিতে {{count}}টি আইটেম চলছে",
|
||||
"session.background.runningCount.other": "পটভূমিতে {{count}}টি আইটেম চলছে",
|
||||
"settings.general.row.terminalPlacement.title": "টার্মিনালের অবস্থান",
|
||||
"settings.general.row.terminalPlacement.description": "সেশনে টার্মিনাল কোথায় খুলবে তা বেছে নিন",
|
||||
"settings.general.row.terminalPlacement.side": "পাশে",
|
||||
"settings.general.row.terminalPlacement.bottom": "নিচে",
|
||||
"session.location.unavailable": "সেশনের অবস্থান অনুপলব্ধ",
|
||||
"session.location.description": "এই সেশনটি চালিয়ে যেতে অন্য একটি ডিরেক্টরি বেছে নিন।",
|
||||
"session.location.choose": "ডিরেক্টরি বেছে নিন",
|
||||
"session.location.worktree": "ওয়ার্কট্রি বেছে নিন",
|
||||
"session.location.worktreesFailed": "ওয়ার্কট্রি লোড করা যায়নি",
|
||||
"session.location.moving": "সেশন সরানো হচ্ছে…",
|
||||
"dialog.server.menu.hide": "প্রকল্পের তালিকা থেকে লুকান",
|
||||
"dialog.server.menu.show": "প্রকল্পের তালিকায় দেখান",
|
||||
"session.queue.count.one": "{{count}}টি সারিবদ্ধ",
|
||||
"session.queue.count.other": "{{count}}টি সারিবদ্ধ",
|
||||
"session.queue.steer": "দিকনির্দেশ দিন",
|
||||
"session.queue.send": "পাঠান",
|
||||
"session.queue.steerTooltip": "বাধা না দিয়ে পাঠান",
|
||||
"session.queue.remove": "সরান",
|
||||
"session.queue.reorder": "সারিবদ্ধ প্রম্পট পুনর্বিন্যস্ত করুন",
|
||||
"session.new.worktree.creating": "ওয়ার্কট্রি তৈরি হচ্ছে",
|
||||
"settings.backToApp": "অ্যাপে ফিরে যান",
|
||||
"settings.appearance.section.experimental": "পরীক্ষামূলক",
|
||||
"settings.appearance.row.tabs.title": "ট্যাব",
|
||||
"settings.appearance.row.tabs.description": "সেশন ট্যাব কীভাবে সাজানো হবে তা বেছে নিন",
|
||||
"settings.appearance.row.tabs.horizontal": "অনুভূমিক",
|
||||
"settings.appearance.row.tabs.vertical": "উল্লম্ব",
|
||||
"settings.general.row.followUpBehavior.title": "ফলো-আপের আচরণ",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"ফলো-আপ সারিতে রাখবেন নাকি বর্তমান টার্নে দিকনির্দেশ দেবেন তা বেছে নিন। বদলাতে {{keybind}} ব্যবহার করুন।",
|
||||
"settings.general.row.followUpBehavior.queue": "সারিতে রাখুন",
|
||||
"settings.general.row.followUpBehavior.steer": "দিকনির্দেশ দিন",
|
||||
"settings.general.row.reasoningMode.title": "মডেলের যুক্তিবিশ্লেষণ",
|
||||
"settings.general.row.reasoningMode.description": "টাইমলাইনে মডেলের যুক্তিবিশ্লেষণ কীভাবে দেখানো হবে তা বেছে নিন",
|
||||
"settings.general.row.reasoningMode.hidden": "লুকানো",
|
||||
"settings.general.row.reasoningMode.compact": "সংক্ষিপ্ত",
|
||||
"settings.general.row.reasoningMode.full": "সম্পূর্ণ",
|
||||
"session.new.workspace.createFrom": "থেকে তৈরি করুন",
|
||||
"session.new.workspace.branch.search.placeholder": "ব্রাঞ্চ খুঁজুন",
|
||||
"toast.migration.progress.clearingOldEvents": "পুরোনো ইভেন্ট পরিষ্কার করা হচ্ছে",
|
||||
"toast.migration.progress.migratingSessions": "সেশন মাইগ্রেট করা হচ্ছে",
|
||||
"session.new.workspace.existingLabel": "ওয়ার্কট্রি",
|
||||
"desktop.onboarding.defaultProject": "ডিফল্ট প্রকল্প",
|
||||
|
||||
"home.projects.all": "সব প্রকল্প",
|
||||
"session.tab.files": "ফাইল",
|
||||
"session.files.openTabs": "খোলা ফাইল",
|
||||
"session.tab.usage": "ব্যবহার",
|
||||
"session.view.select": "সেশন দৃশ্য",
|
||||
"session.background.moveTasks": "{{tasks}} ব্যাকগ্রাউন্ডে নিন",
|
||||
"session.background.moveRunning": "ব্যাকগ্রাউন্ডে নিন",
|
||||
"session.background.inBackground": "{{tasks}} ব্যাকগ্রাউন্ডে চলছে",
|
||||
"session.background.tasksRunning.one": "{{count}}টি ব্যাকগ্রাউন্ড কাজ চলছে",
|
||||
"session.background.tasksRunning.other": "{{count}}টি ব্যাকগ্রাউন্ড কাজ চলছে",
|
||||
"session.background.combine": "{{first}} এবং {{second}}",
|
||||
"session.background.shell.one": "{{count}}টি শেল",
|
||||
"session.background.shell.other": "{{count}}টি শেল",
|
||||
"session.background.subagent.one": "{{count}}টি সাবএজেন্ট",
|
||||
"session.background.subagent.other": "{{count}}টি সাবএজেন্ট",
|
||||
"session.timeline.working": "কাজ চলছে",
|
||||
"session.review.wrapLines": "লাইন মোড়ানো",
|
||||
"session.websearch.title": "তৃতীয়-পক্ষের ওয়েব অনুসন্ধান",
|
||||
"session.websearch.description":
|
||||
"এজেন্টরা ওয়েবে অনুসন্ধানের জন্য যে অনুসন্ধান প্রদানকারী ব্যবহার করবে সেটি বেছে নিন",
|
||||
"session.websearch.provider": "অনুসন্ধান প্রদানকারী",
|
||||
"session.websearch.any": "যেকোনো",
|
||||
"session.websearch.disable": "অনুসন্ধান ব্যবহার করবেন না",
|
||||
"session.websearch.enable": "সক্রিয় করুন",
|
||||
"session.websearch.loadFailed": "অনুসন্ধান প্রদানকারী লোড করা যায়নি।",
|
||||
"session.websearch.empty": "কোনো অনুসন্ধান প্রদানকারী উপলভ্য নেই।",
|
||||
"session.websearch.failed": "আপনার পছন্দ সংরক্ষণ করা যায়নি। আবার চেষ্টা করুন।",
|
||||
"session.websearch.retry": "আবার চেষ্টা করুন",
|
||||
"session.new.worktree.draftPlaceholder": "ওয়ার্কট্রি প্রস্তুত হওয়ার সময় একটি ফলো-আপের খসড়া লিখুন…",
|
||||
"session.search.placeholder": "খুঁজুন...",
|
||||
"session.search.noResults": "কোনো মিল নেই",
|
||||
"titlebar.tabs": "ট্যাব",
|
||||
"titlebar.channel.local": "স্থানীয়",
|
||||
"titlebar.channel.dev": "ডেভ",
|
||||
"titlebar.channel.beta": "বিটা",
|
||||
"titlebar.toggleDebugTools": "ডিবাগ টুল টগল করুন",
|
||||
"settings.tab.experimental": "পরীক্ষামূলক",
|
||||
"settings.experimental.description": "পরীক্ষামূলক ফিচার ব্যবহার করে দেখুন",
|
||||
"settings.tab.about": "পরিচিতি",
|
||||
"settings.about.version": "সংস্করণ {{version}}",
|
||||
"settings.about.devVersion": "ডেভেলপমেন্ট",
|
||||
"settings.about.license": "MIT লাইসেন্সের অধীনে প্রকাশিত",
|
||||
"settings.about.writtenBy": "লিখেছেন",
|
||||
"settings.about.illustratedBy": "অলংকরণ করেছেন",
|
||||
"settings.about.and": "এবং",
|
||||
"settings.about.otherContributor.one": "অন্য {{count}} জন",
|
||||
"settings.about.otherContributor.other": "অন্য {{count}} জন",
|
||||
"settings.about.firstPublished": "প্রথম প্রকাশিত মিসৌরি, যুক্তরাষ্ট্রে",
|
||||
"settings.about.firstIllustrated": "প্রথম অলংকৃত লন্ডন, ইংল্যান্ডে",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode, ওপেন সোর্স কোডিং এজেন্ট",
|
||||
"settings.about.trademark": "OpenCode, Anomaly Innovations, Inc.-এর নিবন্ধিত ট্রেডমার্ক।",
|
||||
"settings.about.typeset": "Inter এবং IBM Plex Mono-তে টাইপসেট",
|
||||
"settings.about.tagline": "আপনাকে ছাড়া AI দারুণ সফটওয়্যার তৈরি করতে পারে না",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "প্রকল্প সম্পাদনা করুন",
|
||||
"settings.timeline.title": "টাইমলাইন",
|
||||
"settings.timeline.detail": "টাইমলাইনের বিস্তারিত",
|
||||
"settings.timeline.description": "টাইমলাইনে কতটা কার্যকলাপ দেখানো হবে তা বেছে নিন। বার্তাগুলো দৃশ্যমান থাকবে।",
|
||||
"settings.timeline.preset.everything": "সবকিছু",
|
||||
"settings.timeline.preset.detailed": "বিস্তারিত",
|
||||
"settings.timeline.preset.compact": "সংক্ষিপ্ত",
|
||||
"settings.timeline.preset.quiet": "নীরব",
|
||||
"settings.timeline.preset.text-only": "শুধু টেক্সট",
|
||||
"settings.timeline.description.everything":
|
||||
"সব কার্যকলাপ আলাদাভাবে দেখান। শেল আউটপুট, সম্পাদনা ও চিন্তা প্রসারিত করুন।",
|
||||
"settings.timeline.description.detailed":
|
||||
"শেল আউটপুট ও সম্পাদনা প্রসারিত করুন। সাবএজেন্ট আলাদাভাবে দেখান এবং অন্য কার্যকলাপ ‘ব্যবহৃত’ অংশে গোষ্ঠীবদ্ধ করুন।",
|
||||
"settings.timeline.description.compact": "সব কার্যকলাপ ‘ব্যবহৃত’ অংশে গোষ্ঠীবদ্ধ করে বিস্তারিত সংকুচিত রাখুন।",
|
||||
"settings.timeline.description.quiet": "সম্পাদনা ও সাবএজেন্ট ‘ব্যবহৃত’ অংশে গোষ্ঠীবদ্ধ করুন। অন্য কার্যকলাপ লুকান।",
|
||||
"settings.timeline.description.text-only": "সব কার্যকলাপ লুকান। শুধু বার্তা দেখান।",
|
||||
"settings.timeline.description.custom":
|
||||
"প্রতিটি কার্যকলাপ বিভাগের জন্য আপনার নির্বাচিত অবস্থান ও বিস্তারিত ব্যবহার করুন।",
|
||||
"settings.timeline.custom": "কাস্টম",
|
||||
"settings.timeline.advanced": "উন্নত",
|
||||
"settings.timeline.advanced.description": "প্রতিটি কার্যকলাপ বিভাগের অবস্থান ও বিস্তারিত নির্ধারণ করুন।",
|
||||
"settings.timeline.category.shell": "শেল",
|
||||
"settings.timeline.category.edit": "সম্পাদনা",
|
||||
"settings.timeline.category.thinking": "চিন্তা",
|
||||
"settings.timeline.category.subagents": "সাবএজেন্ট",
|
||||
"settings.timeline.category.notices": "বিজ্ঞপ্তি",
|
||||
"settings.timeline.category.tools": "অন্যান্য টুল",
|
||||
"settings.general.row.mobileDiffWrap.description": "মোবাইল ডিফে অনুভূমিকভাবে স্ক্রল করার বদলে দীর্ঘ লাইন মোড়ান",
|
||||
|
||||
"provider.connect.error.unsupportedFields": "এই প্রমাণীকরণ ফর্মে অসমর্থিত ফিল্ড রয়েছে",
|
||||
"session.review.filesChangedCount.one": "{{count}}টি ফাইল পরিবর্তিত হয়েছে",
|
||||
"session.review.filesChangedCount.other": "{{count}}টি ফাইল পরিবর্তিত হয়েছে",
|
||||
"settings.about.writtenByNames": "লিখেছেন {{names}}",
|
||||
"settings.about.illustratedByNames": "অলংকরণ করেছেন {{names}}",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"একীভূত না করা পরিবর্তন, সংযুক্ত সেশন বা সক্রিয় অবস্থানসহ ওয়ার্কট্রিগুলি রাখা হবে।",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline": "{{host}} এর সাথে সংযুক্ত নয়৷ আপনার খসড়া সংরক্ষিত আছে; দূরবর্তী কাজ এখনও চলমান হতে পারে.",
|
||||
"ssh.placeholder": "ssh user@example.com",
|
||||
"ssh.add": "SSH সার্ভার যোগ করুন",
|
||||
"ssh.server.menu.label": "SSH সার্ভার",
|
||||
"ssh.target": "হোস্ট বা SSH কমান্ড",
|
||||
"ssh.connect": "সংযোগ করুন",
|
||||
"ssh.connectTo": "{{host}} এর সাথে সংযোগ করুন",
|
||||
"ssh.authenticate": "SSH প্রমাণীকরণ",
|
||||
"ssh.action.authenticate": "প্রমাণীকরণ",
|
||||
"ssh.session.disconnected": "SSH সংযোগ নিষ্ক্রিয়৷",
|
||||
"ssh.session.connecting": "SSH সার্ভারের সাথে সংযোগ করা হচ্ছে৷",
|
||||
"ssh.session.reconnectDescription":
|
||||
"এই অধিবেশন দেখতে এবং কাজ চালিয়ে যেতে পুনরায় সংযোগ করুন. আপনার দূরবর্তী অধিবেশন সংরক্ষিত আছে.",
|
||||
"ssh.session.reconnect": "পুনরায় সংযোগ করুন",
|
||||
"ssh.authenticationRequired": "{{host}} এর জন্য প্রমাণীকরণ প্রয়োজন",
|
||||
"ssh.trust": "বিশ্বাস করুন এবং সংযোগ করুন",
|
||||
"ssh.continue": "চালিয়ে যান",
|
||||
"ssh.retry": "আবার চেষ্টা করুন",
|
||||
"ssh.update": "আপডেট এবং পুনরায় সংযোগ",
|
||||
"ssh.openProject": "প্রকল্প খুলুন",
|
||||
"ssh.project": "{{host}} এ প্রজেক্ট খুলুন",
|
||||
"ssh.disconnect": "সংযোগ বিচ্ছিন্ন করুন",
|
||||
"ssh.forget": "সংযোগ ভুলে যান",
|
||||
"ssh.stage.disconnected": "সংযোগ বিচ্ছিন্ন দূরবর্তী সার্ভার চলমান বাকি আছে.",
|
||||
"ssh.stage.connecting": "সংযোগ করা হচ্ছে SSH…",
|
||||
"ssh.stage.checking": "পরীক্ষা করা হচ্ছে OpenCode…",
|
||||
"ssh.stage.downloading": "সার্ভার ডাউনলোড হচ্ছে...",
|
||||
"ssh.stage.uploading": "সার্ভার আপলোড হচ্ছে...",
|
||||
"ssh.stage.starting": "OpenCode এর সাথে সংযোগ করা হচ্ছে…",
|
||||
"ssh.stage.ready": "সংযুক্ত",
|
||||
"ssh.stage.authentication": "প্রমাণীকরণ প্রয়োজন",
|
||||
"ssh.stage.incompatible": "সার্ভার আপডেট প্রয়োজন",
|
||||
"ssh.stage.failed": "সংযোগ ব্যর্থ হয়েছে৷",
|
||||
"ssh.error.input": "একটি হোস্ট বা SSH সংযোগ কমান্ড লিখুন৷ দূরবর্তী কমান্ড এবং অসমর্থিত SSH বিকল্পগুলি অনুমোদিত নয়৷",
|
||||
"ssh.error.connection": "SSH সংযোগ স্থাপন করা যায়নি৷ আপনার নেটওয়ার্ক এবং SSH কনফিগারেশন পরীক্ষা করুন৷",
|
||||
"ssh.error.platform":
|
||||
"এই দূরবর্তী প্ল্যাটফর্ম সমর্থিত নয়. স্বয়ংক্রিয় সেটআপের জন্য বর্তমানে x64 বা arm64 এ Linux বা macOS প্রয়োজন৷",
|
||||
"ssh.error.version": "সংযোগ করার আগে দূরবর্তী পরিষেবা অবশ্যই এই ডেস্কটপ সংস্করণের সাথে মিলবে৷",
|
||||
"ssh.error.install":
|
||||
"দূরবর্তী সার্ভার ইনস্টল করা যায়নি. কানেক্টিভিটি, ডিস্ক স্পেস চেক করুন এবং সেই টার ইনস্টল করা আছে।",
|
||||
"ssh.error.unpublished":
|
||||
"এই ডেস্কটপ সংস্করণে কোনো প্রকাশিত রিমোট সার্ভার নেই। ডেভেলপমেন্ট বিল্ডের জন্য, হোস্টে V2 ইনস্টল করুন এবং শুরু করুন, তারপর আবার চেষ্টা করুন।",
|
||||
"ssh.error.service": "SSH সংযুক্ত, কিন্তু OpenCode সার্ভার প্রস্তুত হয়নি৷",
|
||||
"ssh.error.host-key":
|
||||
"হোস্টের পরিচয় যাচাই করা যায়নি। আপনার SSHটি পরিচিত হোস্ট আপডেট করার আগে এটির আঙ্গুলের ছাপ যাচাই করুন৷",
|
||||
"ssh.error.ssh-missing":
|
||||
"OpenSSH পাওয়া যায়নি। একটি OpenSSH ক্লায়েন্ট ইনস্টল করুন এবং নিশ্চিত করুন যে PATH-এ ssh উপলব্ধ রয়েছে৷",
|
||||
"command.browser.open": "ব্রাউজার খুলুন",
|
||||
"command.browser.reload": "ব্রাউজার পৃষ্ঠা পুনরায় লোড করুন",
|
||||
"command.session.summary.toggle": "সারাংশ টগল করুন",
|
||||
"common.color.orange": "কমলা",
|
||||
"common.color.yellow": "হলুদ",
|
||||
"common.color.cyan": "সায়ান",
|
||||
"common.color.green": "সবুজ",
|
||||
"common.color.red": "লাল",
|
||||
"common.color.pink": "গোলাপী",
|
||||
"common.color.blue": "নীল",
|
||||
"common.color.purple": "বেগুনি",
|
||||
"common.color.gray": "ধূসর",
|
||||
"mcp.auth.interactiveForm": "MCP সার্ভার {{name}} একটি ইন্টারেক্টিভ প্রমাণীকরণ ফর্ম প্রয়োজন৷",
|
||||
"server.connect.title": "একটি সার্ভারের সাথে সংযোগ করুন",
|
||||
"server.connect.description": "শুরু করতে আপনার সার্ভার ঠিকানা এবং পাসওয়ার্ড লিখুন.",
|
||||
"server.connect.button": "সংযোগ করুন",
|
||||
"server.connect.address.invalid": "একটি বৈধ HTTP বা HTTPS সার্ভার ঠিকানা লিখুন৷",
|
||||
"server.connect.failed": "সংযোগ করা যায়নি। সার্ভার ঠিকানা এবং পাসওয়ার্ড পরীক্ষা করুন, তারপর আবার চেষ্টা করুন.",
|
||||
"server.connect.pair.description": "আপনার সংযোগের বিবরণ পেতে আপনার কম্পিউটারে এই কমান্ডটি চালান।",
|
||||
"server.connect.scan": "QR কোড স্ক্যান করুন",
|
||||
"server.connect.scan.description": "আপনার ক্যামেরাকে ওপেনকোড পেয়ার দ্বারা দেখানো QR কোডে নির্দেশ করুন৷",
|
||||
"server.connect.scan.invalid": "এটি একটি OpenCode পেয়ারিং কোড নয়৷ ওপেনকোড পেয়ার দ্বারা দেখানো কোডটি স্ক্যান করুন।",
|
||||
"server.connect.camera": "পেয়ারিং ক্যামেরা",
|
||||
"server.connect.camera.starting": "ক্যামেরা খোলা হচ্ছে...",
|
||||
"server.connect.mixedContent":
|
||||
"একটি HTTPS পৃষ্ঠা থেকে এই HTTP সার্ভারের সাথে সংযোগ করা যায়নি৷ পরিবর্তে একটি HTTPS সার্ভার ঠিকানা ব্যবহার করুন৷",
|
||||
"server.connect.camera.insecure": "QR স্ক্যান করার জন্য এই পৃষ্ঠাটি HTTPS বা লোকালহোস্টে খুলতে হবে।",
|
||||
"server.connect.camera.unavailable": "এই ব্রাউজারে কোন ক্যামেরা উপলব্ধ নেই৷ ম্যানুয়ালি আপনার সংযোগ বিশদ লিখুন.",
|
||||
"server.connect.camera.error":
|
||||
"ক্যামেরা খুলতে পারিনি। ক্যামেরা অ্যাক্সেসের অনুমতি দিন বা ম্যানুয়ালি আপনার সংযোগের বিবরণ লিখুন।",
|
||||
"dialog.server.menu.remove": "সরান",
|
||||
"file.error.notFound": "ফাইল পাওয়া যায়নি: {{name}}",
|
||||
"toast.migration.progress.migratingSessions.current": "স্থানান্তরিত সেশন {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "স্থানান্তরিত সেশন {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "ডেটা স্থানান্তর করা হচ্ছে",
|
||||
"toast.migration.progress.working.current": "ডেটা স্থানান্তরিত হচ্ছে {{current}}",
|
||||
"toast.migration.progress.working.progress": "ডেটা স্থানান্তরিত হচ্ছে {{current}}/{{total}}",
|
||||
"home.workspaceTip": "পরিবর্তনগুলিকে বিচ্ছিন্ন রাখতে একটি নতুন কর্মক্ষেত্রে পরবর্তী সেশন শুরু করুন৷",
|
||||
"session.tab.browser": "ব্রাউজার",
|
||||
"session.tab.add": "ট্যাব যোগ করুন",
|
||||
"session.queue.attachments.one": "প্লাস {{count}} সংযুক্তি",
|
||||
"session.queue.attachments.other": "প্লাস {{count}}টি সংযুক্তি৷",
|
||||
"session.browser.address": "ব্রাউজার ঠিকানা",
|
||||
"session.browser.replaced": "ব্রাউজার নিয়ন্ত্রণ অন্য ডেস্কটপ উইন্ডোতে সরানো হয়েছে।",
|
||||
"session.browser.unsupported": "এই ডেস্কটপ অ্যাপ্লিকেশন ব্রাউজার ফলক সমর্থন করে না.",
|
||||
"session.browser.suspended": "ব্রাউজার সাসপেন্ড করা হয়েছে। পুনরায় সংযোগ করতে এই সেশনের সাথে ইন্টারঅ্যাক্ট করুন।",
|
||||
"session.browser.address.placeholder": "URL লিখুন",
|
||||
"settings.backToSettings": "সেটিংসে ফিরে যান",
|
||||
"settings.backToProjects": "প্রকল্পগুলিতে ফিরে যান",
|
||||
"settings.search.placeholder": "অনুসন্ধান করুন",
|
||||
"settings.search.results": "সেটিংস ফলাফল",
|
||||
"settings.search.group.pages": "পাতা",
|
||||
"settings.search.group.settings": "সেটিংস",
|
||||
"settings.search.group.projects": "প্রকল্প",
|
||||
"settings.search.group.servers": "সার্ভার",
|
||||
"settings.search.result": "{{title}}, {{scope}}, {{page}}",
|
||||
"settings.search.page": "{{title}}, {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}, {{page}}",
|
||||
"settings.search.empty": "{{query}} এর জন্য কোনো ফলাফল নেই",
|
||||
"settings.search.empty.query": '"{{query}}"',
|
||||
"settings.search.refine": "আরো নির্দিষ্ট ফলাফল দেখতে আপনার অনুসন্ধান সংকীর্ণ করুন.",
|
||||
"settings.server.description": "এই সার্ভারের সংযোগ এবং পছন্দগুলি পরিচালনা করুন",
|
||||
"settings.server.section.connection": "সংযোগ",
|
||||
"settings.server.preferences.websearch.title": "তৃতীয় পক্ষের অনুসন্ধান",
|
||||
"settings.server.preferences.websearch.description":
|
||||
"অনুসন্ধান প্রদানকারী এজেন্টরা ওয়েব অনুসন্ধান করতে ব্যবহার করে নির্বাচন করুন৷",
|
||||
"settings.projects.search.placeholder": "অনুসন্ধান প্রকল্প",
|
||||
"project.settings.name.title": "প্রকল্পের নাম",
|
||||
"project.settings.name.description": "OpenCode জুড়ে এই প্রকল্পের নাম দেখানো হয়েছে",
|
||||
"project.settings.icon.description": "প্রস্তাবিত: 128×128px। একটি ছবি আপলোড করতে ক্লিক করুন বা টেনে আনুন।",
|
||||
"project.settings.color.description": "কোনো কাস্টম ছবি সেট না থাকলে প্রজেক্ট আইকনের জন্য ব্যবহার করা হয়",
|
||||
"project.settings.worktree.startup.description": "একটি নতুন ওয়ার্কট্রি তৈরি করার পরে একবার চলে",
|
||||
"project.settings.worktree.startup.hint.base": "বেস ওয়ার্কট্রির জন্য $OPENCODE_WORKTREE_BASE ব্যবহার করুন।",
|
||||
"project.settings.worktree.startup.hint.new": "নতুন ওয়ার্কট্রির জন্য $OPENCODE_WORKTREE_PATH ব্যবহার করুন৷",
|
||||
"project.settings.extensions.empty.mcps.title": "এখনও কোন MCPs",
|
||||
"project.settings.extensions.empty.mcps.description": "OpenCode-এর কাছে উপলব্ধ MCPগুলি এখানে প্রদর্শিত হবে৷",
|
||||
"project.settings.extensions.empty.plugins.title": "এখনো কোনো প্লাগইন নেই",
|
||||
"project.settings.extensions.empty.plugins.description": "OpenCode এ উপলব্ধ প্লাগইনগুলি এখানে উপস্থিত হবে৷",
|
||||
"project.settings.extensions.empty.skills.title": "এখনো কোনো দক্ষতা নেই",
|
||||
"project.settings.extensions.empty.skills.description": "OpenCode এর কাছে উপলব্ধ দক্ষতাগুলি এখানে প্রদর্শিত হবে৷",
|
||||
"project.settings.extensions.lsp.configured": "কনফিগার করা ভাষা সার্ভার",
|
||||
"project.settings.extensions.lsp.status.enabled": "কনফিগারে সক্রিয় করা হয়েছে",
|
||||
"project.settings.extensions.lsp.status.disabled": "কনফিগারেশনে নিষ্ক্রিয়",
|
||||
"project.settings.extensions.lsp.empty.title": "কোন ভাষা সার্ভার কনফিগার করা নেই",
|
||||
"project.settings.extensions.lsp.empty.description": "এই প্রকল্পের জন্য কনফিগার করা ভাষা সার্ভার এখানে প্রদর্শিত হবে",
|
||||
"project.settings.extensions.lsp.disabled.title": "ভাষা সার্ভার নিষ্ক্রিয়",
|
||||
"project.settings.extensions.lsp.disabled.description": "এই প্রকল্পের কনফিগারেশনে LSP নিষ্ক্রিয় করা আছে",
|
||||
"project.settings.extensions.lsp.loadFailed": "ভাষা সার্ভার কনফিগারেশন লোড করা যায়নি",
|
||||
"project.settings.extensions.lsp.retry": "আবার চেষ্টা করুন",
|
||||
"settings.timeline.summary": "{{preset}}:",
|
||||
"settings.timeline.group": "গ্রুপ",
|
||||
"settings.timeline.collapse": "সঙ্কুচিত",
|
||||
"settings.timeline.visibility.show": "দেখান",
|
||||
"settings.timeline.visibility.hide": "লুকান",
|
||||
"settings.timeline.visibility.label": "{{activity}} দৃশ্যমানতা",
|
||||
"settings.timeline.grouped.label": "{{activity}} গোষ্ঠীবদ্ধ",
|
||||
"settings.timeline.collapsed.label": "{{activity}} ভেঙে পড়েছে৷",
|
||||
"session.new.workspace.search.empty": "কোনো মিলে যাওয়া ওয়ার্কট্রি নেই",
|
||||
"settings.workspaces.description": "ওয়ার্কট্রিগুলি পর্যালোচনা করুন এবং ডিস্কের ব্যবহার পরিচালনা করুন",
|
||||
"settings.workspaces.empty.description": "OpenCode-এ তৈরি ওয়ার্কট্রিগুলি এখানে উপস্থিত হবে৷",
|
||||
"settings.workspaces.sessions.filtered.one": "{{count}} সেশন",
|
||||
"settings.workspaces.sessions.filtered.other": "{{count}}টি সেশন",
|
||||
"settings.workspaces.deleteAll.confirm.one": "এটি স্থায়ীভাবে {{count}}টি নির্বাচিত ওয়ার্কট্রি মুছে ফেলবে৷",
|
||||
"settings.workspaces.deleteAll.confirm.other": "এটি স্থায়ীভাবে {{count}}টি নির্বাচিত ওয়ার্কট্রি মুছে ফেলবে৷",
|
||||
"settings.workspaces.deleteWithoutSessions": "সেশন ছাড়া ওয়ার্কট্রি মুছুন",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"এটি সংযুক্ত সেশন ছাড়াই স্থায়ীভাবে {{count}}টি ওয়ার্কট্রি মুছে দেবে৷",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"এটি সংযুক্ত সেশন ছাড়াই স্থায়ীভাবে {{count}}টি ওয়ার্কট্রি মুছে দেবে৷",
|
||||
"settings.workspaces.deleteWithoutSessions.warning": "অনমার্জিত পরিবর্তন বা সক্রিয় অবস্থান সহ worktrees রাখা হবে.",
|
||||
"settings.workspaces.delete.button": "ওয়ার্কট্রি মুছুন",
|
||||
"workspace.lifecycle.deleting": "মুছে ফেলা হচ্ছে...",
|
||||
"session.summary.tooltip": "সারাংশ",
|
||||
"session.summary.server": "এক্সটেনশন",
|
||||
"session.summary.chooseProject": "একটি প্রকল্প চয়ন করুন",
|
||||
"session.summary.mcp.onCreation": "ওয়ার্কট্রি তৈরি হলে প্রযোজ্য",
|
||||
"session.summary.mcp.prepareFailed": "MCP সার্ভার প্রস্তুত করা যায়নি৷",
|
||||
"session.summary.mcp.unavailable": "এই ওয়ার্কট্রিতে MCP সার্ভার {{name}} উপলব্ধ নেই৷",
|
||||
"session.summary.mcp.signInBeforeSend": "প্রম্পট পাঠানোর আগে {{name}} এ সাইন ইন করুন৷",
|
||||
"session.summary.mcp.notReady": "MCP সার্ভার {{name}} প্রস্তুত নয়৷ প্রম্পট পাঠানোর আগে এর সংযোগটি সমাধান করুন।",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "কনফিগার করা MCP সার্ভার",
|
||||
"session.summary.plugins": "প্লাগইন",
|
||||
"session.summary.plugins.configured": "কনফিগার করা প্লাগইন",
|
||||
"session.summary.skills": "দক্ষতা",
|
||||
"session.summary.skills.configured": "কনফিগার করা দক্ষতা",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "ব্যর্থ হয়েছে",
|
||||
"session.summary.retry": "আবার চেষ্টা করুন",
|
||||
"session.summary.connecting": "সংযোগ করা হচ্ছে...",
|
||||
"session.summary.needsAuth": "সাইন ইন প্রয়োজন",
|
||||
"session.summary.configure": "কনফিগারেশন ফাইল",
|
||||
"session.summary.copyConfigPath": "কনফিগারেশন ফাইল পাথ কপি করুন",
|
||||
"session.summary.configFileMissing": "কোন কনফিগারেশন ফাইল পাওয়া যায়নি",
|
||||
"session.summary.mcp.empty": "কোনো MCP সার্ভার কনফিগার করা হয়নি৷",
|
||||
"session.summary.mcp.add": "opencode.json এ সার্ভার যোগ করুন",
|
||||
"session.summary.plugins.manage": "opencode.json এ প্লাগইনগুলি পরিচালনা করুন",
|
||||
"session.summary.plugins.empty": "কোনো প্লাগইন কনফিগার করা নেই",
|
||||
"session.summary.plugins.add": "opencode.json এ প্লাগইন যোগ করুন",
|
||||
"session.summary.skills.manage": "opencode.json এ দক্ষতা পরিচালনা করুন",
|
||||
"session.summary.skills.empty": "কোন দক্ষতা কনফিগার করা",
|
||||
"session.summary.skills.add": "opencode.json এ দক্ষতা যোগ করুন",
|
||||
"session.summary.lsp.configured": "কনফিগার করা LSP",
|
||||
"session.summary.lsp.empty": "কোনো LSP সার্ভার কনফিগার করা হয়নি৷",
|
||||
"session.summary.lsp.manage": "opencode.json এ LSP পরিচালনা করুন",
|
||||
"workspace.delete.location": "অবস্থান",
|
||||
|
||||
"command.debugBar.toggle": "ডিবাগ বার টগল করুন",
|
||||
"command.session.location.cycle": "সেশনের অবস্থান পর্যায়ক্রমে বদলান",
|
||||
"dialog.provider.anthropic.note": "API কী-এর মাধ্যমে Claude মডেলে সরাসরি অ্যাক্সেস",
|
||||
"provider.connect.title.anthropicProMax": "Anthropic দিয়ে লগ ইন করুন",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"prompt.toast.uploading.cancelFile": "{{filename}}-এর আপলোড বাতিল করুন",
|
||||
"prompt.toast.uploading.cancel": "আপলোড বাতিল করুন",
|
||||
"prompt.toast.uploadFailed.title": "আপলোড ব্যর্থ হয়েছে",
|
||||
"session.browser.empty.title": "URL লিখুন",
|
||||
"session.browser.empty.description": "অথবা প্রম্পট করুন “অ্যাপ ব্রাউজারে খুলুন”",
|
||||
"session.browser.failed.title": "URL-এ পৌঁছানো যাচ্ছে না",
|
||||
"session.browser.failed.description": "URL এবং আপনার সংযোগ পরীক্ষা করে আবার চেষ্টা করুন।",
|
||||
"debugBar.providerAriaLabel": "প্রদানকারীর কর্মক্ষমতা নির্ণয়",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttft.tip": "প্রদানকারীর অনুরোধ পাঠানো থেকে মডেলের প্রথম আউটপুট পর্যন্ত সময়।",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.ttfa.tip": "প্রদানকারীর অনুরোধ পাঠানো থেকে উত্তরের প্রথম লেখা পর্যন্ত সময়।",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.tps.tip": "মডেলের প্রথম আউটপুটের পর প্রতি সেকেন্ডে আউটপুট টোকেনের সংখ্যা।",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
"debugBar.e2e.tip": "প্রদানকারীর অনুরোধ পাঠানো থেকে তার প্রতিক্রিয়া স্ট্রিম শেষ হওয়া পর্যন্ত সময়।",
|
||||
"settings.updates.action.download": "OpenCode ডাউনলোড করুন",
|
||||
"settings.updates.migration.title": "বেটা থেকে স্থিতিশীল সংস্করণে যান",
|
||||
"settings.updates.migration.description":
|
||||
"আপাতত OpenCode Beta, OpenCode Stable-এ স্থানান্তরিত হচ্ছে। {{version}} সংস্করণ ডাউনলোড করুন, তারপর আপডেট পাওয়া অব্যাহত রাখতে ডিস্ক ইমেজ থেকে OpenCode ইনস্টল করুন।",
|
||||
}
|
||||
|
||||
@@ -1,4 +1,349 @@
|
||||
export const dict = {
|
||||
"common.color.orange": "laranja",
|
||||
"common.color.yellow": "amarelo",
|
||||
"common.color.cyan": "ciano",
|
||||
"common.color.green": "verde",
|
||||
"common.color.red": "vermelho",
|
||||
"common.color.pink": "rosa",
|
||||
"common.color.blue": "azul",
|
||||
"common.color.purple": "roxo",
|
||||
"common.color.gray": "cinza",
|
||||
"toast.migration.progress.migratingSessions.current": "Migrando sessões {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "Migrando sessões {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "Migrando dados",
|
||||
"toast.migration.progress.working.current": "Migrando dados {{current}}",
|
||||
"toast.migration.progress.working.progress": "Migrando dados {{current}}/{{total}}",
|
||||
"session.browser.unsupported": "Este aplicativo para desktop não oferece suporte ao painel do navegador.",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline":
|
||||
"Não conectado a {{host}}. Seu rascunho foi preservado; o trabalho remoto ainda pode estar em execução.",
|
||||
"ssh.placeholder": "ssh user@example.com",
|
||||
"ssh.add": "Adicionar servidor SSH",
|
||||
"ssh.server.menu.label": "Servidor SSH",
|
||||
"ssh.target": "Host ou comando SSH",
|
||||
"ssh.connect": "Conectar",
|
||||
"ssh.connectTo": "Conecte-se a {{host}}",
|
||||
"ssh.authenticate": "Autenticação SSH",
|
||||
"ssh.action.authenticate": "Autenticar",
|
||||
"ssh.session.disconnected": "Conexão SSH inativa",
|
||||
"ssh.session.connecting": "Conectando ao servidor SSH",
|
||||
"ssh.session.reconnectDescription":
|
||||
"Reconecte-se para visualizar esta sessão e continuar trabalhando. Sua sessão remota é preservada.",
|
||||
"ssh.session.reconnect": "Reconectar",
|
||||
"ssh.authenticationRequired": "Autenticação necessária para {{host}}",
|
||||
"ssh.trust": "Confie e conecte-se",
|
||||
"ssh.continue": "Continuar",
|
||||
"ssh.retry": "Tentar novamente",
|
||||
"ssh.update": "Atualizar e reconectar",
|
||||
"ssh.openProject": "Abrir projeto",
|
||||
"ssh.project": "Abra o projeto no {{host}}",
|
||||
"ssh.disconnect": "Desconectar",
|
||||
"ssh.forget": "Esqueça a conexão",
|
||||
"ssh.stage.disconnected": "Desconectado. O servidor remoto permanece em execução.",
|
||||
"ssh.stage.connecting": "Conectando através de SSH…",
|
||||
"ssh.stage.checking": "Verificando OpenCode…",
|
||||
"ssh.stage.downloading": "Baixando servidor…",
|
||||
"ssh.stage.uploading": "Fazendo upload do servidor…",
|
||||
"ssh.stage.starting": "Conectando ao OpenCode…",
|
||||
"ssh.stage.ready": "Conectado",
|
||||
"ssh.stage.authentication": "Autenticação necessária",
|
||||
"ssh.stage.incompatible": "Atualização do servidor necessária",
|
||||
"ssh.stage.failed": "Falha na conexão",
|
||||
"ssh.error.input":
|
||||
"Insira um comando de conexão de host ou SSH. Comandos remotos e opções SSH não suportadas não são permitidos.",
|
||||
"ssh.error.connection": "Não foi possível estabelecer a conexão SSH. Verifique sua rede e a configuração do SSH.",
|
||||
"ssh.error.platform":
|
||||
"Esta plataforma remota não é suportada. A configuração automática atualmente requer Linux ou macOS em x64 ou arm64.",
|
||||
"ssh.error.version": "O serviço remoto deve corresponder a esta versão do Desktop antes da conexão.",
|
||||
"ssh.error.install":
|
||||
"Não foi possível instalar o servidor remoto. Verifique a conectividade, o espaço em disco e se o tar está instalado.",
|
||||
"ssh.error.unpublished":
|
||||
"Esta versão Desktop não possui servidor remoto publicado. Para compilações de desenvolvimento, instale e inicie o V2 no host e tente novamente.",
|
||||
"ssh.error.service": "SSH conectado, mas o servidor OpenCode não ficou pronto.",
|
||||
"ssh.error.host-key":
|
||||
"A identidade do anfitrião não pôde ser verificada. Verifique sua impressão digital antes de atualizar seus hosts conhecidos SSH.",
|
||||
"ssh.error.ssh-missing":
|
||||
"OpenSSH não foi encontrado. Instale um cliente OpenSSH e certifique-se de que o ssh esteja disponível no PATH.",
|
||||
"command.browser.open": "Abra o navegador",
|
||||
"command.browser.reload": "Recarregar página do navegador",
|
||||
"command.session.summary.toggle": "Alternar resumo",
|
||||
"mcp.auth.interactiveForm": "Servidor MCP {{name}} requer um formulário de autenticação interativo",
|
||||
"server.connect.title": "Conecte-se a um servidor",
|
||||
"server.connect.description": "Digite o endereço do servidor e a senha para começar.",
|
||||
"server.connect.button": "Conectar",
|
||||
"server.connect.address.invalid": "Insira um endereço de servidor HTTP ou HTTPS válido.",
|
||||
"server.connect.failed": "Não foi possível conectar. Verifique o endereço e a senha do servidor e tente novamente.",
|
||||
"server.connect.pair.description": "Execute este comando em seu computador para obter os detalhes de sua conexão.",
|
||||
"server.connect.scan": "Digitalize o código QR",
|
||||
"server.connect.scan.description": "Aponte sua câmera para o código QR mostrado por opencode pair.",
|
||||
"server.connect.scan.invalid":
|
||||
"Este não é um código de emparelhamento OpenCode. Digitalize o código mostrado por opencode pair.",
|
||||
"server.connect.camera": "Câmera de emparelhamento",
|
||||
"server.connect.camera.starting": "Abrindo a câmera…",
|
||||
"server.connect.mixedContent":
|
||||
"Não foi possível conectar-se a este servidor HTTP a partir de uma página HTTPS. Use um endereço de servidor HTTPS.",
|
||||
"server.connect.camera.insecure": "A varredura QR requer a abertura desta página em HTTPS ou no host local.",
|
||||
"server.connect.camera.unavailable":
|
||||
"Nenhuma câmera está disponível para este navegador. Insira os detalhes da sua conexão manualmente.",
|
||||
"server.connect.camera.error":
|
||||
"Não foi possível abrir a câmera. Permita o acesso à câmera ou insira os detalhes da sua conexão manualmente.",
|
||||
"dialog.server.menu.remove": "Remover",
|
||||
"file.error.notFound": "Arquivo não encontrado: {{name}}",
|
||||
"home.workspaceTip": "Inicie a próxima sessão em um novo espaço de trabalho para manter as alterações isoladas",
|
||||
"session.tab.browser": "Navegador",
|
||||
"session.tab.add": "Adicionar guia",
|
||||
"session.queue.attachments.one": "Mais acessório {{count}}",
|
||||
"session.queue.attachments.other": "Mais acessórios {{count}}",
|
||||
"session.browser.address": "Endereço do navegador",
|
||||
"session.browser.replaced": "O controle do navegador foi movido para outra janela da área de trabalho.",
|
||||
"session.browser.suspended": "Navegador suspenso. Interaja com esta sessão para se reconectar.",
|
||||
"session.browser.address.placeholder": "Digite URL",
|
||||
"settings.backToSettings": "Voltar às configurações",
|
||||
"settings.backToProjects": "Voltar aos projetos",
|
||||
"settings.search.placeholder": "Pesquisar",
|
||||
"settings.search.results": "Resultados das configurações",
|
||||
"settings.search.group.pages": "Páginas",
|
||||
"settings.search.group.settings": "Configurações",
|
||||
"settings.search.group.projects": "Projetos",
|
||||
"settings.search.group.servers": "Servidores",
|
||||
"settings.search.result": "{{title}}, {{scope}}, {{page}}",
|
||||
"settings.search.page": "{{title}}, {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}, {{page}}",
|
||||
"settings.search.empty": "Nenhum resultado para {{query}}",
|
||||
"settings.search.empty.query": '"{{query}}"',
|
||||
"settings.search.refine": "Restrinja sua pesquisa para ver resultados mais específicos.",
|
||||
"settings.server.description": "Gerencie a conexão e as preferências deste servidor",
|
||||
"settings.server.section.connection": "Conexão",
|
||||
"settings.server.preferences.websearch.title": "Pesquisa de terceiros",
|
||||
"settings.server.preferences.websearch.description":
|
||||
"Selecione o provedor de pesquisa que os agentes usam para pesquisar na web",
|
||||
"settings.projects.search.placeholder": "Pesquisar projetos",
|
||||
"project.settings.name.title": "Nome do projeto",
|
||||
"project.settings.name.description": "O nome mostrado para este projeto em OpenCode",
|
||||
"project.settings.icon.description": "Recomendado: 128×128px. Clique ou arraste para fazer upload de uma imagem.",
|
||||
"project.settings.color.description":
|
||||
"Usado para o ícone do projeto quando nenhuma imagem personalizada está definida",
|
||||
"project.settings.worktree.startup.description": "Executa uma vez após a criação de uma novo espaço de trabalho",
|
||||
"project.settings.worktree.startup.hint.base": "Use $OPENCODE_WORKTREE_BASE para o espaço de trabalho base.",
|
||||
"project.settings.worktree.startup.hint.new": "Use $OPENCODE_WORKTREE_PATH para o novo espaço de trabalho.",
|
||||
"project.settings.extensions.empty.mcps.title": "Ainda não há MCPs",
|
||||
"project.settings.extensions.empty.mcps.description": "MCPs disponível para OpenCode aparecerá aqui",
|
||||
"project.settings.extensions.empty.plugins.title": "Ainda não há plug-ins",
|
||||
"project.settings.extensions.empty.plugins.description": "Os plug-ins disponíveis para OpenCode aparecerão aqui",
|
||||
"project.settings.extensions.empty.skills.title": "Nenhuma habilidade ainda",
|
||||
"project.settings.extensions.empty.skills.description": "As habilidades disponíveis para OpenCode aparecerão aqui",
|
||||
"project.settings.extensions.lsp.configured": "Servidores de idiomas configurados",
|
||||
"project.settings.extensions.lsp.status.enabled": "Habilitado na configuração",
|
||||
"project.settings.extensions.lsp.status.disabled": "Desativado na configuração",
|
||||
"project.settings.extensions.lsp.empty.title": "Nenhum servidor de idioma configurado",
|
||||
"project.settings.extensions.lsp.empty.description":
|
||||
"Os servidores de idiomas configurados para este projeto aparecerão aqui",
|
||||
"project.settings.extensions.lsp.disabled.title": "Servidores de idiomas desativados",
|
||||
"project.settings.extensions.lsp.disabled.description": "LSP está desabilitado na configuração deste projeto",
|
||||
"project.settings.extensions.lsp.loadFailed": "Não foi possível carregar a configuração do servidor de idioma",
|
||||
"project.settings.extensions.lsp.retry": "Tentar novamente",
|
||||
"settings.timeline.summary": "{{preset}}:",
|
||||
"settings.timeline.group": "Grupo",
|
||||
"settings.timeline.collapse": "Recolher",
|
||||
"settings.timeline.visibility.show": "Mostrar",
|
||||
"settings.timeline.visibility.hide": "Esconder",
|
||||
"settings.timeline.visibility.label": "Visibilidade {{activity}}",
|
||||
"settings.timeline.grouped.label": "{{activity}} agrupado",
|
||||
"settings.timeline.collapsed.label": "{{activity}} entrou em colapso",
|
||||
"session.new.workspace.search.empty": "Nenhuma espaço de trabalho correspondente",
|
||||
"settings.workspaces.description": "Revise as espaços de trabalho e gerencie o uso do disco",
|
||||
"settings.workspaces.empty.description": "As espaços de trabalho criadas em OpenCode aparecerão aqui",
|
||||
"settings.workspaces.sessions.filtered.one": "Sessão {{count}}",
|
||||
"settings.workspaces.sessions.filtered.other": "Sessões {{count}}",
|
||||
"settings.workspaces.deleteAll.confirm.one":
|
||||
"Isso excluirá permanentemente a espaço de trabalho selecionada {{count}}.",
|
||||
"settings.workspaces.deleteAll.confirm.other":
|
||||
"Isso excluirá permanentemente as espaços de trabalho selecionadas do {{count}}.",
|
||||
"settings.workspaces.deleteWithoutSessions": "Excluir espaços de trabalho sem sessões",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"Isso excluirá permanentemente a espaço de trabalho {{count}} sem sessões vinculadas.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"Isso excluirá permanentemente as espaços de trabalho {{count}} sem sessões vinculadas.",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"As espaços de trabalho com alterações não mescladas ou locais ativos serão mantidas.",
|
||||
"settings.workspaces.delete.button": "Excluir espaços de trabalho",
|
||||
"workspace.lifecycle.deleting": "Excluindo…",
|
||||
"session.summary.tooltip": "Resumo",
|
||||
"session.summary.server": "Extensões",
|
||||
"session.summary.chooseProject": "Escolha um projeto",
|
||||
"session.summary.mcp.onCreation": "Aplica-se quando a espaço de trabalho é criada",
|
||||
"session.summary.mcp.prepareFailed": "Não foi possível preparar os servidores MCP",
|
||||
"session.summary.mcp.unavailable": "O servidor MCP {{name}} não está disponível nesta espaço de trabalho.",
|
||||
"session.summary.mcp.signInBeforeSend": "Faça login no {{name}} antes de enviar o prompt.",
|
||||
"session.summary.mcp.notReady":
|
||||
"O servidor MCP {{name}} não está pronto. Resolva sua conexão antes de enviar o prompt.",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "Servidores MCP configurados",
|
||||
"session.summary.plugins": "Plug-ins",
|
||||
"session.summary.plugins.configured": "Plug-ins configurados",
|
||||
"session.summary.skills": "Habilidades",
|
||||
"session.summary.skills.configured": "Habilidades configuradas",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "Falha",
|
||||
"session.summary.retry": "Tentar novamente",
|
||||
"session.summary.connecting": "Conectando…",
|
||||
"session.summary.needsAuth": "É necessário fazer login",
|
||||
"session.summary.configure": "Arquivo de configuração",
|
||||
"session.summary.copyConfigPath": "Copiar caminho do arquivo de configuração",
|
||||
"session.summary.configFileMissing": "Nenhum arquivo de configuração encontrado",
|
||||
"session.summary.mcp.empty": "Nenhum servidor MCP configurado",
|
||||
"session.summary.mcp.add": "Adicionar servidores em opencode.json",
|
||||
"session.summary.plugins.manage": "Gerenciar plug-ins em opencode.json",
|
||||
"session.summary.plugins.empty": "Nenhum plug-in configurado",
|
||||
"session.summary.plugins.add": "Adicionar plug-ins em opencode.json",
|
||||
"session.summary.skills.manage": "Gerenciar habilidades em opencode.json",
|
||||
"session.summary.skills.empty": "Nenhuma habilidade configurada",
|
||||
"session.summary.skills.add": "Adicionar habilidades em opencode.json",
|
||||
"session.summary.lsp.configured": "LSPs configurado",
|
||||
"session.summary.lsp.empty": "Nenhum servidor LSP configurado",
|
||||
"session.summary.lsp.manage": "Gerenciar LSP em opencode.json",
|
||||
"workspace.delete.location": "Localização",
|
||||
"session.queue.attachments.many": "Mais acessórios {{count}}",
|
||||
"settings.workspaces.sessions.filtered.many": "Sessões {{count}}",
|
||||
"settings.workspaces.deleteAll.confirm.many":
|
||||
"Isso excluirá permanentemente as espaços de trabalho selecionadas do {{count}}.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.many":
|
||||
"Isso excluirá permanentemente as espaços de trabalho {{count}} sem sessões vinculadas.",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"Espaços de trabalho com alterações não mescladas, sessões vinculadas ou locais ativos serão mantidos.",
|
||||
"provider.connect.error.unsupportedFields": "Este formulário de autenticação contém campos incompatíveis",
|
||||
"session.review.filesChangedCount.one": "{{count}} arquivo alterado",
|
||||
"session.review.filesChangedCount.other": "{{count}} arquivos alterados",
|
||||
"session.review.filesChangedCount.many": "{{count}} arquivos alterados",
|
||||
"settings.about.writtenByNames": "Escrito por {{names}}",
|
||||
"settings.about.illustratedByNames": "Ilustrado por {{names}}",
|
||||
"home.projects.all": "Todos os projetos",
|
||||
"session.tab.files": "Arquivos",
|
||||
"session.files.openTabs": "Arquivos abertos",
|
||||
"session.tab.usage": "Uso",
|
||||
"session.view.select": "Visualização da sessão",
|
||||
"session.background.moveTasks": "Mover {{tasks}} para segundo plano",
|
||||
"session.background.moveRunning": "Mover para segundo plano",
|
||||
"session.background.inBackground": "Executando {{tasks}} em segundo plano",
|
||||
"session.background.tasksRunning.one": "{{count}} tarefa em segundo plano em execução",
|
||||
"session.background.tasksRunning.other": "{{count}} tarefas em segundo plano em execução",
|
||||
"session.background.combine": "{{first}} e {{second}}",
|
||||
"session.background.shell.one": "{{count}} shell",
|
||||
"session.background.shell.other": "{{count}} shells",
|
||||
"session.background.subagent.one": "{{count}} subagente",
|
||||
"session.background.subagent.other": "{{count}} subagentes",
|
||||
"session.timeline.working": "Trabalhando",
|
||||
"session.review.wrapLines": "Quebrar linhas",
|
||||
"session.websearch.title": "Pesquisa na web de terceiros",
|
||||
"session.websearch.description": "Selecione o provedor de pesquisa que os agentes usam para pesquisar na web",
|
||||
"session.websearch.provider": "Provedor de pesquisa",
|
||||
"session.websearch.any": "Qualquer um",
|
||||
"session.websearch.disable": "Não usar pesquisa",
|
||||
"session.websearch.enable": "Ativar",
|
||||
"session.websearch.loadFailed": "Não foi possível carregar os provedores de pesquisa.",
|
||||
"session.websearch.empty": "Nenhum provedor de pesquisa disponível.",
|
||||
"session.websearch.failed": "Não foi possível salvar sua escolha. Tente novamente.",
|
||||
"session.websearch.retry": "Tentar novamente",
|
||||
"session.new.worktree.draftPlaceholder": "Escreva um rascunho de acompanhamento enquanto o worktree é preparado…",
|
||||
"session.search.placeholder": "Localizar...",
|
||||
"session.search.noResults": "Nenhuma correspondência",
|
||||
"titlebar.tabs": "Abas",
|
||||
"titlebar.channel.local": "Local",
|
||||
"titlebar.channel.dev": "Dev",
|
||||
"titlebar.channel.beta": "Beta",
|
||||
"titlebar.toggleDebugTools": "Alternar ferramentas de depuração",
|
||||
"settings.tab.experimental": "Experimental",
|
||||
"settings.experimental.description": "Experimente recursos experimentais",
|
||||
"settings.tab.about": "Sobre",
|
||||
"settings.about.version": "Versão {{version}}",
|
||||
"settings.about.devVersion": "desenvolvimento",
|
||||
"settings.about.license": "Lançado sob a Licença MIT",
|
||||
"settings.about.writtenBy": "Escrito por",
|
||||
"settings.about.illustratedBy": "Ilustrado por",
|
||||
"settings.about.and": "e",
|
||||
"settings.about.otherContributor.one": "{{count}} outro",
|
||||
"settings.about.otherContributor.other": "{{count}} outros",
|
||||
"settings.about.firstPublished": "Publicado pela primeira vez no Missouri, EUA",
|
||||
"settings.about.firstIllustrated": "Ilustrado pela primeira vez em Londres, Inglaterra",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode, o agente de programação de código aberto",
|
||||
"settings.about.trademark": "OpenCode é uma marca registrada da Anomaly Innovations, Inc.",
|
||||
"settings.about.typeset": "Composto em Inter e IBM Plex Mono",
|
||||
"settings.about.tagline": "A IA não consegue criar um ótimo software sem você",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "Editar projeto",
|
||||
"settings.timeline.title": "Linha do tempo",
|
||||
"settings.timeline.detail": "Detalhamento da linha do tempo",
|
||||
"settings.timeline.description":
|
||||
"Escolha quanta atividade aparece na linha do tempo. As mensagens permanecem visíveis.",
|
||||
"settings.timeline.preset.everything": "Tudo",
|
||||
"settings.timeline.preset.detailed": "Detalhado",
|
||||
"settings.timeline.preset.compact": "Compacto",
|
||||
"settings.timeline.preset.quiet": "Discreto",
|
||||
"settings.timeline.preset.text-only": "Somente texto",
|
||||
"settings.timeline.description.everything":
|
||||
"Mostrar cada atividade separadamente. Expandir a saída do shell, as edições e o raciocínio.",
|
||||
"settings.timeline.description.detailed":
|
||||
"Expandir a saída do shell e as edições. Mostrar subagentes separadamente e agrupar outras atividades em Usado.",
|
||||
"settings.timeline.description.compact": "Agrupar todas as atividades em Usado com os detalhes recolhidos.",
|
||||
"settings.timeline.description.quiet": "Agrupar edições e subagentes em Usado. Ocultar outras atividades.",
|
||||
"settings.timeline.description.text-only": "Ocultar todas as atividades. Mostrar somente mensagens.",
|
||||
"settings.timeline.description.custom":
|
||||
"Usar o posicionamento e os detalhes selecionados para cada categoria de atividade.",
|
||||
"settings.timeline.custom": "Personalizado",
|
||||
"settings.timeline.advanced": "Avançado",
|
||||
"settings.timeline.advanced.description": "Defina o posicionamento e os detalhes de cada categoria de atividade.",
|
||||
"settings.timeline.category.shell": "Shell",
|
||||
"settings.timeline.category.edit": "Edições",
|
||||
"settings.timeline.category.thinking": "Raciocínio",
|
||||
"settings.timeline.category.subagents": "Subagentes",
|
||||
"settings.timeline.category.notices": "Avisos",
|
||||
"settings.timeline.category.tools": "Outras ferramentas",
|
||||
"settings.general.row.mobileDiffWrap.description":
|
||||
"Quebrar linhas longas nos diffs para dispositivos móveis em vez de rolar horizontalmente",
|
||||
"session.background.tasksRunning.many": "{{count}} tarefas em segundo plano em execução",
|
||||
"session.background.shell.many": "{{count}} shells",
|
||||
"session.background.subagent.many": "{{count}} subagentes",
|
||||
"settings.about.otherContributor.many": "{{count}} outros",
|
||||
"toast.migration.progress.clearingOldEvents": "Limpando eventos antigos",
|
||||
"toast.migration.progress.migratingSessions": "Migrando sessões",
|
||||
"session.new.workspace.existingLabel": "Worktree",
|
||||
"desktop.onboarding.defaultProject": "Projeto Padrão",
|
||||
"session.location.unavailable": "Local da sessão indisponível",
|
||||
"session.location.description": "Escolha outro diretório para continuar esta sessão.",
|
||||
"session.location.choose": "Escolher diretório",
|
||||
"session.location.worktree": "Escolher worktree",
|
||||
"session.location.worktreesFailed": "Falha ao carregar worktrees",
|
||||
"session.location.moving": "Movendo sessão…",
|
||||
"dialog.server.menu.hide": "Ocultar da lista de projetos",
|
||||
"dialog.server.menu.show": "Mostrar na lista de projetos",
|
||||
"session.queue.count.one": "{{count}} na fila",
|
||||
"session.queue.count.many": "{{count}} na fila",
|
||||
"session.queue.count.other": "{{count}} na fila",
|
||||
"session.queue.steer": "Orientar",
|
||||
"session.queue.send": "Enviar",
|
||||
"session.queue.steerTooltip": "Enviar sem interromper",
|
||||
"session.queue.remove": "Remover",
|
||||
"session.queue.reorder": "Reordenar prompt na fila",
|
||||
"session.new.worktree.creating": "Criando worktree",
|
||||
"settings.backToApp": "Voltar ao aplicativo",
|
||||
"settings.appearance.section.experimental": "Experimental",
|
||||
"settings.appearance.row.tabs.title": "Abas",
|
||||
"settings.appearance.row.tabs.description": "Escolha como as abas de sessão são organizadas",
|
||||
"settings.appearance.row.tabs.horizontal": "Horizontal",
|
||||
"settings.appearance.row.tabs.vertical": "Vertical",
|
||||
"settings.general.row.followUpBehavior.title": "Comportamento das mensagens de acompanhamento",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"Escolha entre colocar mensagens de acompanhamento na fila ou orientar a interação atual. Use {{keybind}} para alternar.",
|
||||
"settings.general.row.followUpBehavior.queue": "Colocar na fila",
|
||||
"settings.general.row.followUpBehavior.steer": "Orientar",
|
||||
"settings.general.row.reasoningMode.title": "Raciocínio do modelo",
|
||||
"settings.general.row.reasoningMode.description": "Escolha como o raciocínio do modelo é exibido na linha do tempo",
|
||||
"settings.general.row.reasoningMode.hidden": "Oculto",
|
||||
"settings.general.row.reasoningMode.compact": "Compacto",
|
||||
"settings.general.row.reasoningMode.full": "Completo",
|
||||
"session.new.workspace.createFrom": "Criar a partir da branch",
|
||||
"session.new.workspace.branch.search.placeholder": "Pesquisar branches",
|
||||
"desktop.menu.app": "OpenCode",
|
||||
"desktop.menu.file": "Arquivo",
|
||||
"desktop.menu.edit": "Editar",
|
||||
@@ -677,6 +1022,7 @@ export const dict = {
|
||||
"session.error.serverConnection": "Não é possível conectar a este servidor",
|
||||
"session.review.filesChanged": "{{count}} arquivos alterados",
|
||||
"session.review.change.one": "Alteração",
|
||||
"session.review.change.many": "Alterações",
|
||||
"session.review.change.other": "Alterações",
|
||||
"session.review.loadingChanges": "Carregando alterações…",
|
||||
"session.review.empty": "Nenhuma alteração nesta sessão ainda",
|
||||
@@ -1111,4 +1457,138 @@ export const dict = {
|
||||
"error.childStore.persistedProjectIconCreateFailed": "Falha ao criar ícone de projeto persistente",
|
||||
"error.childStore.storeCreateFailed": "Falha ao criar armazenamento",
|
||||
"terminal.connectionLost.abnormalClose": "WebSocket fechado anormalmente: {{code}}",
|
||||
|
||||
"provider.disconnect.toast.noCredentials.description": "Nenhuma credencial removível encontrada para {{provider}}.",
|
||||
"provider.disconnect.toast.failed.description": "Falha ao desconectar {{provider}}.",
|
||||
"toast.migration.failed.title": "Falha na migração de dados",
|
||||
"command.session.background": "Mover para segundo plano",
|
||||
"session.timeline.notice.finished": "{{actor}} finalizado",
|
||||
"session.timeline.notice.failed": "{{actor}} falhou",
|
||||
"session.timeline.notice.cancelled": "{{actor}} cancelado",
|
||||
"settings.tab.preferences": "Preferências",
|
||||
"settings.tab.notifications": "Notificações",
|
||||
"settings.tab.projects": "Projetos",
|
||||
"settings.tab.extensions": "Extensões",
|
||||
"settings.preferences.description": "Personalize preferências, tema e comportamento padrão",
|
||||
"settings.appearance.description": "Personalize tema e fontes",
|
||||
"settings.notifications.description": "Escolha quando receber notificações e ouvir sons",
|
||||
"settings.shortcuts.description": "Personalize atalhos para ações comuns",
|
||||
"settings.servers.description": "Gerenciar conexões de servidor",
|
||||
"settings.projects.title": "Projetos",
|
||||
"settings.projects.description": "Gerencie as configurações do projeto neste servidor",
|
||||
"settings.projects.empty": "Nenhum projeto encontrado",
|
||||
"settings.projects.server.all": "Todos os servidores",
|
||||
"settings.mcps.description": "Gerenciar servidores e ferramentas do Model Context Protocol (MCP)",
|
||||
"settings.extensions.description": "Gerenciar extensões disponíveis neste servidor",
|
||||
"settings.extensions.tab.mcps": "MCP",
|
||||
"settings.extensions.tab.skills": "Habilidades",
|
||||
"settings.extensions.availableAll": "Disponível para todos os projetos",
|
||||
"settings.extensions.manageConfig": "Gerenciar em opencode.json",
|
||||
"settings.extensions.addSkills": "Como adicionar habilidades",
|
||||
"dialog.server.authenticate.title": "Autenticar",
|
||||
"project.settings.general.description": "Gerenciar o nome e a aparência do projeto",
|
||||
"project.settings.scripts": "Roteiros",
|
||||
"project.settings.scripts.description": "Configurar scripts para este projeto",
|
||||
"project.settings.extensions.description": "Ver extensões disponíveis para este projeto",
|
||||
"project.settings.extensions.tab.lsps": "LSPs",
|
||||
"project.settings.extensions.added": "Adicionado a este projeto",
|
||||
"project.settings.extensions.shared": "Compartilhado com todos os projetos",
|
||||
"project.settings.extensions.lsp.detected": "Servidores de linguagem detectados",
|
||||
"project.settings.extensions.lsp.description": "Detectado automaticamente em tipos de arquivo",
|
||||
"project.settings.extensions.setupRequired": "Configuração necessária",
|
||||
"settings.general.section.general": "Em geral",
|
||||
"common.viewAll": "Ver tudo",
|
||||
"session.new.workspace.local.tooltip": "Usar checkout atual",
|
||||
"session.new.workspace.new.tooltip": "Criar checkout isolado",
|
||||
"session.new.workspace.fromBranch": "de {{branch}}",
|
||||
"session.new.workspace.trigger.tooltip": "Selecione onde executar a sessão",
|
||||
"session.new.workspace.search.placeholder": "Pesquisar espaços de trabalho",
|
||||
"settings.tab.workspaces": "Espaços de trabalho",
|
||||
"settings.workspaces.filter.all": "Todos os projetos",
|
||||
"settings.workspaces.empty": "Sem espaços de trabalho",
|
||||
"settings.workspaces.count.one": "Espaço de trabalho {{count}}",
|
||||
"settings.workspaces.count.other": "Espaços de trabalho {{count}}",
|
||||
"settings.workspaces.sessions.one": "Sessão {{count}} em {{project}}",
|
||||
"settings.workspaces.sessions.other": "Sessões {{count}} em {{project}}",
|
||||
"settings.workspaces.lastActiveSession": "Última sessão ativa",
|
||||
"settings.workspaces.deleteAll": "Excluir todos os espaços de trabalho",
|
||||
"settings.workspaces.delete.warning":
|
||||
"O diretório e a ramificação do espaço de trabalho serão removidos permanentemente, incluindo quaisquer alterações não mescladas mostradas abaixo.",
|
||||
"settings.workspaces.delete.blocked.active": "O espaço de trabalho ativo não pode ser excluído.",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"As sessões vinculadas permanecerão, mas seu diretório de trabalho será removido permanentemente.",
|
||||
"settings.workspaces.default.title": "Ambiente padrão",
|
||||
"settings.workspaces.default.description": "Escolha onde as novas sessões começam",
|
||||
"settings.workspaces.default.lastUsed": "Última utilização por projeto",
|
||||
"settings.workspaces.default.local": "Diretório local",
|
||||
"settings.workspaces.default.new": "Novo espaço de trabalho",
|
||||
"workspace.move.title": "Mover para o espaço de trabalho",
|
||||
"workspace.move.menu.title": "Mover sessão para",
|
||||
"workspace.move.failed": "Falha ao mover sessão",
|
||||
"workspace.lifecycle.creating": "Criando espaço de trabalho",
|
||||
"workspace.lifecycle.created": "Espaço de trabalho criado",
|
||||
"workspace.lifecycle.starting": "Iniciando sessão",
|
||||
"workspace.onboarding.title": "Isolar sessões com espaços de trabalho",
|
||||
"workspace.onboarding.description":
|
||||
"Cada um recebe seu próprio checkout, então nada interfere no seu repositório local",
|
||||
"workspace.lifecycle.moving": "Movendo para o espaço de trabalho",
|
||||
"workspace.lifecycle.set": "Espaço de trabalho definido",
|
||||
"session.summary.title": "Detalhes da sessão",
|
||||
"session.summary.noBranch": "Sem branch",
|
||||
"session.summary.basedOn": "Baseado em {{branch}}",
|
||||
"settings.workspaces.count.many": "{{count}} espaços de trabalho",
|
||||
"settings.workspaces.sessions.many": "{{count}} sessões em {{project}}",
|
||||
"desktop.menu.installCli": "Instalar CLI...",
|
||||
"desktop.cli.installed.title": "CLI instalada",
|
||||
"desktop.cli.installed.message": "CLI instalada em {{path}}\n\nReinicie o terminal para usar o comando 'opencode2'.",
|
||||
"desktop.cli.failed.title": "Falha na instalação",
|
||||
"desktop.cli.failed.message": "Falha ao instalar a CLI: {{error}}",
|
||||
"command.project.copyID": "Copiar ID do projeto",
|
||||
"command.session.copyID": "Copiar ID da sessão",
|
||||
"server.row.incompatible":
|
||||
"Este servidor está executando o OpenCode {{version}}, que não é compatível com este aplicativo. Atualize-o para o OpenCode V2 para continuar.",
|
||||
"toast.session.copyID.failed.title": "Falha ao copiar o ID da sessão",
|
||||
"toast.session.copyID.failed.description": "Ocorreu um erro ao copiar o ID da sessão",
|
||||
"toast.project.copyID.failed.title": "Falha ao copiar o ID do projeto",
|
||||
"toast.project.copyID.failed.description": "Ocorreu um erro ao copiar o ID do projeto",
|
||||
"error.page.title.status": "Falha na solicitação ao servidor",
|
||||
"error.page.description.status": "O servidor retornou uma resposta HTTP {{status}}.",
|
||||
"error.page.action.reload": "Recarregar",
|
||||
"session.error.incompatible": "Esta versão do servidor não é compatível",
|
||||
"session.error.incompatible.description":
|
||||
"{{server}} está executando o OpenCode {{version}}, que não é compatível com este aplicativo. Atualize o servidor para o OpenCode V2 para continuar.",
|
||||
"session.background.moveInline": "Pressione {{keybind}} para mover o trabalho em execução para segundo plano",
|
||||
"session.background.running": "Trabalho em execução em segundo plano",
|
||||
"session.background.runningCount.one": "{{count}} item em execução em segundo plano",
|
||||
"session.background.runningCount.other": "{{count}} itens em execução em segundo plano",
|
||||
"session.background.runningCount.many": "{{count}} de itens em execução em segundo plano",
|
||||
"settings.general.row.terminalPlacement.title": "Posição do terminal",
|
||||
"settings.general.row.terminalPlacement.description": "Escolha onde o terminal será aberto nas sessões",
|
||||
"settings.general.row.terminalPlacement.side": "Lateral",
|
||||
"settings.general.row.terminalPlacement.bottom": "Inferior",
|
||||
"command.debugBar.toggle": "Alternar barra de depuração",
|
||||
"command.session.location.cycle": "Alternar local da sessão",
|
||||
"dialog.provider.anthropic.note": "Acesso direto aos modelos Claude por chave de API",
|
||||
"provider.connect.title.anthropicProMax": "Entrar com a Anthropic",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"prompt.toast.uploading.cancel": "Cancelar envio",
|
||||
"prompt.toast.uploading.cancelFile": "Cancelar envio de {{filename}}",
|
||||
"prompt.toast.uploadFailed.title": "Falha no envio",
|
||||
"session.browser.empty.title": "Insira a URL",
|
||||
"session.browser.empty.description": "Ou peça “Abrir no navegador do aplicativo”",
|
||||
"session.browser.failed.title": "Não foi possível acessar a URL",
|
||||
"session.browser.failed.description": "Verifique a URL e sua conexão e tente novamente.",
|
||||
"debugBar.providerAriaLabel": "Diagnóstico de desempenho do provedor",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttft.tip": "Tempo entre o envio da solicitação ao provedor e a primeira saída do modelo.",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.ttfa.tip": "Tempo entre o envio da solicitação ao provedor e o primeiro texto da resposta.",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.tps.tip": "Tokens de saída por segundo após a primeira saída do modelo.",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
"debugBar.e2e.tip": "Tempo entre o envio da solicitação ao provedor e o fim do fluxo de resposta.",
|
||||
"settings.updates.action.download": "Baixar o OpenCode",
|
||||
"settings.updates.migration.title": "Migrar da versão Beta para a Estável",
|
||||
"settings.updates.migration.description":
|
||||
"Por enquanto, o OpenCode Beta está migrando para o OpenCode Estável. Baixe a versão {{version}} e instale o OpenCode pela imagem de disco para continuar recebendo atualizações.",
|
||||
}
|
||||
|
||||
@@ -627,7 +627,6 @@ export const dict = {
|
||||
"toast.context.noLineSelection.title": "Nema odabranih linija",
|
||||
"toast.context.noLineSelection.description": "Prvo odaberi raspon linija u kartici datoteke.",
|
||||
|
||||
|
||||
"toast.session.unshare.success.title": "Dijeljenje sesije ukinuto",
|
||||
"toast.session.unshare.success.description": "Dijeljenje sesije je uspješno ukinuto!",
|
||||
"toast.session.unshare.failed.title": "Neuspjelo ukidanje dijeljenja",
|
||||
@@ -1189,4 +1188,477 @@ export const dict = {
|
||||
"error.childStore.persistedProjectIconCreateFailed": "Nije uspjelo kreiranje trajne ikone projekta",
|
||||
"error.childStore.storeCreateFailed": "Nije uspjelo kreiranje skladišta",
|
||||
"terminal.connectionLost.abnormalClose": "WebSocket zatvoren nenormalno: {{code}}",
|
||||
"provider.disconnect.toast.noCredentials.description": "Nisu pronađeni uklonjivi akreditivi za {{provider}}.",
|
||||
"provider.disconnect.toast.failed.description": "Prekid veze {{provider}} nije uspio.",
|
||||
"toast.migration.failed.title": "Migracija podataka nije uspjela",
|
||||
"command.session.background": "Premjesti u pozadinu",
|
||||
"session.timeline.notice.finished": "{{actor}} završeno",
|
||||
"session.timeline.notice.failed": "{{actor}} nije uspio",
|
||||
"session.timeline.notice.cancelled": "{{actor}} otkazan",
|
||||
"settings.tab.preferences": "Postavke",
|
||||
"settings.tab.notifications": "Obavještenja",
|
||||
"settings.tab.projects": "Projekti",
|
||||
"settings.tab.extensions": "Ekstenzije",
|
||||
"settings.preferences.description": "Prilagodite postavke i temu i zadano ponašanje",
|
||||
"settings.appearance.description": "Prilagodite temu i fontove",
|
||||
"settings.notifications.description": "Odaberite kada ćete primati obavještenja i čuti zvukove",
|
||||
"settings.shortcuts.description": "Prilagodite prečice za uobičajene radnje",
|
||||
"settings.servers.description": "Upravljajte serverskim vezama",
|
||||
"settings.projects.title": "Projekti",
|
||||
"settings.projects.description": "Upravljajte postavkama projekta na ovom serveru",
|
||||
"settings.projects.empty": "Nije pronađen nijedan projekat",
|
||||
"settings.projects.server.all": "Svi serveri",
|
||||
"settings.mcps.description": "Upravljajte serverima i alatima Model Context Protocol (MCP).",
|
||||
"settings.extensions.description": "Upravljajte ekstenzijama dostupnim na ovom serveru",
|
||||
"settings.extensions.tab.mcps": "MCP-ovi",
|
||||
"settings.extensions.tab.skills": "Vještine",
|
||||
"settings.extensions.availableAll": "Dostupan za sve projekte",
|
||||
"settings.extensions.manageConfig": "Upravljajte u opencode.json",
|
||||
"settings.extensions.addSkills": "Kako dodati vještine",
|
||||
"dialog.server.authenticate.title": "Autentificiraj",
|
||||
"project.settings.general.description": "Upravljajte imenom i izgledom projekta",
|
||||
"project.settings.scripts": "Skripte",
|
||||
"project.settings.scripts.description": "Konfigurirajte skripte za ovaj projekat",
|
||||
"project.settings.extensions.description": "Pogledajte proširenja dostupna za ovaj projekat",
|
||||
"project.settings.extensions.tab.lsps": "LSP-ovi",
|
||||
"project.settings.extensions.added": "Dodato ovom projektu",
|
||||
"project.settings.extensions.shared": "Dijeljeno sa svim projektima",
|
||||
"project.settings.extensions.lsp.detected": "Otkriveni jezički serveri",
|
||||
"project.settings.extensions.lsp.description": "Automatski otkriveno prema tipovima datoteka",
|
||||
"project.settings.extensions.setupRequired": "Potrebna je konfiguracija",
|
||||
"settings.general.section.general": "Opšte",
|
||||
"common.viewAll": "Pogledaj sve",
|
||||
"session.new.workspace.local.tooltip": "Koristi trenutnu radnu kopiju",
|
||||
"session.new.workspace.new.tooltip": "Kreiraj izolovanu radnu kopiju",
|
||||
"session.new.workspace.fromBranch": "od {{branch}}",
|
||||
"session.new.workspace.trigger.tooltip": "Odaberite gdje želite pokrenuti sesiju",
|
||||
"session.new.workspace.search.placeholder": "Pretražite radne prostore",
|
||||
"settings.tab.workspaces": "Radni prostori",
|
||||
"settings.workspaces.filter.all": "Svi projekti",
|
||||
"settings.workspaces.empty": "Nema radnih prostora",
|
||||
"settings.workspaces.count.one": "{{count}} radni prostor",
|
||||
"settings.workspaces.count.other": "{{count}} radni prostori",
|
||||
"settings.workspaces.sessions.one": "{{count}} sesija u {{project}}",
|
||||
"settings.workspaces.sessions.other": "{{count}} sesije u {{project}}",
|
||||
"settings.workspaces.lastActiveSession": "Zadnja aktivna sesija",
|
||||
"settings.workspaces.deleteAll": "Izbrišite sve radne prostore",
|
||||
"settings.workspaces.delete.warning":
|
||||
"Direktorij i grana radnog prostora će biti trajno uklonjeni, uključujući sve nespojene promjene prikazane u nastavku.",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"Radna stabla s nespojenim promjenama, povezanim sesijama ili aktivnim lokacijama bit će sačuvana.",
|
||||
"settings.workspaces.delete.blocked.active": "Aktivni radni prostor se ne može izbrisati.",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"Povezane sesije će ostati, ali će njihov radni direktorij biti trajno uklonjen.",
|
||||
"settings.workspaces.default.title": "Zadano okruženje",
|
||||
"settings.workspaces.default.description": "Odaberite gdje počinju nove sesije",
|
||||
"settings.workspaces.default.lastUsed": "Posljednje korišteno po projektu",
|
||||
"settings.workspaces.default.local": "Lokalni imenik",
|
||||
"settings.workspaces.default.new": "Novi radni prostor",
|
||||
"workspace.move.title": "Premjestite se u radni prostor",
|
||||
"workspace.move.menu.title": "Premjesti sesiju na",
|
||||
"workspace.move.failed": "Premještanje sesije nije uspjelo",
|
||||
"workspace.lifecycle.creating": "Kreiranje radnog prostora",
|
||||
"workspace.lifecycle.created": "Radni prostor kreiran",
|
||||
"workspace.lifecycle.starting": "Početak sesije",
|
||||
"workspace.onboarding.title": "Izolirajte sesije s radnim prostorima",
|
||||
"workspace.onboarding.description": "Svaka dobija vlastitu radnu kopiju, tako da ništa ne ometa lokalni repozitorij",
|
||||
"workspace.lifecycle.moving": "Prelazak u radni prostor",
|
||||
"workspace.lifecycle.set": "Radni prostor postavljen",
|
||||
"session.summary.title": "Detalji sesije",
|
||||
"session.summary.noBranch": "Nema grane",
|
||||
"session.summary.basedOn": "Zasnovano na {{branch}}",
|
||||
"settings.workspaces.count.few": "{{count}} radna prostora",
|
||||
"settings.workspaces.sessions.few": "{{count}} sesije u {{project}}",
|
||||
"desktop.menu.installCli": "Instaliraj CLI...",
|
||||
"desktop.cli.installed.title": "CLI je instaliran",
|
||||
"desktop.cli.installed.message":
|
||||
"CLI je instaliran u {{path}}\n\nPonovo pokrenite terminal da biste koristili naredbu 'opencode2'.",
|
||||
"desktop.cli.failed.title": "Instalacija nije uspjela",
|
||||
"desktop.cli.failed.message": "Instalacija CLI-ja nije uspjela: {{error}}",
|
||||
"command.project.copyID": "Kopiraj ID projekta",
|
||||
"command.session.copyID": "Kopiraj ID sesije",
|
||||
"server.row.incompatible":
|
||||
"Ovaj server koristi OpenCode {{version}}, koji nije kompatibilan s ovom aplikacijom. Nadogradite ga na OpenCode V2 da biste nastavili.",
|
||||
"toast.session.copyID.failed.title": "Kopiranje ID-a sesije nije uspjelo",
|
||||
"toast.session.copyID.failed.description": "Došlo je do greške pri kopiranju ID-a sesije",
|
||||
"toast.project.copyID.failed.title": "Kopiranje ID-a projekta nije uspjelo",
|
||||
"toast.project.copyID.failed.description": "Došlo je do greške pri kopiranju ID-a projekta",
|
||||
"error.page.title.status": "Zahtjev serveru nije uspio",
|
||||
"error.page.description.status": "Server je vratio HTTP odgovor {{status}}.",
|
||||
"error.page.action.reload": "Ponovo učitaj",
|
||||
"session.error.incompatible": "Ova verzija servera nije podržana",
|
||||
"session.error.incompatible.description":
|
||||
"{{server}} koristi OpenCode {{version}}, koji nije kompatibilan s ovom aplikacijom. Nadogradite server na OpenCode V2 da biste nastavili.",
|
||||
"session.background.moveInline": "Pritisnite {{keybind}} da premjestite aktivni rad u pozadinu",
|
||||
"session.background.running": "Rad se izvršava u pozadini",
|
||||
"session.background.runningCount.one": "{{count}} stavka se izvršava u pozadini",
|
||||
"session.background.runningCount.few": "{{count}} stavke se izvršavaju u pozadini",
|
||||
"session.background.runningCount.other": "{{count}} stavki se izvršava u pozadini",
|
||||
"settings.general.row.terminalPlacement.title": "Položaj terminala",
|
||||
"settings.general.row.terminalPlacement.description": "Odaberite gdje se terminal otvara u sesijama",
|
||||
"settings.general.row.terminalPlacement.side": "Sa strane",
|
||||
"settings.general.row.terminalPlacement.bottom": "Na dnu",
|
||||
"session.location.unavailable": "Lokacija sesije nije dostupna",
|
||||
"session.location.description": "Odaberite drugi direktorij da nastavite ovu sesiju.",
|
||||
"session.location.choose": "Odaberi direktorij",
|
||||
"session.location.worktree": "Odaberi worktree",
|
||||
"session.location.worktreesFailed": "Učitavanje worktreeova nije uspjelo",
|
||||
"session.location.moving": "Premještanje sesije…",
|
||||
"dialog.server.menu.hide": "Sakrij sa spiska projekata",
|
||||
"dialog.server.menu.show": "Prikaži na spisku projekata",
|
||||
"session.queue.count.one": "{{count}} stavka u redu čekanja",
|
||||
"session.queue.count.few": "{{count}} stavke u redu čekanja",
|
||||
"session.queue.count.other": "{{count}} stavki u redu čekanja",
|
||||
"session.queue.steer": "Usmjeri",
|
||||
"session.queue.send": "Pošalji",
|
||||
"session.queue.steerTooltip": "Pošalji bez prekidanja",
|
||||
"session.queue.remove": "Ukloni",
|
||||
"session.queue.reorder": "Promijeni redoslijed upita u redu čekanja",
|
||||
"session.new.worktree.creating": "Kreiranje worktreea",
|
||||
"settings.backToApp": "Nazad u aplikaciju",
|
||||
"settings.appearance.section.experimental": "Eksperimentalno",
|
||||
"settings.appearance.row.tabs.title": "Kartice",
|
||||
"settings.appearance.row.tabs.description": "Odaberite raspored kartica sesija",
|
||||
"settings.appearance.row.tabs.horizontal": "Vodoravno",
|
||||
"settings.appearance.row.tabs.vertical": "Uspravno",
|
||||
"settings.general.row.followUpBehavior.title": "Ponašanje naknadnih poruka",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"Odaberite hoće li se naknadne poruke staviti u red čekanja ili usmjeriti trenutni korak. Koristite {{keybind}} za prebacivanje.",
|
||||
"settings.general.row.followUpBehavior.queue": "Red čekanja",
|
||||
"settings.general.row.followUpBehavior.steer": "Usmjeri",
|
||||
"settings.general.row.reasoningMode.title": "Rasuđivanje modela",
|
||||
"settings.general.row.reasoningMode.description":
|
||||
"Odaberite kako se rasuđivanje modela prikazuje na vremenskoj traci",
|
||||
"settings.general.row.reasoningMode.hidden": "Sakriveno",
|
||||
"settings.general.row.reasoningMode.compact": "Sažeto",
|
||||
"settings.general.row.reasoningMode.full": "Potpuno",
|
||||
"session.new.workspace.createFrom": "Kreiraj iz grane",
|
||||
"session.new.workspace.branch.search.placeholder": "Pretraži grane",
|
||||
"desktop.onboarding.defaultProject": "Podrazumijevani projekat",
|
||||
"toast.migration.progress.clearingOldEvents": "Brisanje starih događaja",
|
||||
"toast.migration.progress.migratingSessions": "Migracija sesija",
|
||||
"session.new.workspace.existingLabel": "Radno stablo",
|
||||
"session.review.change.few": "Izmjene",
|
||||
"home.projects.all": "Svi projekti",
|
||||
"session.tab.files": "Datoteke",
|
||||
"session.files.openTabs": "Otvorene datoteke",
|
||||
"session.tab.usage": "Upotreba",
|
||||
"session.view.select": "Prikaz sesije",
|
||||
"session.background.moveTasks": "Premjesti {{tasks}} u pozadinu",
|
||||
"session.background.moveRunning": "Premjesti u pozadinu",
|
||||
"session.background.inBackground": "Pokretanje {{tasks}} u pozadini",
|
||||
"session.background.tasksRunning.one": "{{count}} pozadinski zadatak je pokrenut",
|
||||
"session.background.tasksRunning.other": "{{count}} pozadinskih zadataka je pokrenuto",
|
||||
"session.background.combine": "{{first}} i {{second}}",
|
||||
"session.background.shell.one": "{{count}} ljuska",
|
||||
"session.background.shell.other": "{{count}} ljuski",
|
||||
"session.background.subagent.one": "{{count}} podagent",
|
||||
"session.background.subagent.other": "{{count}} podagenata",
|
||||
"session.timeline.working": "U tijeku",
|
||||
"session.review.wrapLines": "Prelamaj retke",
|
||||
"session.websearch.title": "Web pretraga treće strane",
|
||||
"session.websearch.description": "Odaberite provajdera pretraživanja koje agenti koriste za pretraživanje weba",
|
||||
"session.websearch.provider": "Provajder pretraživanja",
|
||||
"session.websearch.any": "Bilo koji",
|
||||
"session.websearch.disable": "Nemojte koristiti pretragu",
|
||||
"session.websearch.enable": "Omogući",
|
||||
"session.websearch.loadFailed": "Nije moguće učitati provajdere pretraživanja.",
|
||||
"session.websearch.empty": "Nema dostupnih provajdera pretrage.",
|
||||
"session.websearch.failed": "Nije moguće sačuvati vaš izbor. Molimo pokušajte ponovo.",
|
||||
"session.websearch.retry": "Pokušaj ponovo",
|
||||
"session.new.worktree.draftPlaceholder": "Napišite naknadnu poruku dok se radno stablo priprema…",
|
||||
"session.search.placeholder": "Pronađi...",
|
||||
"session.search.noResults": "Nema podudaranja",
|
||||
"titlebar.tabs": "Kartice",
|
||||
"titlebar.channel.local": "Lokalno",
|
||||
"titlebar.channel.dev": "Dev",
|
||||
"titlebar.channel.beta": "Beta",
|
||||
"titlebar.toggleDebugTools": "Prebaci alate za otklanjanje grešaka",
|
||||
"settings.tab.experimental": "Eksperimentalno",
|
||||
"settings.experimental.description": "Isprobajte eksperimentalne funkcije",
|
||||
"settings.tab.about": "O programu",
|
||||
"settings.about.version": "Verzija {{version}}",
|
||||
"settings.about.devVersion": "razvoj",
|
||||
"settings.about.license": "Izdan pod MIT License",
|
||||
"settings.about.writtenBy": "Napisao",
|
||||
"settings.about.illustratedBy": "Ilustrovao",
|
||||
"settings.about.and": "i",
|
||||
"settings.about.otherContributor.one": "{{count}} drugi",
|
||||
"settings.about.otherContributor.other": "{{count}} drugih",
|
||||
"settings.about.firstPublished": "Prvi put objavljeno u Missouriju, SAD",
|
||||
"settings.about.firstIllustrated": "Prvi put ilustrovan u Londonu, Engleska",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode, agent za kodiranje otvorenog koda",
|
||||
"settings.about.trademark": "OpenCode je registrovani zaštitni znak Anomaly Innovations, Inc.",
|
||||
"settings.about.typeset": "Postavljen u Inter i IBM Plex Mono",
|
||||
"settings.about.tagline": "AI ne može napraviti odličan softver bez vas",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "Uredi projekat",
|
||||
"settings.timeline.title": "Vremenska linija",
|
||||
"settings.timeline.detail": "Detalji vremenske linije",
|
||||
"settings.timeline.description":
|
||||
"Odaberite koliko aktivnosti se pojavljuje na vremenskoj liniji. Poruke ostaju vidljive.",
|
||||
"settings.timeline.preset.everything": "Sve",
|
||||
"settings.timeline.preset.detailed": "Detaljno",
|
||||
"settings.timeline.preset.compact": "Sažeto",
|
||||
"settings.timeline.preset.quiet": "Tiho",
|
||||
"settings.timeline.preset.text-only": "Samo tekst",
|
||||
"settings.timeline.description.everything":
|
||||
"Prikaži sve aktivnosti zasebno. Proširite izlaz školjke, uređivanja i razmišljanja.",
|
||||
"settings.timeline.description.detailed":
|
||||
"Proširivanje izlaza ljuske i uređivanja. Prikaži podagente odvojeno i grupiši ostale aktivnosti u Korišteno.",
|
||||
"settings.timeline.description.compact": "Grupacija svih aktivnosti u Korišteno s detaljima je srušena.",
|
||||
"settings.timeline.description.quiet": "Grupni uređivači i subagenti u Korišteno. Sakrij drugu aktivnost.",
|
||||
"settings.timeline.description.text-only": "Sakrij sve aktivnosti. Prikaži samo poruke.",
|
||||
"settings.timeline.description.custom": "Koristite odabrani položaj i detalje za svaku kategoriju aktivnosti.",
|
||||
"settings.timeline.custom": "Prilagođeno",
|
||||
"settings.timeline.advanced": "Napredno",
|
||||
"settings.timeline.advanced.description": "Postavite položaj i detalje za svaku kategoriju aktivnosti.",
|
||||
"settings.timeline.category.shell": "Ljuska",
|
||||
"settings.timeline.category.edit": "Uređivanja",
|
||||
"settings.timeline.category.thinking": "Razmišljanje",
|
||||
"settings.timeline.category.subagents": "Podagenti",
|
||||
"settings.timeline.category.notices": "Napomene",
|
||||
"settings.timeline.category.tools": "Ostali alati",
|
||||
"settings.general.row.mobileDiffWrap.description":
|
||||
"Umotajte dugačke redove u mobilne razlike umjesto horizontalnog pomicanja",
|
||||
"session.background.tasksRunning.few": "{{count}} pozadinska zadatka su pokrenuta",
|
||||
"session.background.shell.few": "{{count}} ljuske",
|
||||
"session.background.subagent.few": "{{count}} podagenta",
|
||||
"settings.about.otherContributor.few": "{{count}} druga",
|
||||
"provider.connect.error.unsupportedFields": "Ovaj obrazac za autentifikaciju sadrži nepodržana polja",
|
||||
"session.review.filesChangedCount.one": "{{count}} datoteka je izmijenjena",
|
||||
"session.review.filesChangedCount.few": "{{count}} datoteke su izmijenjene",
|
||||
"session.review.filesChangedCount.other": "{{count}} datoteka je izmijenjeno",
|
||||
"settings.about.writtenByNames": "Napisao {{names}}",
|
||||
"settings.about.illustratedByNames": "Ilustrovao {{names}}",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline": "Nije uspostavljena veza s hostom {{host}}. Vaš nacrt je sačuvan; udaljeni rad možda još traje.",
|
||||
"ssh.placeholder": "ssh korisnik@primjer.com",
|
||||
"ssh.add": "Dodaj SSH server",
|
||||
"ssh.server.menu.label": "SSH server",
|
||||
"ssh.target": "Host ili SSH naredba",
|
||||
"ssh.connect": "Poveži se",
|
||||
"ssh.connectTo": "Poveži se s hostom {{host}}",
|
||||
"ssh.authenticate": "SSH autentifikacija",
|
||||
"ssh.action.authenticate": "Autentificiraj",
|
||||
"ssh.session.disconnected": "SSH veza nije aktivna",
|
||||
"ssh.session.connecting": "Povezivanje sa SSH serverom",
|
||||
"ssh.session.reconnectDescription":
|
||||
"Ponovo se povežite da biste vidjeli ovu sesiju i nastavili raditi. Vaša udaljena sesija je sačuvana.",
|
||||
"ssh.session.reconnect": "Ponovo se poveži",
|
||||
"ssh.authenticationRequired": "Potrebna je autentifikacija za {{host}}",
|
||||
"ssh.trust": "Vjeruj i poveži se",
|
||||
"ssh.continue": "Nastavi",
|
||||
"ssh.retry": "Pokušaj ponovo",
|
||||
"ssh.update": "Ažuriraj i ponovo se poveži",
|
||||
"ssh.openProject": "Otvori projekat",
|
||||
"ssh.project": "Otvori projekat na hostu {{host}}",
|
||||
"ssh.disconnect": "Prekini vezu",
|
||||
"ssh.forget": "Zaboravi vezu",
|
||||
"ssh.stage.disconnected": "Veza je prekinuta. Udaljeni server je ostavljen da radi.",
|
||||
"ssh.stage.connecting": "Povezivanje putem SSH-a…",
|
||||
"ssh.stage.checking": "Provjera OpenCode-a…",
|
||||
"ssh.stage.downloading": "Preuzimanje servera…",
|
||||
"ssh.stage.uploading": "Slanje servera…",
|
||||
"ssh.stage.starting": "Povezivanje s OpenCode-om…",
|
||||
"ssh.stage.ready": "Povezano",
|
||||
"ssh.stage.authentication": "Potrebna je autentifikacija",
|
||||
"ssh.stage.incompatible": "Potrebno je ažuriranje servera",
|
||||
"ssh.stage.failed": "Povezivanje nije uspjelo",
|
||||
"ssh.error.input":
|
||||
"Unesite host ili naredbu za SSH povezivanje. Udaljene naredbe i nepodržane SSH opcije nisu dozvoljene.",
|
||||
"ssh.error.connection": "Nije bilo moguće uspostaviti SSH vezu. Provjerite mrežu i SSH konfiguraciju.",
|
||||
"ssh.error.platform":
|
||||
"Ova udaljena platforma nije podržana. Automatsko postavljanje trenutno zahtijeva Linux ili macOS na arhitekturi x64 ili arm64.",
|
||||
"ssh.error.version": "Udaljena usluga mora odgovarati ovoj verziji Desktopa prije povezivanja.",
|
||||
"ssh.error.install":
|
||||
"Nije bilo moguće instalirati udaljeni server. Provjerite vezu, prostor na disku i je li tar instaliran.",
|
||||
"ssh.error.unpublished":
|
||||
"Ova verzija Desktopa nema objavljen udaljeni server. Za razvojne verzije instalirajte i pokrenite V2 na hostu, pa pokušajte ponovo.",
|
||||
"ssh.error.service": "SSH je povezan, ali OpenCode server nije postao spreman.",
|
||||
"ssh.error.host-key":
|
||||
"Identitet hosta nije bilo moguće potvrditi. Provjerite njegov otisak prije ažuriranja poznatih SSH hostova.",
|
||||
"ssh.error.ssh-missing":
|
||||
"OpenSSH nije pronađen. Instalirajte OpenSSH klijent i provjerite je li ssh dostupan u varijabli PATH.",
|
||||
"command.browser.open": "Otvori preglednik",
|
||||
"command.browser.reload": "Ponovo učitaj stranicu preglednika",
|
||||
"command.session.summary.toggle": "Prikaži ili sakrij sažetak",
|
||||
"common.color.orange": "narandžasta",
|
||||
"common.color.yellow": "žuta",
|
||||
"common.color.cyan": "cijan",
|
||||
"common.color.green": "zelena",
|
||||
"common.color.red": "crvena",
|
||||
"common.color.pink": "ružičasta",
|
||||
"common.color.blue": "plava",
|
||||
"common.color.purple": "ljubičasta",
|
||||
"common.color.gray": "siva",
|
||||
"mcp.auth.interactiveForm": "MCP server {{name}} zahtijeva interaktivni obrazac za autentifikaciju",
|
||||
"server.connect.title": "Poveži se sa serverom",
|
||||
"server.connect.description": "Unesite adresu servera i lozinku da biste započeli.",
|
||||
"server.connect.button": "Poveži se",
|
||||
"server.connect.address.invalid": "Unesite ispravnu HTTP ili HTTPS adresu servera.",
|
||||
"server.connect.failed": "Povezivanje nije uspjelo. Provjerite adresu servera i lozinku, pa pokušajte ponovo.",
|
||||
"server.connect.pair.description": "Pokrenite ovu naredbu na računaru da biste dobili podatke za povezivanje.",
|
||||
"server.connect.scan": "Skeniraj QR kod",
|
||||
"server.connect.scan.description": "Usmjerite kameru prema QR kodu koji prikazuje opencode pair.",
|
||||
"server.connect.scan.invalid": "Ovo nije OpenCode kod za uparivanje. Skenirajte kod koji prikazuje opencode pair.",
|
||||
"server.connect.camera": "Kamera za uparivanje",
|
||||
"server.connect.camera.starting": "Otvaranje kamere…",
|
||||
"server.connect.mixedContent":
|
||||
"Nije se moguće povezati s ovim HTTP serverom s HTTPS stranice. Umjesto toga koristite HTTPS adresu servera.",
|
||||
"server.connect.camera.insecure":
|
||||
"Za skeniranje QR koda ovu stranicu morate otvoriti putem HTTPS-a ili na localhostu.",
|
||||
"server.connect.camera.unavailable": "Ovom pregledniku nije dostupna kamera. Ručno unesite podatke za povezivanje.",
|
||||
"server.connect.camera.error":
|
||||
"Kameru nije bilo moguće otvoriti. Dozvolite pristup kameri ili ručno unesite podatke za povezivanje.",
|
||||
"dialog.server.menu.remove": "Ukloni",
|
||||
"file.error.notFound": "Datoteka nije pronađena: {{name}}",
|
||||
"toast.migration.progress.migratingSessions.current": "Migracija sesija {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "Migracija sesija {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "Migracija podataka",
|
||||
"toast.migration.progress.working.current": "Migracija podataka {{current}}",
|
||||
"toast.migration.progress.working.progress": "Migracija podataka {{current}}/{{total}}",
|
||||
"home.workspaceTip": "Pokrenite sljedeću sesiju u novom radnom prostoru kako bi promjene ostale izolovane",
|
||||
"session.tab.browser": "Preglednik",
|
||||
"session.tab.add": "Dodaj karticu",
|
||||
"session.queue.attachments.one": "Još {{count}} prilog",
|
||||
"session.queue.attachments.few": "Još {{count}} priloga",
|
||||
"session.queue.attachments.other": "Još {{count}} priloga",
|
||||
"session.browser.address": "Adresa preglednika",
|
||||
"session.browser.replaced": "Upravljanje preglednikom premješteno je u drugi prozor Desktopa.",
|
||||
"session.browser.unsupported": "Ova aplikacija za računar ne podržava okno preglednika.",
|
||||
"session.browser.suspended":
|
||||
"Preglednik je obustavljen. Stupite u interakciju s ovom sesijom da biste se ponovo povezali.",
|
||||
"session.browser.address.placeholder": "Unesite URL",
|
||||
"settings.backToSettings": "Nazad na postavke",
|
||||
"settings.backToProjects": "Nazad na projekte",
|
||||
"settings.search.placeholder": "Pretraži",
|
||||
"settings.search.results": "Rezultati postavki",
|
||||
"settings.search.group.pages": "Stranice",
|
||||
"settings.search.group.settings": "Postavke",
|
||||
"settings.search.group.projects": "Projekti",
|
||||
"settings.search.group.servers": "Serveri",
|
||||
"settings.search.result": "{{title}}, {{scope}}, {{page}}",
|
||||
"settings.search.page": "{{title}}, {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}, {{page}}",
|
||||
"settings.search.empty": "Nema rezultata za {{query}}",
|
||||
"settings.search.empty.query": "„{{query}}“",
|
||||
"settings.search.refine": "Suzite pretragu da biste vidjeli određenije rezultate.",
|
||||
"settings.server.description": "Upravljajte vezom i postavkama ovog servera",
|
||||
"settings.server.section.connection": "Veza",
|
||||
"settings.server.preferences.websearch.title": "Pretraga treće strane",
|
||||
"settings.server.preferences.websearch.description":
|
||||
"Odaberite pružatelja pretrage kojeg agenti koriste za pretraživanje weba",
|
||||
"settings.projects.search.placeholder": "Pretraži projekte",
|
||||
"project.settings.name.title": "Naziv projekta",
|
||||
"project.settings.name.description": "Naziv koji se prikazuje za ovaj projekat u cijelom OpenCode-u",
|
||||
"project.settings.icon.description": "Preporučeno: 128 × 128 px. Kliknite ili prevucite sliku da biste je poslali.",
|
||||
"project.settings.color.description": "Koristi se za ikonu projekta kada nije postavljena prilagođena slika",
|
||||
"project.settings.worktree.startup.description": "Pokreće se jednom nakon kreiranja novog worktreea",
|
||||
"project.settings.worktree.startup.hint.base": "Koristite $OPENCODE_WORKTREE_BASE za osnovni worktree.",
|
||||
"project.settings.worktree.startup.hint.new": "Koristite $OPENCODE_WORKTREE_PATH za novi worktree.",
|
||||
"project.settings.extensions.empty.mcps.title": "Još nema MCP-ova",
|
||||
"project.settings.extensions.empty.mcps.description": "MCP-ovi dostupni OpenCode-u pojavit će se ovdje",
|
||||
"project.settings.extensions.empty.plugins.title": "Još nema dodataka",
|
||||
"project.settings.extensions.empty.plugins.description": "Dodaci dostupni OpenCode-u pojavit će se ovdje",
|
||||
"project.settings.extensions.empty.skills.title": "Još nema vještina",
|
||||
"project.settings.extensions.empty.skills.description": "Vještine dostupne OpenCode-u pojavit će se ovdje",
|
||||
"project.settings.extensions.lsp.configured": "Konfigurirani jezički serveri",
|
||||
"project.settings.extensions.lsp.status.enabled": "Omogućeno u konfiguraciji",
|
||||
"project.settings.extensions.lsp.status.disabled": "Onemogućeno u konfiguraciji",
|
||||
"project.settings.extensions.lsp.empty.title": "Nema konfiguriranih jezičkih servera",
|
||||
"project.settings.extensions.lsp.empty.description":
|
||||
"Jezički serveri konfigurirani za ovaj projekat pojavit će se ovdje",
|
||||
"project.settings.extensions.lsp.disabled.title": "Jezički serveri su onemogućeni",
|
||||
"project.settings.extensions.lsp.disabled.description": "LSP je onemogućen u konfiguraciji ovog projekta",
|
||||
"project.settings.extensions.lsp.loadFailed": "Nije bilo moguće učitati konfiguraciju jezičkog servera",
|
||||
"project.settings.extensions.lsp.retry": "Pokušaj ponovo",
|
||||
"settings.timeline.summary": "{{preset}}:",
|
||||
"settings.timeline.group": "Grupiši",
|
||||
"settings.timeline.collapse": "Sažmi",
|
||||
"settings.timeline.visibility.show": "Prikaži",
|
||||
"settings.timeline.visibility.hide": "Sakrij",
|
||||
"settings.timeline.visibility.label": "Vidljivost aktivnosti {{activity}}",
|
||||
"settings.timeline.grouped.label": "Aktivnost {{activity}} je grupisana",
|
||||
"settings.timeline.collapsed.label": "Aktivnost {{activity}} je sažeta",
|
||||
"session.new.workspace.search.empty": "Nema odgovarajućih worktreeova",
|
||||
"settings.workspaces.description": "Pregledajte worktreeove i upravljajte korištenjem diska",
|
||||
"settings.workspaces.empty.description": "Worktreeovi kreirani u OpenCode-u pojavit će se ovdje",
|
||||
"settings.workspaces.sessions.filtered.one": "{{count}} sesija",
|
||||
"settings.workspaces.sessions.filtered.few": "{{count}} sesije",
|
||||
"settings.workspaces.sessions.filtered.other": "{{count}} sesija",
|
||||
"settings.workspaces.deleteAll.confirm.one": "Ovim ćete trajno izbrisati {{count}} odabrano radno stablo.",
|
||||
"settings.workspaces.deleteAll.confirm.few": "Ovim ćete trajno izbrisati {{count}} odabrana radna stabla.",
|
||||
"settings.workspaces.deleteAll.confirm.other": "Ovim ćete trajno izbrisati {{count}} odabranih radnih stabala.",
|
||||
"settings.workspaces.deleteWithoutSessions": "Izbriši worktreeove bez sesija",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"Ovim ćete trajno izbrisati {{count}} radno stablo bez povezanih sesija.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.few":
|
||||
"Ovim ćete trajno izbrisati {{count}} radna stabla bez povezanih sesija.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"Ovim ćete trajno izbrisati {{count}} radnih stabala bez povezanih sesija.",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"Worktreeovi s nespojenim promjenama ili aktivnim lokacijama bit će zadržani.",
|
||||
"settings.workspaces.delete.button": "Izbriši worktreeove",
|
||||
"workspace.lifecycle.deleting": "Brisanje…",
|
||||
"session.summary.tooltip": "Sažetak",
|
||||
"session.summary.server": "Proširenja",
|
||||
"session.summary.chooseProject": "Odaberite projekat",
|
||||
"session.summary.mcp.onCreation": "Primjenjuje se pri kreiranju worktreea",
|
||||
"session.summary.mcp.prepareFailed": "Nije bilo moguće pripremiti MCP servere",
|
||||
"session.summary.mcp.unavailable": "MCP server {{name}} nije dostupan u ovom worktreeu.",
|
||||
"session.summary.mcp.signInBeforeSend": "Prijavite se na {{name}} prije slanja upita.",
|
||||
"session.summary.mcp.notReady": "MCP server {{name}} nije spreman. Riješite njegovu vezu prije slanja upita.",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "Konfigurirani MCP serveri",
|
||||
"session.summary.plugins": "Dodaci",
|
||||
"session.summary.plugins.configured": "Konfigurirani dodaci",
|
||||
"session.summary.skills": "Vještine",
|
||||
"session.summary.skills.configured": "Konfigurirane vještine",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "Neuspješno",
|
||||
"session.summary.retry": "Pokušaj ponovo",
|
||||
"session.summary.connecting": "Povezivanje…",
|
||||
"session.summary.needsAuth": "Potrebna je prijava",
|
||||
"session.summary.configure": "Konfiguracijska datoteka",
|
||||
"session.summary.copyConfigPath": "Kopiraj putanju konfiguracijske datoteke",
|
||||
"session.summary.configFileMissing": "Konfiguracijska datoteka nije pronađena",
|
||||
"session.summary.mcp.empty": "Nema konfiguriranih MCP servera",
|
||||
"session.summary.mcp.add": "Dodajte servere u opencode.json",
|
||||
"session.summary.plugins.manage": "Upravljajte dodacima u opencode.json",
|
||||
"session.summary.plugins.empty": "Nema konfiguriranih dodataka",
|
||||
"session.summary.plugins.add": "Dodajte dodatke u opencode.json",
|
||||
"session.summary.skills.manage": "Upravljajte vještinama u opencode.json",
|
||||
"session.summary.skills.empty": "Nema konfiguriranih vještina",
|
||||
"session.summary.skills.add": "Dodajte vještine u opencode.json",
|
||||
"session.summary.lsp.configured": "Konfigurirani LSP-ovi",
|
||||
"session.summary.lsp.empty": "Nema konfiguriranih LSP servera",
|
||||
"session.summary.lsp.manage": "Upravljajte LSP-om u opencode.json",
|
||||
"workspace.delete.location": "Lokacija",
|
||||
"command.debugBar.toggle": "Uključi/isključi traku za otklanjanje grešaka",
|
||||
"command.session.location.cycle": "Promijeni lokaciju sesije",
|
||||
"dialog.provider.anthropic.note": "Direktan pristup Claude modelima putem API ključa",
|
||||
"provider.connect.title.anthropicProMax": "Prijava putem Anthropic-a",
|
||||
"prompt.toast.uploading.cancel": "Otkaži otpremanje",
|
||||
"prompt.toast.uploading.cancelFile": "Otkaži otpremanje datoteke {{filename}}",
|
||||
"prompt.toast.uploadFailed.title": "Otpremanje nije uspjelo",
|
||||
"session.browser.empty.title": "Unesite URL",
|
||||
"session.browser.empty.description": "Ili zadajte upit „Otvori u pregledniku aplikacije“",
|
||||
"session.browser.failed.title": "URL nije dostupan",
|
||||
"session.browser.failed.description": "Provjerite URL i vezu, a zatim pokušajte ponovo.",
|
||||
"debugBar.providerAriaLabel": "Dijagnostika performansi pružaoca usluge",
|
||||
"debugBar.ttft.tip": "Vrijeme od slanja zahtjeva pružaocu do prvog izlaza modela.",
|
||||
"debugBar.ttfa.tip": "Vrijeme od slanja zahtjeva pružaocu do prvog teksta odgovora.",
|
||||
"debugBar.tps.tip": "Izlazni tokeni u sekundi nakon prvog izlaza modela.",
|
||||
"debugBar.e2e.tip": "Vrijeme od slanja zahtjeva pružaocu do završetka toka odgovora.",
|
||||
"settings.updates.action.download": "Preuzmi OpenCode",
|
||||
"settings.updates.migration.title": "Prelazak sa Beta na Stable",
|
||||
"settings.updates.migration.description":
|
||||
"OpenCode Beta za sada prelazi na OpenCode Stable. Preuzmite verziju {{version}}, a zatim instalirajte OpenCode iz slike diska da biste nastavili primati ažuriranja.",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
}
|
||||
|
||||
@@ -1077,6 +1077,49 @@ export const dict = {
|
||||
"session.delete.confirm": 'Voleu suprimir la sessió "{{name}}"?',
|
||||
"session.delete.button": "Suprimeix la sessió",
|
||||
"workspace.new": "Nou espai de treball",
|
||||
"common.viewAll": "Mostra-ho tot",
|
||||
"session.new.workspace.local.tooltip": "Utilitza el checkout actual",
|
||||
"session.new.workspace.new.tooltip": "Crea un checkout aïllat",
|
||||
"session.new.workspace.fromBranch": "des de {{branch}}",
|
||||
"session.new.workspace.trigger.tooltip": "Selecciona on s'executarà la sessió",
|
||||
"session.new.workspace.search.placeholder": "Cerca espais de treball",
|
||||
"settings.tab.workspaces": "Espais de treball",
|
||||
"settings.workspaces.filter.all": "Tots els projectes",
|
||||
"settings.workspaces.empty": "No hi ha espais de treball",
|
||||
"settings.workspaces.count.one": "{{count}} espai de treball",
|
||||
"settings.workspaces.count.many": "{{count}} d'espais de treball",
|
||||
"settings.workspaces.count.other": "{{count}} espais de treball",
|
||||
"settings.workspaces.sessions.one": "{{count}} sessió a {{project}}",
|
||||
"settings.workspaces.sessions.many": "{{count}} de sessions a {{project}}",
|
||||
"settings.workspaces.sessions.other": "{{count}} sessions a {{project}}",
|
||||
"settings.workspaces.lastActiveSession": "Última sessió activa",
|
||||
"settings.workspaces.deleteAll": "Suprimeix tots els espais de treball",
|
||||
"settings.workspaces.delete.warning":
|
||||
"El directori i la branca de l'espai de treball se suprimiran permanentment, inclosos els canvis no fusionats que es mostren a continuació.",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"Els arbres de treball amb canvis no combinats, sessions enllaçades o ubicacions actives es mantindran.",
|
||||
"settings.workspaces.delete.blocked.active": "L'espai de treball actiu no es pot suprimir.",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"Les sessions enllaçades es conservaran, però el seu directori de treball se suprimirà permanentment.",
|
||||
"settings.workspaces.default.title": "Entorn predeterminat",
|
||||
"settings.workspaces.default.description": "Trieu on s'inicien les sessions noves",
|
||||
"settings.workspaces.default.lastUsed": "Últim utilitzat per projecte",
|
||||
"settings.workspaces.default.local": "Directori local",
|
||||
"settings.workspaces.default.new": "Espai de treball nou",
|
||||
"workspace.move.title": "Mou a un espai de treball",
|
||||
"workspace.move.menu.title": "Mou la sessió a",
|
||||
"workspace.move.failed": "No s'ha pogut moure la sessió",
|
||||
"workspace.lifecycle.creating": "S'està creant l'espai de treball",
|
||||
"workspace.lifecycle.created": "S'ha creat l'espai de treball",
|
||||
"workspace.lifecycle.starting": "S'està iniciant la sessió",
|
||||
"workspace.onboarding.title": "Aïlla les sessions amb espais de treball",
|
||||
"workspace.onboarding.description":
|
||||
"Cadascuna té el seu propi checkout, de manera que res no interfereix amb el repositori local",
|
||||
"workspace.lifecycle.moving": "S'està movent a l'espai de treball",
|
||||
"workspace.lifecycle.set": "Espai de treball establert",
|
||||
"session.summary.title": "Detalls de la sessió",
|
||||
"session.summary.noBranch": "Sense branca",
|
||||
"session.summary.basedOn": "Basat en {{branch}}",
|
||||
"workspace.type.local": "locals",
|
||||
"workspace.type.sandbox": "caixa de sorra",
|
||||
"workspace.create.failed.title": "No s'ha pogut crear l'espai de treball",
|
||||
@@ -1102,4 +1145,443 @@ export const dict = {
|
||||
"workspace.reset.archived.many": "{{count}} sessions s'arxivaran.",
|
||||
"workspace.reset.note": "Això restablirà l'espai de treball perquè coincideixi amb la branca predeterminada.",
|
||||
"dialog.usageExceeded.dontShowAgain": "No ho tornis a mostrar",
|
||||
"provider.disconnect.toast.noCredentials.description": "No s'han trobat credencials eliminables per a {{provider}}.",
|
||||
"provider.disconnect.toast.failed.description": "No s'ha pogut desconnectar {{provider}}.",
|
||||
"toast.migration.failed.title": "La migració de dades ha fallat",
|
||||
"command.session.background": "Mou al segon pla",
|
||||
"session.timeline.notice.finished": "{{actor}} ha acabat",
|
||||
"session.timeline.notice.failed": "{{actor}} ha fallat",
|
||||
"session.timeline.notice.cancelled": "{{actor}} s'ha cancel·lat",
|
||||
"settings.tab.preferences": "Preferències",
|
||||
"settings.tab.notifications": "Notificacions",
|
||||
"settings.tab.projects": "Projectes",
|
||||
"settings.tab.extensions": "Extensions",
|
||||
"settings.preferences.description": "Personalitzeu les preferències, el tema i el comportament predeterminat",
|
||||
"settings.appearance.description": "Personalitzeu el tema i els tipus de lletra",
|
||||
"settings.notifications.description": "Trieu quan voleu rebre notificacions i sentir sons",
|
||||
"settings.shortcuts.description": "Personalitzeu les dreceres per a les accions habituals",
|
||||
"settings.servers.description": "Gestioneu les connexions als servidors",
|
||||
"settings.projects.title": "Projectes",
|
||||
"settings.projects.description": "Gestioneu la configuració dels projectes d'aquest servidor",
|
||||
"settings.projects.empty": "No s'ha trobat cap projecte",
|
||||
"settings.projects.server.all": "Tots els servidors",
|
||||
"settings.mcps.description": "Gestioneu els servidors i les eines del Model Context Protocol (MCP)",
|
||||
"settings.extensions.description": "Gestioneu les extensions disponibles en aquest servidor",
|
||||
"settings.extensions.tab.mcps": "MCP",
|
||||
"settings.extensions.tab.skills": "Habilitats",
|
||||
"settings.extensions.availableAll": "Disponible per a tots els projectes",
|
||||
"settings.extensions.manageConfig": "Gestiona-ho a opencode.json",
|
||||
"settings.extensions.addSkills": "Com afegir habilitats",
|
||||
"dialog.server.authenticate.title": "Autentica",
|
||||
"project.settings.general.description": "Gestioneu el nom i l'aparença del projecte",
|
||||
"project.settings.scripts": "Scripts",
|
||||
"project.settings.scripts.description": "Configureu els scripts d'aquest projecte",
|
||||
"project.settings.extensions.description": "Consulteu les extensions disponibles per a aquest projecte",
|
||||
"project.settings.extensions.tab.lsps": "LSP",
|
||||
"project.settings.extensions.added": "Afegit a aquest projecte",
|
||||
"project.settings.extensions.shared": "Compartit amb tots els projectes",
|
||||
"project.settings.extensions.lsp.detected": "Servidors de llenguatge detectats",
|
||||
"project.settings.extensions.lsp.description": "Detectats automàticament segons els tipus de fitxer",
|
||||
"project.settings.extensions.setupRequired": "Cal configurar-ho",
|
||||
"settings.general.section.general": "General",
|
||||
"desktop.menu.installCli": "Instal·la la CLI...",
|
||||
"desktop.cli.installed.title": "CLI instal·lada",
|
||||
"desktop.cli.installed.message":
|
||||
"La CLI s'ha instal·lat a {{path}}\n\nReinicieu el terminal per utilitzar l'ordre 'opencode2'.",
|
||||
"desktop.cli.failed.title": "La instal·lació ha fallat",
|
||||
"desktop.cli.failed.message": "No s'ha pogut instal·lar la CLI: {{error}}",
|
||||
"command.project.copyID": "Copia l'ID del projecte",
|
||||
"command.session.copyID": "Copia l'ID de la sessió",
|
||||
"server.row.incompatible":
|
||||
"Aquest servidor executa OpenCode {{version}}, que no és compatible amb aquesta aplicació. Actualitzeu-lo a OpenCode V2 per continuar.",
|
||||
"toast.session.copyID.failed.title": "No s'ha pogut copiar l'ID de la sessió",
|
||||
"toast.session.copyID.failed.description": "S'ha produït un error en copiar l'ID de la sessió",
|
||||
"toast.project.copyID.failed.title": "No s'ha pogut copiar l'ID del projecte",
|
||||
"toast.project.copyID.failed.description": "S'ha produït un error en copiar l'ID del projecte",
|
||||
"error.page.title.status": "La sol·licitud al servidor ha fallat",
|
||||
"error.page.description.status": "El servidor ha retornat una resposta HTTP {{status}}.",
|
||||
"error.page.action.reload": "Torna a carregar",
|
||||
"session.error.incompatible": "Aquesta versió del servidor no és compatible",
|
||||
"session.error.incompatible.description":
|
||||
"{{server}} executa OpenCode {{version}}, que no és compatible amb aquesta aplicació. Actualitzeu el servidor a OpenCode V2 per continuar.",
|
||||
"session.background.moveInline": "Premeu {{keybind}} per moure la feina en curs al segon pla",
|
||||
"session.background.running": "Hi ha feina en curs en segon pla",
|
||||
"session.background.runningCount.one": "{{count}} element en curs en segon pla",
|
||||
"session.background.runningCount.many": "{{count}} d'elements en curs en segon pla",
|
||||
"session.background.runningCount.other": "{{count}} elements en curs en segon pla",
|
||||
"settings.general.row.terminalPlacement.title": "Ubicació del terminal",
|
||||
"settings.general.row.terminalPlacement.description": "Trieu on s'obre el terminal a les sessions",
|
||||
"settings.general.row.terminalPlacement.side": "Al costat",
|
||||
"settings.general.row.terminalPlacement.bottom": "A baix",
|
||||
"session.location.unavailable": "La ubicació de la sessió no està disponible",
|
||||
"session.location.description": "Trieu un altre directori per continuar aquesta sessió.",
|
||||
"session.location.choose": "Tria un directori",
|
||||
"session.location.worktree": "Tria un arbre de treball",
|
||||
"session.location.worktreesFailed": "No s'han pogut carregar els arbres de treball",
|
||||
"session.location.moving": "S'està movent la sessió…",
|
||||
"dialog.server.menu.hide": "Amaga de la llista de projectes",
|
||||
"dialog.server.menu.show": "Mostra a la llista de projectes",
|
||||
"session.queue.count.one": "{{count}} a la cua",
|
||||
"session.queue.count.many": "{{count}} a la cua",
|
||||
"session.queue.count.other": "{{count}} a la cua",
|
||||
"session.queue.steer": "Redirigeix",
|
||||
"session.queue.send": "Envia",
|
||||
"session.queue.steerTooltip": "Envia sense interrompre",
|
||||
"session.queue.remove": "Elimina",
|
||||
"session.queue.reorder": "Reordena la indicació en cua",
|
||||
"session.new.worktree.creating": "S'està creant l'arbre de treball",
|
||||
"settings.backToApp": "Torna a l'aplicació",
|
||||
"settings.appearance.section.experimental": "Experimental",
|
||||
"settings.appearance.row.tabs.title": "Pestanyes",
|
||||
"settings.appearance.row.tabs.description": "Trieu com s'organitzen les pestanyes de sessió",
|
||||
"settings.appearance.row.tabs.horizontal": "Horitzontals",
|
||||
"settings.appearance.row.tabs.vertical": "Verticals",
|
||||
"settings.general.row.followUpBehavior.title": "Comportament dels seguiments",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"Trieu si voleu posar els seguiments a la cua o redirigir el torn actual. Feu servir {{keybind}} per canviar.",
|
||||
"settings.general.row.followUpBehavior.queue": "Posa a la cua",
|
||||
"settings.general.row.followUpBehavior.steer": "Redirigeix",
|
||||
"settings.general.row.reasoningMode.title": "Raonament del model",
|
||||
"settings.general.row.reasoningMode.description": "Trieu com es mostra el raonament del model a la cronologia",
|
||||
"settings.general.row.reasoningMode.hidden": "Ocult",
|
||||
"settings.general.row.reasoningMode.compact": "Compacte",
|
||||
"settings.general.row.reasoningMode.full": "Complet",
|
||||
"session.new.workspace.createFrom": "Crea a partir d'una branca",
|
||||
"session.new.workspace.branch.search.placeholder": "Cerca branques",
|
||||
"session.review.change.many": "Canvis",
|
||||
"toast.migration.progress.clearingOldEvents": "Es netegen els esdeveniments antics",
|
||||
"toast.migration.progress.migratingSessions": "S'estan migrant les sessions",
|
||||
"session.new.workspace.existingLabel": "Arbre de treball",
|
||||
"desktop.onboarding.defaultProject": "Projecte predeterminat",
|
||||
"home.projects.all": "Tots els projectes",
|
||||
"session.tab.files": "Fitxers",
|
||||
"session.files.openTabs": "Obre els fitxers",
|
||||
"session.tab.usage": "Ús",
|
||||
"session.view.select": "Visualització de sessió",
|
||||
"session.background.moveTasks": "Mou {{tasks}} al fons",
|
||||
"session.background.moveRunning": "Vés al fons",
|
||||
"session.background.inBackground": "S'està executant {{tasks}} en segon pla",
|
||||
"session.background.tasksRunning.one": "Tarea de fons {{count}} en execució",
|
||||
"session.background.tasksRunning.other": "S'estan executant les tasques de fons {{count}}",
|
||||
"session.background.combine": "{{first}} i {{second}}",
|
||||
"session.background.shell.one": "Shell {{count}}",
|
||||
"session.background.shell.other": "Shell {{count}}",
|
||||
"session.background.subagent.one": "{{count}} subagent",
|
||||
"session.background.subagent.other": "{{count}} subagents",
|
||||
"session.timeline.working": "Treballant",
|
||||
"session.review.wrapLines": "Ajusta les línies",
|
||||
"session.websearch.title": "Cerca web de tercers",
|
||||
"session.websearch.description": "Selecciona els agents proveïdors de cerca que utilitzen per cercar al web",
|
||||
"session.websearch.provider": "Proveïdor de cerca",
|
||||
"session.websearch.any": "Qualsevol",
|
||||
"session.websearch.disable": "No facis servir la cerca",
|
||||
"session.websearch.enable": "Habilita",
|
||||
"session.websearch.loadFailed": "No s'han pogut carregar els proveïdors de cerca",
|
||||
"session.websearch.empty": "No hi ha proveïdors de cerca disponibles.",
|
||||
"session.websearch.failed": "No s'ha pogut desar l'elecció. Torna-ho a provar.",
|
||||
"session.websearch.retry": "Torna-ho a provar",
|
||||
"session.new.worktree.draftPlaceholder": "Redacta un seguiment mentre s'està preparant l'arbre de treball…",
|
||||
"session.search.placeholder": "Cerca…",
|
||||
"session.search.noResults": "No hi ha coincidències",
|
||||
"titlebar.tabs": "Pestanyes",
|
||||
"titlebar.channel.local": "Local",
|
||||
"titlebar.channel.dev": "Dev",
|
||||
"titlebar.channel.beta": "Beta",
|
||||
"titlebar.toggleDebugTools": "Commuta les eines de depuració",
|
||||
"settings.tab.experimental": "Experimental",
|
||||
"settings.experimental.description": "Prova les funcions experimentals",
|
||||
"settings.tab.about": "Quant a",
|
||||
"settings.about.version": "Versió {{version}}",
|
||||
"settings.about.devVersion": "desenvolupament",
|
||||
"settings.about.license": "Publicat sota la llicència del MIT",
|
||||
"settings.about.writtenBy": "Escrit per",
|
||||
"settings.about.illustratedBy": "Il·lustrat per",
|
||||
"settings.about.and": "i",
|
||||
"settings.about.otherContributor.one": "{{count}} altre",
|
||||
"settings.about.otherContributor.other": "{{count}} altres",
|
||||
"settings.about.firstPublished": "Publicat per primera vegada a Missouri, EUA",
|
||||
"settings.about.firstIllustrated": "Il·lustrat per primera vegada a Londres, Anglaterra",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode, l'agent de codificació de codi obert",
|
||||
"settings.about.trademark": "OpenCode és una marca registrada de Anomaly Innovations, Inc.",
|
||||
"settings.about.typeset": "Tipografia en Inter i IBM Plex Mono",
|
||||
"settings.about.tagline": "La IA no pot crear un gran programari sense tu",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "Modifica el projecte",
|
||||
"settings.timeline.title": "Cronologia",
|
||||
"settings.timeline.detail": "Detall de la cronologia",
|
||||
"settings.timeline.description":
|
||||
"Tria quanta activitat apareix a la línia de temps. Els missatges es mantenen visibles.",
|
||||
"settings.timeline.preset.everything": "Tot",
|
||||
"settings.timeline.preset.detailed": "Detallat",
|
||||
"settings.timeline.preset.compact": "Compacte",
|
||||
"settings.timeline.preset.quiet": "Tranquil·la",
|
||||
"settings.timeline.preset.text-only": "Només text",
|
||||
"settings.timeline.description.everything":
|
||||
"Mostra totes les activitats per separat. Amplia la sortida de l'intèrpret d'ordres, les edicions i el pensament.",
|
||||
"settings.timeline.description.detailed":
|
||||
"Expandeix la sortida i les edicions de l'shell. Mostra els subagents per separat i agrupa altres activitats a Usat.",
|
||||
"settings.timeline.description.compact": "Agrupa tota l'activitat a Usat amb els detalls col·lapsats.",
|
||||
"settings.timeline.description.quiet": "Edicions de grup i subagents a Usat. Amaga una altra activitat.",
|
||||
"settings.timeline.description.text-only": "Amaga tota l'activitat. Mostra només els missatges.",
|
||||
"settings.timeline.description.custom":
|
||||
"Utilitza la ubicació i les dades seleccionades per a cada categoria d'activitat.",
|
||||
"settings.timeline.custom": "Personalitzat",
|
||||
"settings.timeline.advanced": "Avançat",
|
||||
"settings.timeline.advanced.description": "Estableix la ubicació i els detalls per a cada categoria d'activitat.",
|
||||
"settings.timeline.category.shell": "Shell",
|
||||
"settings.timeline.category.edit": "Modifica",
|
||||
"settings.timeline.category.thinking": "Pensament",
|
||||
"settings.timeline.category.subagents": "Subagents",
|
||||
"settings.timeline.category.notices": "Avisos",
|
||||
"settings.timeline.category.tools": "Altres eines",
|
||||
"settings.general.row.mobileDiffWrap.description":
|
||||
"Ajustar les línies llargues en diffs mòbils en lloc de desplaçar-se horitzontalment",
|
||||
|
||||
"session.background.tasksRunning.many": "S'estan executant {{count}} tasques en segon pla",
|
||||
"session.background.shell.many": "{{count}} shells",
|
||||
"session.background.subagent.many": "{{count}} subagents",
|
||||
"settings.about.otherContributor.many": "{{count}} altres",
|
||||
"provider.connect.error.unsupportedFields": "Aquest formulari d'autenticació conté camps no admesos",
|
||||
"session.review.filesChangedCount.one": "{{count}} fitxer ha canviat",
|
||||
"session.review.filesChangedCount.other": "S'han canviat {{count}} fitxers",
|
||||
"settings.about.writtenByNames": "Escrit per {{names}}",
|
||||
"settings.about.illustratedByNames": "Il·lustrat per {{names}}",
|
||||
"session.review.filesChangedCount.many": "{{count}} fitxers han canviat",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline": "No connectat a {{host}}. El vostre esborrany es conserva; el treball remot encara s'està executant.",
|
||||
"ssh.placeholder": "ssh usuari@exemple.com",
|
||||
"ssh.add": "Afegeix el servidor SSH",
|
||||
"ssh.server.menu.label": "Servidor SSH",
|
||||
"ssh.target": "Amfitrió o comanda SSH",
|
||||
"ssh.connect": "Connecta",
|
||||
"ssh.connectTo": "Connecteu-vos a {{host}}",
|
||||
"ssh.authenticate": "Autenticació SSH",
|
||||
"ssh.action.authenticate": "Autenticar",
|
||||
"ssh.session.disconnected": "Connexió SSH inactiva",
|
||||
"ssh.session.connecting": "S'està connectant al servidor SSH",
|
||||
"ssh.session.reconnectDescription":
|
||||
"Torneu a connectar-vos per veure aquesta sessió i continuar treballant. La vostra sessió remota es conserva.",
|
||||
"ssh.session.reconnect": "Torna a connectar",
|
||||
"ssh.authenticationRequired": "Cal autenticació per a {{host}}",
|
||||
"ssh.trust": "Confia i connecta",
|
||||
"ssh.continue": "Continuar",
|
||||
"ssh.retry": "Torna-ho a provar",
|
||||
"ssh.update": "Actualitza i torna a connectar",
|
||||
"ssh.openProject": "Projecte obert",
|
||||
"ssh.project": "Projecte obert a {{host}}",
|
||||
"ssh.disconnect": "Desconnectar",
|
||||
"ssh.forget": "Oblida la connexió",
|
||||
"ssh.stage.disconnected": "Desconnectat. El servidor remot es deixa en funcionament.",
|
||||
"ssh.stage.connecting": "S'està connectant a través de SSH…",
|
||||
"ssh.stage.checking": "S'està comprovant OpenCode…",
|
||||
"ssh.stage.downloading": "S'està baixant el servidor…",
|
||||
"ssh.stage.uploading": "S'està carregant el servidor…",
|
||||
"ssh.stage.starting": "S'està connectant a OpenCode…",
|
||||
"ssh.stage.ready": "Connectat",
|
||||
"ssh.stage.authentication": "Cal autenticació",
|
||||
"ssh.stage.incompatible": "Cal actualitzar el servidor",
|
||||
"ssh.stage.failed": "La connexió ha fallat",
|
||||
"ssh.error.input":
|
||||
"Introduïu un host o una ordre de connexió SSH. Les ordres remotes i les opcions SSH no admeses no es permeten.",
|
||||
"ssh.error.connection": "No s'ha pogut establir la connexió SSH. Comproveu la vostra xarxa i la configuració de SSH.",
|
||||
"ssh.error.platform":
|
||||
"Aquesta plataforma remota no és compatible. Actualment, la configuració automàtica requereix Linux o macOS a x64 o arm64.",
|
||||
"ssh.error.version": "El servei remot ha de coincidir amb aquesta versió d'escriptori abans de connectar-se.",
|
||||
"ssh.error.install":
|
||||
"No s'ha pogut instal·lar el servidor remot. Comproveu la connectivitat, l'espai en disc i que el tar està instal·lat.",
|
||||
"ssh.error.unpublished":
|
||||
"Aquesta versió d'escriptori no té cap servidor remot publicat. Per a les compilacions de desenvolupament, instal·leu i inicieu la V2 a l'amfitrió i, a continuació, torneu-ho a provar.",
|
||||
"ssh.error.service": "SSH s'ha connectat, però el servidor OpenCode no està preparat.",
|
||||
"ssh.error.host-key":
|
||||
"No s'ha pogut verificar la identitat de l'amfitrió. Verifiqueu la seva empremta digital abans d'actualitzar els vostres amfitrions coneguts SSH.",
|
||||
"ssh.error.ssh-missing":
|
||||
"No s'ha trobat OpenSSH. Instal·leu un client OpenSSH i assegureu-vos que ssh estigui disponible a PATH.",
|
||||
"command.browser.open": "Obre el navegador",
|
||||
"command.browser.reload": "Torna a carregar la pàgina del navegador",
|
||||
"command.session.summary.toggle": "Commuta el resum",
|
||||
"mcp.auth.interactiveForm": "El servidor MCP {{name}} requereix un formulari d'autenticació interactiu",
|
||||
"server.connect.title": "Connecta't a un servidor",
|
||||
"server.connect.description": "Introduïu l'adreça del servidor i la contrasenya per començar.",
|
||||
"server.connect.button": "Connecta",
|
||||
"server.connect.address.invalid": "Introduïu una adreça de servidor HTTP o HTTPS vàlida.",
|
||||
"server.connect.failed":
|
||||
"No s'ha pogut connectar. Comproveu l'adreça i la contrasenya del servidor i torneu-ho a provar.",
|
||||
"server.connect.pair.description":
|
||||
"Executeu aquesta ordre al vostre ordinador per obtenir els detalls de la vostra connexió.",
|
||||
"server.connect.scan": "Escaneja el codi QR",
|
||||
"server.connect.scan.description": "Apunteu la càmera al codi QR que mostra opencode pair.",
|
||||
"server.connect.scan.invalid":
|
||||
"Aquest no és un codi d'aparellament OpenCode. Escaneja el codi mostrat per opencode pair.",
|
||||
"server.connect.camera": "Càmera d'aparellament",
|
||||
"server.connect.camera.starting": "Obertura de la càmera...",
|
||||
"server.connect.mixedContent":
|
||||
"No s'ha pogut connectar a aquest servidor HTTP des d'una pàgina HTTPS. Utilitzeu una adreça de servidor HTTPS.",
|
||||
"server.connect.camera.insecure": "L'exploració de QR requereix obrir aquesta pàgina a HTTPS o a localhost.",
|
||||
"server.connect.camera.unavailable":
|
||||
"No hi ha cap càmera disponible per a aquest navegador. Introduïu els detalls de connexió manualment.",
|
||||
"server.connect.camera.error":
|
||||
"No s'ha pogut obrir la càmera. Permet l'accés a la càmera o introdueix els detalls de connexió manualment.",
|
||||
"dialog.server.menu.remove": "Elimina",
|
||||
"file.error.notFound": "No s'ha trobat el fitxer: {{name}}",
|
||||
"home.workspaceTip": "Inicieu la propera sessió en un nou espai de treball per mantenir els canvis aïllats",
|
||||
"session.tab.browser": "Navegador",
|
||||
"session.tab.add": "Afegeix una pestanya",
|
||||
"session.queue.attachments.one": "Més adjunt {{count}}",
|
||||
"session.queue.attachments.other": "Més fitxers adjunts {{count}}",
|
||||
"session.browser.address": "Adreça del navegador",
|
||||
"session.browser.replaced": "El control del navegador s'ha mogut a una altra finestra d'escriptori.",
|
||||
"session.browser.suspended": "Navegador suspès. Interacciona amb aquesta sessió per tornar a connectar.",
|
||||
"session.browser.address.placeholder": "Introduïu l'URL",
|
||||
"settings.backToSettings": "Tornar a la configuració",
|
||||
"settings.backToProjects": "Tornar als projectes",
|
||||
"settings.search.placeholder": "Cerca",
|
||||
"settings.search.results": "Resultats de la configuració",
|
||||
"settings.search.group.pages": "Pàgines",
|
||||
"settings.search.group.settings": "Configuració",
|
||||
"settings.search.group.projects": "Projectes",
|
||||
"settings.search.group.servers": "Servidors",
|
||||
"settings.search.result": "{{title}}, {{scope}}, {{page}}",
|
||||
"settings.search.page": "{{title}}, {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}, {{page}}",
|
||||
"settings.search.empty": "No hi ha resultats per a {{query}}",
|
||||
"settings.search.empty.query": '"{{query}}"',
|
||||
"settings.search.refine": "Limiteu la cerca per veure resultats més específics.",
|
||||
"settings.server.description": "Gestioneu la connexió i les preferències d'aquest servidor",
|
||||
"settings.server.section.connection": "Connexió",
|
||||
"settings.server.preferences.websearch.title": "Cerca de tercers",
|
||||
"settings.server.preferences.websearch.description":
|
||||
"Seleccioneu el proveïdor de cerca que utilitzen els agents per cercar al web",
|
||||
"settings.projects.search.placeholder": "Cerca projectes",
|
||||
"project.settings.name.title": "Nom del projecte",
|
||||
"project.settings.name.description": "El nom mostrat per a aquest projecte a tot OpenCode",
|
||||
"project.settings.icon.description": "Recomanat: 128×128px. Feu clic o arrossegueu per pujar una imatge.",
|
||||
"project.settings.color.description":
|
||||
"S'utilitza per a la icona del projecte quan no s'ha establert cap imatge personalitzada",
|
||||
"project.settings.worktree.startup.description": "S'executa una vegada després de crear un nou arbre de treball",
|
||||
"project.settings.worktree.startup.hint.base": "Utilitzeu $OPENCODE_WORKTREE_BASE per a l'arbre de treball base.",
|
||||
"project.settings.worktree.startup.hint.new": "Utilitzeu $OPENCODE_WORKTREE_PATH per al nou arbre de treball.",
|
||||
"project.settings.extensions.empty.mcps.title": "Encara no MCPs",
|
||||
"project.settings.extensions.empty.mcps.description": "MCPs disponible per a OpenCode apareixerà aquí",
|
||||
"project.settings.extensions.empty.plugins.title": "Encara no hi ha connectors",
|
||||
"project.settings.extensions.empty.plugins.description": "Els connectors disponibles per a OpenCode apareixeran aquí",
|
||||
"project.settings.extensions.empty.skills.title": "Encara no hi ha habilitats",
|
||||
"project.settings.extensions.empty.skills.description": "Les habilitats disponibles per a OpenCode apareixeran aquí",
|
||||
"project.settings.extensions.lsp.configured": "Servidors d'idiomes configurats",
|
||||
"project.settings.extensions.lsp.status.enabled": "Habilitat a la configuració",
|
||||
"project.settings.extensions.lsp.status.disabled": "Desactivat a la configuració",
|
||||
"project.settings.extensions.lsp.empty.title": "No s'ha configurat cap servidor d'idiomes",
|
||||
"project.settings.extensions.lsp.empty.description":
|
||||
"Els servidors d'idiomes configurats per a aquest projecte apareixeran aquí",
|
||||
"project.settings.extensions.lsp.disabled.title": "Servidors d'idiomes desactivats",
|
||||
"project.settings.extensions.lsp.disabled.description": "LSP està desactivat a la configuració d'aquest projecte",
|
||||
"project.settings.extensions.lsp.loadFailed": "No s'ha pogut carregar la configuració del servidor d'idiomes",
|
||||
"project.settings.extensions.lsp.retry": "Torna-ho a provar",
|
||||
"settings.timeline.summary": "{{preset}}:",
|
||||
"settings.timeline.group": "Grup",
|
||||
"settings.timeline.collapse": "Col·lapse",
|
||||
"settings.timeline.visibility.show": "Mostra",
|
||||
"settings.timeline.visibility.hide": "Amaga",
|
||||
"settings.timeline.visibility.label": "{{activity}} visibilitat",
|
||||
"settings.timeline.grouped.label": "{{activity}} agrupat",
|
||||
"settings.timeline.collapsed.label": "{{activity}} col·lapsat",
|
||||
"session.new.workspace.search.empty": "No hi ha arbres de treball coincidents",
|
||||
"settings.workspaces.description": "Reviseu els arbres de treball i gestioneu l'ús del disc",
|
||||
"settings.workspaces.empty.description": "Els arbres de treball creats a OpenCode apareixeran aquí",
|
||||
"settings.workspaces.sessions.filtered.one": "Sessió {{count}}",
|
||||
"settings.workspaces.sessions.filtered.other": "{{count}} sessions",
|
||||
"settings.workspaces.deleteAll.confirm.one":
|
||||
"Això suprimirà permanentment l'arbre de treball seleccionat de {{count}}.",
|
||||
"settings.workspaces.deleteAll.confirm.other":
|
||||
"Això suprimirà permanentment els arbres de treball seleccionats de {{count}}.",
|
||||
"settings.workspaces.deleteWithoutSessions": "Suprimeix els arbres de treball sense sessions",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"Això suprimirà permanentment l'arbre de treball {{count}} sense sessions enllaçades.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"Això suprimirà permanentment els arbres de treball {{count}} sense sessions enllaçades.",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"Es mantindran els arbres de treball amb canvis no combinats o ubicacions actives.",
|
||||
"settings.workspaces.delete.button": "Suprimeix els arbres de treball",
|
||||
"workspace.lifecycle.deleting": "S'està suprimint…",
|
||||
"session.summary.tooltip": "Resum",
|
||||
"session.summary.server": "Extensions",
|
||||
"session.summary.chooseProject": "Trieu un projecte",
|
||||
"session.summary.mcp.onCreation": "S'aplica quan es crea l'arbre de treball",
|
||||
"session.summary.mcp.prepareFailed": "No s'han pogut preparar els servidors MCP",
|
||||
"session.summary.mcp.unavailable": "El servidor MCP {{name}} no està disponible en aquest arbre de treball.",
|
||||
"session.summary.mcp.signInBeforeSend": "Inicieu la sessió a {{name}} abans d'enviar la sol·licitud.",
|
||||
"session.summary.mcp.notReady":
|
||||
"El servidor MCP {{name}} no està preparat. Resol la seva connexió abans d'enviar la sol·licitud.",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "Servidors MCP configurats",
|
||||
"session.summary.plugins": "Connectors",
|
||||
"session.summary.plugins.configured": "Connectors configurats",
|
||||
"session.summary.skills": "Habilitats",
|
||||
"session.summary.skills.configured": "Habilitats configurades",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "Ha fallat",
|
||||
"session.summary.retry": "Torna-ho a provar",
|
||||
"session.summary.connecting": "S'està connectant…",
|
||||
"session.summary.needsAuth": "Cal iniciar sessió",
|
||||
"session.summary.configure": "Fitxer de configuració",
|
||||
"session.summary.copyConfigPath": "Copia el camí del fitxer de configuració",
|
||||
"session.summary.configFileMissing": "No s'ha trobat cap fitxer de configuració",
|
||||
"session.summary.mcp.empty": "No s'ha configurat cap servidor MCP",
|
||||
"session.summary.mcp.add": "Afegiu servidors a opencode.json",
|
||||
"session.summary.plugins.manage": "Gestioneu els connectors a opencode.json",
|
||||
"session.summary.plugins.empty": "No s'ha configurat cap connector",
|
||||
"session.summary.plugins.add": "Afegiu connectors a opencode.json",
|
||||
"session.summary.skills.manage": "Gestioneu les habilitats a opencode.json",
|
||||
"session.summary.skills.empty": "No s'ha configurat cap habilitat",
|
||||
"session.summary.skills.add": "Afegiu habilitats a opencode.json",
|
||||
"session.summary.lsp.configured": "LSPs configurat",
|
||||
"session.summary.lsp.empty": "No s'ha configurat cap servidor LSP",
|
||||
"session.summary.lsp.manage": "Gestioneu LSP a opencode.json",
|
||||
"workspace.delete.location": "Ubicació",
|
||||
"session.queue.attachments.many": "Més fitxers adjunts {{count}}",
|
||||
"settings.workspaces.sessions.filtered.many": "{{count}} sessions",
|
||||
"settings.workspaces.deleteAll.confirm.many":
|
||||
"Això suprimirà permanentment els arbres de treball seleccionats de {{count}}.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.many":
|
||||
"Això suprimirà permanentment els arbres de treball {{count}} sense sessions enllaçades.",
|
||||
"common.color.orange": "taronja",
|
||||
"common.color.yellow": "groc",
|
||||
"common.color.cyan": "cian",
|
||||
"common.color.green": "verd",
|
||||
"common.color.red": "vermell",
|
||||
"common.color.pink": "rosa",
|
||||
"common.color.blue": "blau",
|
||||
"common.color.purple": "violeta",
|
||||
"common.color.gray": "gris",
|
||||
"toast.migration.progress.migratingSessions.current": "Sessions de migració {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "Migració de sessions {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "Migració de dades",
|
||||
"toast.migration.progress.working.current": "Migració de dades {{current}}",
|
||||
"toast.migration.progress.working.progress": "S'estan migrant dades {{current}}/{{total}}",
|
||||
"session.browser.unsupported": "Aquesta aplicació d'escriptori no admet el panell del navegador.",
|
||||
"command.debugBar.toggle": "Commuta la barra de depuració",
|
||||
"command.session.location.cycle": "Canvia la ubicació de la sessió",
|
||||
"dialog.provider.anthropic.note": "Accés directe als models Claude mitjançant una clau d’API",
|
||||
"provider.connect.title.anthropicProMax": "Inicia la sessió amb Anthropic",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"prompt.toast.uploading.cancel": "Cancel·la la pujada",
|
||||
"prompt.toast.uploading.cancelFile": "Cancel·la la pujada de {{filename}}",
|
||||
"prompt.toast.uploadFailed.title": "Ha fallat la pujada",
|
||||
"session.browser.empty.title": "Introduïu l’URL",
|
||||
"session.browser.empty.description": "O demaneu «Obre al navegador de l’aplicació»",
|
||||
"session.browser.failed.title": "No es pot accedir a l’URL",
|
||||
"session.browser.failed.description": "Comproveu l’URL i la connexió i torneu-ho a provar.",
|
||||
"debugBar.providerAriaLabel": "Diagnòstic del rendiment del proveïdor",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttft.tip": "Temps des de l’enviament de la sol·licitud al proveïdor fins a la primera sortida del model.",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.ttfa.tip": "Temps des de l’enviament de la sol·licitud al proveïdor fins al primer text de resposta.",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.tps.tip": "Fitxes de sortida per segon després de la primera sortida del model.",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
"debugBar.e2e.tip": "Temps des de l’enviament de la sol·licitud al proveïdor fins que finalitza el flux de resposta.",
|
||||
"settings.updates.action.download": "Baixa l’OpenCode",
|
||||
"settings.updates.migration.title": "Passa de Beta a Estable",
|
||||
"settings.updates.migration.description":
|
||||
"De moment, OpenCode Beta passa a OpenCode Estable. Baixeu la versió {{version}} i instal·leu l’OpenCode des de la imatge de disc per continuar rebent actualitzacions.",
|
||||
}
|
||||
|
||||
@@ -1094,4 +1094,490 @@ export const dict = {
|
||||
"workspace.reset.archived.many": "{{count}} relací bude archivováno.",
|
||||
"workspace.reset.note": "Tím se pracovní prostor resetuje tak, aby odpovídal výchozí větvi.",
|
||||
"dialog.usageExceeded.dontShowAgain": "Znovu nezobrazovat",
|
||||
"provider.disconnect.toast.noCredentials.description":
|
||||
"Pro {{provider}} nebyly nalezeny žádné vyměnitelné přihlašovací údaje.",
|
||||
"provider.disconnect.toast.failed.description": "Odpojení {{provider}} se nezdařilo.",
|
||||
"toast.migration.failed.title": "Migrace dat se nezdařila",
|
||||
"command.session.background": "Přesuňte se na pozadí",
|
||||
"session.timeline.notice.finished": "{{actor}} dokončeno",
|
||||
"session.timeline.notice.failed": "{{actor}} se nezdařilo",
|
||||
"session.timeline.notice.cancelled": "{{actor}} zrušeno",
|
||||
"settings.tab.preferences": "Předvolby",
|
||||
"settings.tab.notifications": "Oznámení",
|
||||
"settings.tab.projects": "Projekty",
|
||||
"settings.tab.extensions": "Rozšíření",
|
||||
"settings.preferences.description": "Přizpůsobte předvolby a motiv a výchozí chování",
|
||||
"settings.appearance.description": "Přizpůsobte si motiv a písma",
|
||||
"settings.notifications.description": "Vyberte, kdy chcete dostávat oznámení a slyšet zvuky",
|
||||
"settings.shortcuts.description": "Přizpůsobte si zkratky pro běžné akce",
|
||||
"settings.servers.description": "Správa připojení k serveru",
|
||||
"settings.projects.title": "Projekty",
|
||||
"settings.projects.description": "Spravujte nastavení projektu na tomto serveru",
|
||||
"settings.projects.empty": "Nebyly nalezeny žádné projekty",
|
||||
"settings.projects.server.all": "Všechny servery",
|
||||
"settings.mcps.description": "Správa serverů a nástrojů Model Context Protocol (MCP).",
|
||||
"settings.extensions.description": "Spravujte rozšíření dostupná na tomto serveru",
|
||||
"settings.extensions.tab.mcps": "MCP",
|
||||
"settings.extensions.tab.skills": "Dovednosti",
|
||||
"settings.extensions.availableAll": "Dostupné pro všechny projekty",
|
||||
"settings.extensions.manageConfig": "Spravujte v opencode.json",
|
||||
"settings.extensions.addSkills": "Jak přidat dovednosti",
|
||||
"dialog.server.authenticate.title": "Ověřit",
|
||||
"project.settings.general.description": "Spravujte název a vzhled projektu",
|
||||
"project.settings.scripts": "Skripty",
|
||||
"project.settings.scripts.description": "Nakonfigurujte skripty pro tento projekt",
|
||||
"project.settings.extensions.description": "Zobrazit rozšíření dostupná pro tento projekt",
|
||||
"project.settings.extensions.tab.lsps": "LSP",
|
||||
"project.settings.extensions.added": "Přidáno do tohoto projektu",
|
||||
"project.settings.extensions.shared": "Sdíleno se všemi projekty",
|
||||
"project.settings.extensions.lsp.detected": "Zjištěné jazykové servery",
|
||||
"project.settings.extensions.lsp.description": "Automaticky zjištěno z typů souborů",
|
||||
"project.settings.extensions.setupRequired": "Je vyžadováno nastavení",
|
||||
"settings.general.section.general": "Obecné",
|
||||
"common.viewAll": "Zobrazit vše",
|
||||
"session.new.workspace.local.tooltip": "Použít aktuální pracovní kopii",
|
||||
"session.new.workspace.new.tooltip": "Vytvořit izolovanou pracovní kopii",
|
||||
"session.new.workspace.fromBranch": "od {{branch}}",
|
||||
"session.new.workspace.trigger.tooltip": "Vyberte, kde chcete relaci spustit",
|
||||
"session.new.workspace.search.placeholder": "Prohledejte pracovní prostory",
|
||||
"settings.tab.workspaces": "Pracovní prostory",
|
||||
"settings.workspaces.filter.all": "Všechny projekty",
|
||||
"settings.workspaces.empty": "Žádné pracovní prostory",
|
||||
"settings.workspaces.count.one": "Pracovní plocha {{count}}",
|
||||
"settings.workspaces.count.other": "Pracovní prostory {{count}}",
|
||||
"settings.workspaces.sessions.one": "Relace {{count}} v {{project}}",
|
||||
"settings.workspaces.sessions.other": "Relace {{count}} v {{project}}",
|
||||
"settings.workspaces.lastActiveSession": "Poslední aktivní relace",
|
||||
"settings.workspaces.deleteAll": "Smazat všechny pracovní prostory",
|
||||
"settings.workspaces.delete.warning":
|
||||
"Adresář a větev pracovního prostoru budou trvale odstraněny, včetně všech nesloučených změn zobrazených níže.",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"Pracovní stromy s nesloučenými změnami, propojenými relacemi nebo aktivními umístěními budou zachovány.",
|
||||
"settings.workspaces.delete.blocked.active": "Aktivní pracovní prostor nelze smazat.",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"Propojené relace zůstanou, ale jejich pracovní adresář bude trvale odstraněn.",
|
||||
"settings.workspaces.default.title": "Výchozí prostředí",
|
||||
"settings.workspaces.default.description": "Vyberte, kde začínají nové relace",
|
||||
"settings.workspaces.default.lastUsed": "Naposledy použito na projekt",
|
||||
"settings.workspaces.default.local": "Místní adresář",
|
||||
"settings.workspaces.default.new": "Nový pracovní prostor",
|
||||
"workspace.move.title": "Přesuňte se do pracovního prostoru",
|
||||
"workspace.move.menu.title": "Přesunout relaci do",
|
||||
"workspace.move.failed": "Přesun relace se nezdařil",
|
||||
"workspace.lifecycle.creating": "Vytváření pracovního prostoru",
|
||||
"workspace.lifecycle.created": "Pracovní prostor vytvořen",
|
||||
"workspace.lifecycle.starting": "Zahájení relace",
|
||||
"workspace.onboarding.title": "Izolujte relace s pracovními prostory",
|
||||
"workspace.onboarding.description": "Každá získá vlastní pracovní kopii, takže nic nezasahuje do místního repozitáře",
|
||||
"workspace.lifecycle.moving": "Přesun do pracovního prostoru",
|
||||
"workspace.lifecycle.set": "Pracovní prostor nastaven",
|
||||
"session.summary.title": "Podrobnosti relace",
|
||||
"session.summary.noBranch": "Žádná větev",
|
||||
"session.summary.basedOn": "Na základě {{branch}}",
|
||||
"settings.workspaces.count.few": "{{count}} pracovní plochy",
|
||||
"settings.workspaces.count.many": "{{count}} pracovních míst",
|
||||
"settings.workspaces.sessions.few": "{{count}} sezení v {{project}}",
|
||||
"settings.workspaces.sessions.many": "{{count}} relací v {{project}}",
|
||||
"desktop.menu.installCli": "Nainstalovat CLI...",
|
||||
"desktop.cli.installed.title": "CLI nainstalováno",
|
||||
"desktop.cli.installed.message":
|
||||
"CLI bylo nainstalováno do {{path}}\n\nChcete-li používat příkaz 'opencode2', restartujte terminál.",
|
||||
"desktop.cli.failed.title": "Instalace se nezdařila",
|
||||
"desktop.cli.failed.message": "CLI se nepodařilo nainstalovat: {{error}}",
|
||||
"command.project.copyID": "Kopírovat ID projektu",
|
||||
"command.session.copyID": "Kopírovat ID relace",
|
||||
"server.row.incompatible":
|
||||
"Tento server používá OpenCode {{version}}, který není kompatibilní s touto aplikací. Chcete-li pokračovat, upgradujte jej na OpenCode V2.",
|
||||
"toast.session.copyID.failed.title": "ID relace se nepodařilo zkopírovat",
|
||||
"toast.session.copyID.failed.description": "Při kopírování ID relace došlo k chybě",
|
||||
"toast.project.copyID.failed.title": "ID projektu se nepodařilo zkopírovat",
|
||||
"toast.project.copyID.failed.description": "Při kopírování ID projektu došlo k chybě",
|
||||
"error.page.title.status": "Požadavek na server se nezdařil",
|
||||
"error.page.description.status": "Server vrátil odpověď HTTP {{status}}.",
|
||||
"error.page.action.reload": "Načíst znovu",
|
||||
"session.error.incompatible": "Tato verze serveru není podporována",
|
||||
"session.error.incompatible.description":
|
||||
"{{server}} používá OpenCode {{version}}, který není kompatibilní s touto aplikací. Chcete-li pokračovat, upgradujte server na OpenCode V2.",
|
||||
"session.background.moveInline": "Stisknutím {{keybind}} přesunete probíhající práci na pozadí",
|
||||
"session.background.running": "Práce probíhá na pozadí",
|
||||
"session.background.runningCount.one": "Na pozadí probíhá {{count}} položka",
|
||||
"session.background.runningCount.few": "Na pozadí probíhají {{count}} položky",
|
||||
"session.background.runningCount.many": "Na pozadí probíhá {{count}} položky",
|
||||
"session.background.runningCount.other": "Na pozadí probíhá {{count}} položek",
|
||||
"settings.general.row.terminalPlacement.title": "Umístění terminálu",
|
||||
"settings.general.row.terminalPlacement.description": "Zvolte, kde se bude terminál v relacích otevírat",
|
||||
"settings.general.row.terminalPlacement.side": "Na straně",
|
||||
"settings.general.row.terminalPlacement.bottom": "Dole",
|
||||
"session.location.unavailable": "Umístění relace není dostupné",
|
||||
"session.location.description": "Chcete-li v této relaci pokračovat, vyberte jiný adresář.",
|
||||
"session.location.choose": "Vybrat adresář",
|
||||
"session.location.worktree": "Vybrat pracovní strom",
|
||||
"session.location.worktreesFailed": "Pracovní stromy se nepodařilo načíst",
|
||||
"session.location.moving": "Přesouvání relace…",
|
||||
"dialog.server.menu.hide": "Skrýt ze seznamu projektů",
|
||||
"dialog.server.menu.show": "Zobrazit v seznamu projektů",
|
||||
"session.queue.count.one": "{{count}} položka ve frontě",
|
||||
"session.queue.count.few": "{{count}} položky ve frontě",
|
||||
"session.queue.count.many": "{{count}} položky ve frontě",
|
||||
"session.queue.count.other": "{{count}} položek ve frontě",
|
||||
"session.queue.steer": "Usměrnit",
|
||||
"session.queue.send": "Odeslat",
|
||||
"session.queue.steerTooltip": "Odeslat bez přerušení",
|
||||
"session.queue.remove": "Odebrat",
|
||||
"session.queue.reorder": "Změnit pořadí požadavku ve frontě",
|
||||
"session.new.worktree.creating": "Vytváření pracovního stromu",
|
||||
"settings.backToApp": "Zpět do aplikace",
|
||||
"settings.appearance.section.experimental": "Experimentální",
|
||||
"settings.appearance.row.tabs.title": "Karty",
|
||||
"settings.appearance.row.tabs.description": "Zvolte uspořádání karet relací",
|
||||
"settings.appearance.row.tabs.horizontal": "Vodorovně",
|
||||
"settings.appearance.row.tabs.vertical": "Svisle",
|
||||
"settings.general.row.followUpBehavior.title": "Chování navazujících zpráv",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"Zvolte, zda navazující zprávy zařadit do fronty, nebo jimi usměrnit aktuální krok. Pomocí {{keybind}} lze režim přepnout.",
|
||||
"settings.general.row.followUpBehavior.queue": "Zařadit do fronty",
|
||||
"settings.general.row.followUpBehavior.steer": "Usměrnit",
|
||||
"settings.general.row.reasoningMode.title": "Zdůvodnění modelu",
|
||||
"settings.general.row.reasoningMode.description": "Zvolte, jak se zdůvodnění modelu zobrazí na časové ose",
|
||||
"settings.general.row.reasoningMode.hidden": "Skryté",
|
||||
"settings.general.row.reasoningMode.compact": "Kompaktní",
|
||||
"settings.general.row.reasoningMode.full": "Úplné",
|
||||
"session.new.workspace.createFrom": "Vytvořit z větve",
|
||||
"session.new.workspace.branch.search.placeholder": "Hledat větve",
|
||||
"desktop.onboarding.defaultProject": "Výchozí projekt",
|
||||
"toast.migration.progress.clearingOldEvents": "Mazání starých událostí",
|
||||
"toast.migration.progress.migratingSessions": "Migrace relací",
|
||||
"session.new.workspace.existingLabel": "Pracovní strom",
|
||||
"session.review.change.few": "Změny",
|
||||
"session.review.change.many": "Změny",
|
||||
"home.projects.all": "Všechny projekty",
|
||||
"session.tab.files": "Soubory",
|
||||
"session.files.openTabs": "Otevřené soubory",
|
||||
"session.tab.usage": "Použití",
|
||||
"session.view.select": "Zobrazení relace",
|
||||
"session.background.moveTasks": "Přesuňte {{tasks}} na pozadí",
|
||||
"session.background.moveRunning": "Přesun na pozadí",
|
||||
"session.background.inBackground": "Na pozadí běží {{tasks}}",
|
||||
"session.background.tasksRunning.one": "{{count}} úloha běží na pozadí",
|
||||
"session.background.tasksRunning.other": "{{count}} úloh běží na pozadí",
|
||||
"session.background.combine": "{{first}} a {{second}}",
|
||||
"session.background.shell.one": "{{count}} shell",
|
||||
"session.background.shell.other": "{{count}} shellů",
|
||||
"session.background.subagent.one": "{{count}} podagent",
|
||||
"session.background.subagent.other": "{{count}} podagentů",
|
||||
"session.timeline.working": "Pracuje",
|
||||
"session.review.wrapLines": "Zalamovat řádky",
|
||||
"session.websearch.title": "Webové vyhledávání třetích stran",
|
||||
"session.websearch.description": "Vyberte agenty poskytovatele vyhledávání, které používají k vyhledávání na webu",
|
||||
"session.websearch.provider": "Poskytovatel vyhledávání",
|
||||
"session.websearch.any": "Libovolný",
|
||||
"session.websearch.disable": "Nepoužívejte vyhledávání",
|
||||
"session.websearch.enable": "Povolit",
|
||||
"session.websearch.loadFailed": "Nelze načíst poskytovatele vyhledávání.",
|
||||
"session.websearch.empty": "Nejsou k dispozici žádní poskytovatelé vyhledávání.",
|
||||
"session.websearch.failed": "Vaši volbu nelze uložit. Zkuste to prosím znovu.",
|
||||
"session.websearch.retry": "Zkuste to znovu",
|
||||
"session.new.worktree.draftPlaceholder": "Napište následnou zprávu, zatímco se připravuje pracovní strom…",
|
||||
"session.search.placeholder": "Najít...",
|
||||
"session.search.noResults": "Žádné shody",
|
||||
"titlebar.tabs": "Karty",
|
||||
"titlebar.channel.local": "Místní",
|
||||
"titlebar.channel.dev": "Dev",
|
||||
"titlebar.channel.beta": "Beta",
|
||||
"titlebar.toggleDebugTools": "Přepínání nástrojů pro ladění",
|
||||
"settings.tab.experimental": "Experimentální",
|
||||
"settings.experimental.description": "Vyzkoušejte experimentální funkce",
|
||||
"settings.tab.about": "O",
|
||||
"settings.about.version": "Verze {{version}}",
|
||||
"settings.about.devVersion": "Vývoj",
|
||||
"settings.about.license": "Vydáno pod MIT License",
|
||||
"settings.about.writtenBy": "Napsal",
|
||||
"settings.about.illustratedBy": "Ilustroval",
|
||||
"settings.about.and": "a",
|
||||
"settings.about.otherContributor.one": "{{count}} další",
|
||||
"settings.about.otherContributor.other": "{{count}} dalších",
|
||||
"settings.about.firstPublished": "Poprvé publikováno v Missouri, USA",
|
||||
"settings.about.firstIllustrated": "Poprvé ilustrováno v Londýně, Anglie",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode, open source kódovací agent",
|
||||
"settings.about.trademark": "OpenCode je registrovaná ochranná známka společnosti Anomaly Innovations, Inc.",
|
||||
"settings.about.typeset": "Typová sada v Inter a IBM Plex Mono",
|
||||
"settings.about.tagline": "AI nemůže vytvořit skvělý software bez vás",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "Upravit projekt",
|
||||
"settings.timeline.title": "Časová osa",
|
||||
"settings.timeline.detail": "Detail časové osy",
|
||||
"settings.timeline.description": "Zvolte, kolik aktivity se objeví na časové ose. Zprávy zůstávají viditelné.",
|
||||
"settings.timeline.preset.everything": "Všechno",
|
||||
"settings.timeline.preset.detailed": "Detailně",
|
||||
"settings.timeline.preset.compact": "Kompaktní",
|
||||
"settings.timeline.preset.quiet": "Tichý",
|
||||
"settings.timeline.preset.text-only": "Pouze text",
|
||||
"settings.timeline.description.everything":
|
||||
"Zobrazit všechny aktivity samostatně. Rozšiřte výstup shellu, úpravy a myšlení.",
|
||||
"settings.timeline.description.detailed":
|
||||
"Rozšiřte výstup shellu a úpravy. Zobrazit podagenty samostatně a seskupit další aktivity v Použito.",
|
||||
"settings.timeline.description.compact": "Seskupit veškerou aktivitu v Použito se sbalenými podrobnostmi.",
|
||||
"settings.timeline.description.quiet": "Úpravy skupin a subagenti v Použito. Skrýt jinou aktivitu.",
|
||||
"settings.timeline.description.text-only": "Skrýt veškerou aktivitu. Zobrazit pouze zprávy.",
|
||||
"settings.timeline.description.custom": "Použijte zvolené umístění a podrobnosti pro každou kategorii aktivity.",
|
||||
"settings.timeline.custom": "Vlastní",
|
||||
"settings.timeline.advanced": "Pokročilé",
|
||||
"settings.timeline.advanced.description": "Nastavte umístění a podrobnosti pro každou kategorii aktivity.",
|
||||
"settings.timeline.category.shell": "Shell",
|
||||
"settings.timeline.category.edit": "Úpravy",
|
||||
"settings.timeline.category.thinking": "Myšlení",
|
||||
"settings.timeline.category.subagents": "subagenty",
|
||||
"settings.timeline.category.notices": "Upozornění",
|
||||
"settings.timeline.category.tools": "Jiné nářadí",
|
||||
"settings.general.row.mobileDiffWrap.description":
|
||||
"Zabalte dlouhé řádky do mobilních diffů namísto vodorovného posouvání",
|
||||
"session.background.tasksRunning.few": "{{count}} úlohy běží na pozadí",
|
||||
"session.background.tasksRunning.many": "{{count}} úlohy běží na pozadí",
|
||||
"session.background.shell.few": "{{count}} shelly",
|
||||
"session.background.shell.many": "{{count}} shellu",
|
||||
"session.background.subagent.few": "{{count}} podagenti",
|
||||
"session.background.subagent.many": "{{count}} podagenta",
|
||||
"settings.about.otherContributor.few": "{{count}} další",
|
||||
"settings.about.otherContributor.many": "{{count}} dalšího",
|
||||
"provider.connect.error.unsupportedFields": "Tento ověřovací formulář obsahuje nepodporovaná pole",
|
||||
"session.review.filesChangedCount.one": "{{count}} soubor změněn",
|
||||
"session.review.filesChangedCount.few": "{{count}} soubory změněny",
|
||||
"session.review.filesChangedCount.many": "{{count}} souboru změněno",
|
||||
"session.review.filesChangedCount.other": "{{count}} souborů změněno",
|
||||
"settings.about.writtenByNames": "Napsal {{names}}",
|
||||
"settings.about.illustratedByNames": "Ilustroval {{names}}",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline": "Nejste připojeni k hostiteli {{host}}. Koncept je zachován; vzdálená úloha může stále běžet.",
|
||||
"ssh.placeholder": "ssh uzivatel@example.com",
|
||||
"ssh.add": "Přidat server SSH",
|
||||
"ssh.server.menu.label": "Server SSH",
|
||||
"ssh.target": "Hostitel nebo příkaz SSH",
|
||||
"ssh.connect": "Připojit",
|
||||
"ssh.connectTo": "Připojit k hostiteli {{host}}",
|
||||
"ssh.authenticate": "Ověření SSH",
|
||||
"ssh.action.authenticate": "Ověřit",
|
||||
"ssh.session.disconnected": "Připojení SSH není aktivní",
|
||||
"ssh.session.connecting": "Připojování k serveru SSH",
|
||||
"ssh.session.reconnectDescription":
|
||||
"Opětovným připojením zobrazíte tuto relaci a můžete pokračovat v práci. Vzdálená relace je zachována.",
|
||||
"ssh.session.reconnect": "Znovu připojit",
|
||||
"ssh.authenticationRequired": "Hostitel {{host}} vyžaduje ověření",
|
||||
"ssh.trust": "Důvěřovat a připojit",
|
||||
"ssh.continue": "Pokračovat",
|
||||
"ssh.retry": "Zkusit znovu",
|
||||
"ssh.update": "Aktualizovat a znovu připojit",
|
||||
"ssh.openProject": "Otevřít projekt",
|
||||
"ssh.project": "Otevřít projekt na hostiteli {{host}}",
|
||||
"ssh.disconnect": "Odpojit",
|
||||
"ssh.forget": "Zapomenout připojení",
|
||||
"ssh.stage.disconnected": "Odpojeno. Vzdálený server zůstal spuštěný.",
|
||||
"ssh.stage.connecting": "Připojování přes SSH…",
|
||||
"ssh.stage.checking": "Kontrola OpenCode…",
|
||||
"ssh.stage.downloading": "Stahování serveru…",
|
||||
"ssh.stage.uploading": "Nahrávání serveru…",
|
||||
"ssh.stage.starting": "Připojování k OpenCode…",
|
||||
"ssh.stage.ready": "Připojeno",
|
||||
"ssh.stage.authentication": "Je vyžadováno ověření",
|
||||
"ssh.stage.incompatible": "Je vyžadována aktualizace serveru",
|
||||
"ssh.stage.failed": "Připojení se nezdařilo",
|
||||
"ssh.error.input":
|
||||
"Zadejte hostitele nebo příkaz pro připojení SSH. Vzdálené příkazy a nepodporované volby SSH nejsou povoleny.",
|
||||
"ssh.error.connection": "Připojení SSH se nepodařilo navázat. Zkontrolujte síť a konfiguraci SSH.",
|
||||
"ssh.error.platform":
|
||||
"Tato vzdálená platforma není podporována. Automatické nastavení nyní vyžaduje Linux nebo macOS na architektuře x64 či arm64.",
|
||||
"ssh.error.version": "Vzdálená služba musí před připojením odpovídat této verzi aplikace Desktop.",
|
||||
"ssh.error.install":
|
||||
"Vzdálený server se nepodařilo nainstalovat. Zkontrolujte připojení, místo na disku a instalaci programu tar.",
|
||||
"ssh.error.unpublished":
|
||||
"Pro tuto verzi aplikace Desktop není publikován vzdálený server. U vývojových sestavení nainstalujte a spusťte V2 na hostiteli a zkuste to znovu.",
|
||||
"ssh.error.service": "SSH se připojilo, ale server OpenCode nebyl připraven.",
|
||||
"ssh.error.host-key":
|
||||
"Identitu hostitele se nepodařilo ověřit. Před aktualizací známých hostitelů SSH ověřte jeho otisk.",
|
||||
"ssh.error.ssh-missing":
|
||||
"OpenSSH nebylo nalezeno. Nainstalujte klienta OpenSSH a ověřte, že je ssh dostupné v proměnné PATH.",
|
||||
"command.browser.open": "Otevřít prohlížeč",
|
||||
"command.browser.reload": "Znovu načíst stránku prohlížeče",
|
||||
"command.session.summary.toggle": "Přepnout souhrn",
|
||||
"common.color.orange": "oranžová",
|
||||
"common.color.yellow": "žlutá",
|
||||
"common.color.cyan": "azurová",
|
||||
"common.color.green": "zelená",
|
||||
"common.color.red": "červená",
|
||||
"common.color.pink": "růžová",
|
||||
"common.color.blue": "modrá",
|
||||
"common.color.purple": "fialová",
|
||||
"common.color.gray": "šedá",
|
||||
"mcp.auth.interactiveForm": "Server MCP {{name}} vyžaduje interaktivní ověřovací formulář",
|
||||
"server.connect.title": "Připojit k serveru",
|
||||
"server.connect.description": "Začněte zadáním adresy serveru a hesla.",
|
||||
"server.connect.button": "Připojit",
|
||||
"server.connect.address.invalid": "Zadejte platnou adresu serveru HTTP nebo HTTPS.",
|
||||
"server.connect.failed": "Připojení se nezdařilo. Zkontrolujte adresu serveru a heslo a zkuste to znovu.",
|
||||
"server.connect.pair.description": "Spuštěním tohoto příkazu v počítači získáte údaje pro připojení.",
|
||||
"server.connect.scan": "Naskenovat QR kód",
|
||||
"server.connect.scan.description": "Namiřte kameru na QR kód zobrazený příkazem opencode pair.",
|
||||
"server.connect.scan.invalid": "Toto není párovací kód OpenCode. Naskenujte kód zobrazený příkazem opencode pair.",
|
||||
"server.connect.camera": "Kamera pro párování",
|
||||
"server.connect.camera.starting": "Otevírání kamery…",
|
||||
"server.connect.mixedContent":
|
||||
"K tomuto serveru HTTP se nelze připojit ze stránky HTTPS. Použijte adresu serveru HTTPS.",
|
||||
"server.connect.camera.insecure": "Skenování QR kódu vyžaduje otevření této stránky přes HTTPS nebo na localhostu.",
|
||||
"server.connect.camera.unavailable":
|
||||
"Pro tento prohlížeč není dostupná žádná kamera. Zadejte údaje pro připojení ručně.",
|
||||
"server.connect.camera.error":
|
||||
"Kameru se nepodařilo otevřít. Povolte přístup ke kameře nebo zadejte údaje pro připojení ručně.",
|
||||
"dialog.server.menu.remove": "Odebrat",
|
||||
"file.error.notFound": "Soubor nebyl nalezen: {{name}}",
|
||||
"toast.migration.progress.migratingSessions.current": "Migrace relací {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "Migrace relací {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "Migrace dat",
|
||||
"toast.migration.progress.working.current": "Migrace dat {{current}}",
|
||||
"toast.migration.progress.working.progress": "Migrace dat {{current}}/{{total}}",
|
||||
"home.workspaceTip": "Spusťte příští relaci v novém pracovním prostoru, aby změny zůstaly oddělené",
|
||||
"session.tab.browser": "Prohlížeč",
|
||||
"session.tab.add": "Přidat kartu",
|
||||
"session.queue.attachments.one": "A {{count}} příloha",
|
||||
"session.queue.attachments.few": "A {{count}} přílohy",
|
||||
"session.queue.attachments.many": "A {{count}} přílohy",
|
||||
"session.queue.attachments.other": "A {{count}} příloh",
|
||||
"session.browser.address": "Adresa prohlížeče",
|
||||
"session.browser.replaced": "Ovládání prohlížeče bylo přesunuto do jiného okna aplikace Desktop.",
|
||||
"session.browser.unsupported": "Tato desktopová aplikace nepodporuje panel prohlížeče.",
|
||||
"session.browser.suspended": "Prohlížeč je pozastaven. Interakcí s touto relací se znovu připojíte.",
|
||||
"session.browser.address.placeholder": "Zadejte URL",
|
||||
"settings.backToSettings": "Zpět na nastavení",
|
||||
"settings.backToProjects": "Zpět na projekty",
|
||||
"settings.search.placeholder": "Hledat",
|
||||
"settings.search.results": "Výsledky nastavení",
|
||||
"settings.search.group.pages": "Stránky",
|
||||
"settings.search.group.settings": "Nastavení",
|
||||
"settings.search.group.projects": "Projekty",
|
||||
"settings.search.group.servers": "Servery",
|
||||
"settings.search.result": "{{title}}, {{scope}}, {{page}}",
|
||||
"settings.search.page": "{{title}}, {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}, {{page}}",
|
||||
"settings.search.empty": "Žádné výsledky pro {{query}}",
|
||||
"settings.search.empty.query": "„{{query}}“",
|
||||
"settings.search.refine": "Zúžením hledání zobrazíte konkrétnější výsledky.",
|
||||
"settings.server.description": "Správa připojení a předvoleb tohoto serveru",
|
||||
"settings.server.section.connection": "Připojení",
|
||||
"settings.server.preferences.websearch.title": "Vyhledávání třetí strany",
|
||||
"settings.server.preferences.websearch.description":
|
||||
"Vyberte poskytovatele, kterého agenti používají k vyhledávání na webu",
|
||||
"settings.projects.search.placeholder": "Hledat projekty",
|
||||
"project.settings.name.title": "Název projektu",
|
||||
"project.settings.name.description": "Název zobrazovaný pro tento projekt v celém OpenCode",
|
||||
"project.settings.icon.description": "Doporučeno: 128 × 128 px. Kliknutím nebo přetažením nahrajte obrázek.",
|
||||
"project.settings.color.description": "Použije se pro ikonu projektu, pokud není nastaven vlastní obrázek",
|
||||
"project.settings.worktree.startup.description": "Spustí se jednou po vytvoření nového pracovního stromu",
|
||||
"project.settings.worktree.startup.hint.base": "Pro základní pracovní strom použijte $OPENCODE_WORKTREE_BASE.",
|
||||
"project.settings.worktree.startup.hint.new": "Pro nový pracovní strom použijte $OPENCODE_WORKTREE_PATH.",
|
||||
"project.settings.extensions.empty.mcps.title": "Zatím žádné MCP",
|
||||
"project.settings.extensions.empty.mcps.description": "Zde se zobrazí MCP dostupná pro OpenCode",
|
||||
"project.settings.extensions.empty.plugins.title": "Zatím žádné zásuvné moduly",
|
||||
"project.settings.extensions.empty.plugins.description": "Zde se zobrazí zásuvné moduly dostupné pro OpenCode",
|
||||
"project.settings.extensions.empty.skills.title": "Zatím žádné dovednosti",
|
||||
"project.settings.extensions.empty.skills.description": "Zde se zobrazí dovednosti dostupné pro OpenCode",
|
||||
"project.settings.extensions.lsp.configured": "Nakonfigurované jazykové servery",
|
||||
"project.settings.extensions.lsp.status.enabled": "Povoleno v konfiguraci",
|
||||
"project.settings.extensions.lsp.status.disabled": "Zakázáno v konfiguraci",
|
||||
"project.settings.extensions.lsp.empty.title": "Nejsou nakonfigurovány žádné jazykové servery",
|
||||
"project.settings.extensions.lsp.empty.description":
|
||||
"Zde se zobrazí jazykové servery nakonfigurované pro tento projekt",
|
||||
"project.settings.extensions.lsp.disabled.title": "Jazykové servery jsou zakázány",
|
||||
"project.settings.extensions.lsp.disabled.description": "LSP je v konfiguraci tohoto projektu zakázáno",
|
||||
"project.settings.extensions.lsp.loadFailed": "Konfiguraci jazykového serveru se nepodařilo načíst",
|
||||
"project.settings.extensions.lsp.retry": "Zkusit znovu",
|
||||
"settings.timeline.summary": "{{preset}}:",
|
||||
"settings.timeline.group": "Seskupit",
|
||||
"settings.timeline.collapse": "Sbalit",
|
||||
"settings.timeline.visibility.show": "Zobrazit",
|
||||
"settings.timeline.visibility.hide": "Skrýt",
|
||||
"settings.timeline.visibility.label": "Viditelnost aktivity {{activity}}",
|
||||
"settings.timeline.grouped.label": "Aktivita {{activity}} je seskupená",
|
||||
"settings.timeline.collapsed.label": "Aktivita {{activity}} je sbalená",
|
||||
"session.new.workspace.search.empty": "Žádné odpovídající pracovní stromy",
|
||||
"settings.workspaces.description": "Kontrola pracovních stromů a správa využití disku",
|
||||
"settings.workspaces.empty.description": "Zde se zobrazí pracovní stromy vytvořené v OpenCode",
|
||||
"settings.workspaces.sessions.filtered.one": "{{count}} relace",
|
||||
"settings.workspaces.sessions.filtered.few": "{{count}} relace",
|
||||
"settings.workspaces.sessions.filtered.many": "{{count}} relace",
|
||||
"settings.workspaces.sessions.filtered.other": "{{count}} relací",
|
||||
"settings.workspaces.deleteAll.confirm.one": "Tímto trvale odstraníte {{count}} vybraný pracovní strom.",
|
||||
"settings.workspaces.deleteAll.confirm.few": "Tímto trvale odstraníte {{count}} vybrané pracovní stromy.",
|
||||
"settings.workspaces.deleteAll.confirm.many": "Tímto trvale odstraníte {{count}} vybraného pracovního stromu.",
|
||||
"settings.workspaces.deleteAll.confirm.other": "Tímto trvale odstraníte {{count}} vybraných pracovních stromů.",
|
||||
"settings.workspaces.deleteWithoutSessions": "Odstranit pracovní stromy bez relací",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"Tímto trvale odstraníte {{count}} pracovní strom bez propojených relací.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.few":
|
||||
"Tímto trvale odstraníte {{count}} pracovní stromy bez propojených relací.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.many":
|
||||
"Tímto trvale odstraníte {{count}} pracovního stromu bez propojených relací.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"Tímto trvale odstraníte {{count}} pracovních stromů bez propojených relací.",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"Pracovní stromy s nesloučenými změnami nebo aktivními umístěními budou zachovány.",
|
||||
"settings.workspaces.delete.button": "Odstranit pracovní stromy",
|
||||
"workspace.lifecycle.deleting": "Odstraňování…",
|
||||
"session.summary.tooltip": "Souhrn",
|
||||
"session.summary.server": "Rozšíření",
|
||||
"session.summary.chooseProject": "Vyberte projekt",
|
||||
"session.summary.mcp.onCreation": "Použije se při vytvoření pracovního stromu",
|
||||
"session.summary.mcp.prepareFailed": "Servery MCP se nepodařilo připravit",
|
||||
"session.summary.mcp.unavailable": "Server MCP {{name}} není v tomto pracovním stromu dostupný.",
|
||||
"session.summary.mcp.signInBeforeSend": "Před odesláním výzvy se přihlaste k {{name}}.",
|
||||
"session.summary.mcp.notReady": "Server MCP {{name}} není připraven. Před odesláním výzvy vyřešte jeho připojení.",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "Nakonfigurované servery MCP",
|
||||
"session.summary.plugins": "Zásuvné moduly",
|
||||
"session.summary.plugins.configured": "Nakonfigurované zásuvné moduly",
|
||||
"session.summary.skills": "Dovednosti",
|
||||
"session.summary.skills.configured": "Nakonfigurované dovednosti",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "Nezdařilo se",
|
||||
"session.summary.retry": "Zkusit znovu",
|
||||
"session.summary.connecting": "Připojování…",
|
||||
"session.summary.needsAuth": "Je vyžadováno přihlášení",
|
||||
"session.summary.configure": "Konfigurační soubor",
|
||||
"session.summary.copyConfigPath": "Kopírovat cestu ke konfiguračnímu souboru",
|
||||
"session.summary.configFileMissing": "Nebyl nalezen žádný konfigurační soubor",
|
||||
"session.summary.mcp.empty": "Nejsou nakonfigurovány žádné servery MCP",
|
||||
"session.summary.mcp.add": "Přidejte servery v opencode.json",
|
||||
"session.summary.plugins.manage": "Spravujte zásuvné moduly v opencode.json",
|
||||
"session.summary.plugins.empty": "Nejsou nakonfigurovány žádné zásuvné moduly",
|
||||
"session.summary.plugins.add": "Přidejte zásuvné moduly v opencode.json",
|
||||
"session.summary.skills.manage": "Spravujte dovednosti v opencode.json",
|
||||
"session.summary.skills.empty": "Nejsou nakonfigurovány žádné dovednosti",
|
||||
"session.summary.skills.add": "Přidejte dovednosti v opencode.json",
|
||||
"session.summary.lsp.configured": "Nakonfigurovaná LSP",
|
||||
"session.summary.lsp.empty": "Nejsou nakonfigurovány žádné servery LSP",
|
||||
"session.summary.lsp.manage": "Spravujte LSP v opencode.json",
|
||||
"workspace.delete.location": "Umístění",
|
||||
"command.debugBar.toggle": "Přepnout panel ladění",
|
||||
"command.session.location.cycle": "Přepnout umístění relace",
|
||||
"dialog.provider.anthropic.note": "Přímý přístup k modelům Claude pomocí klíče API",
|
||||
"provider.connect.title.anthropicProMax": "Přihlásit se přes Anthropic",
|
||||
"prompt.toast.uploading.cancel": "Zrušit nahrávání",
|
||||
"prompt.toast.uploading.cancelFile": "Zrušit nahrávání souboru {{filename}}",
|
||||
"prompt.toast.uploadFailed.title": "Nahrávání se nezdařilo",
|
||||
"session.browser.empty.title": "Zadejte URL",
|
||||
"session.browser.empty.description": "Nebo zadejte pokyn „Otevřít v prohlížeči aplikace“",
|
||||
"session.browser.failed.title": "URL není dostupná",
|
||||
"session.browser.failed.description": "Zkontrolujte URL a připojení a zkuste to znovu.",
|
||||
"debugBar.providerAriaLabel": "Diagnostika výkonu poskytovatele",
|
||||
"debugBar.ttft.tip": "Doba od odeslání požadavku poskytovateli do prvního výstupu modelu.",
|
||||
"debugBar.ttfa.tip": "Doba od odeslání požadavku poskytovateli do prvního textu odpovědi.",
|
||||
"debugBar.tps.tip": "Počet výstupních tokenů za sekundu po prvním výstupu modelu.",
|
||||
"debugBar.e2e.tip": "Doba od odeslání požadavku poskytovateli do ukončení proudu odpovědi.",
|
||||
"settings.updates.action.download": "Stáhnout OpenCode",
|
||||
"settings.updates.migration.title": "Přejít z Beta na Stable",
|
||||
"settings.updates.migration.description":
|
||||
"OpenCode Beta prozatím přechází na OpenCode Stable. Stáhněte verzi {{version}} a poté nainstalujte OpenCode z obrazu disku, abyste mohli nadále dostávat aktualizace.",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
}
|
||||
|
||||
@@ -1,4 +1,328 @@
|
||||
export const dict = {
|
||||
"common.color.orange": "orange",
|
||||
"common.color.yellow": "gul",
|
||||
"common.color.cyan": "cyan",
|
||||
"common.color.green": "grøn",
|
||||
"common.color.red": "rød",
|
||||
"common.color.pink": "lyserød",
|
||||
"common.color.blue": "blå",
|
||||
"common.color.purple": "lilla",
|
||||
"common.color.gray": "grå",
|
||||
"toast.migration.progress.migratingSessions.current": "Migrerer sessioner {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "Migrerer sessioner {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "Migrerer data",
|
||||
"toast.migration.progress.working.current": "Migrerer data {{current}}",
|
||||
"toast.migration.progress.working.progress": "Migrerer data {{current}}/{{total}}",
|
||||
"session.browser.unsupported": "Denne desktopapp understøtter ikke browserpanelet.",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline": "Ikke forbundet til {{host}}. Dit udkast er bevaret; fjernarbejde kører muligvis stadig.",
|
||||
"ssh.placeholder": "ssh user@example.com",
|
||||
"ssh.add": "Tilføj SSH-server",
|
||||
"ssh.server.menu.label": "SSH server",
|
||||
"ssh.target": "Host eller SSH kommando",
|
||||
"ssh.connect": "Forbind",
|
||||
"ssh.connectTo": "Tilslut til {{host}}",
|
||||
"ssh.authenticate": "SSH-godkendelse",
|
||||
"ssh.action.authenticate": "Godkend",
|
||||
"ssh.session.disconnected": "SSH-forbindelse inaktiv",
|
||||
"ssh.session.connecting": "Opretter forbindelse til SSH-server",
|
||||
"ssh.session.reconnectDescription":
|
||||
"Opret forbindelse igen for at se denne session og fortsæt med at arbejde. Din fjernsession er bevaret.",
|
||||
"ssh.session.reconnect": "Tilslut igen",
|
||||
"ssh.authenticationRequired": "Godkendelse påkrævet for {{host}}",
|
||||
"ssh.trust": "Tillid og forbind",
|
||||
"ssh.continue": "Fortsæt",
|
||||
"ssh.retry": "Prøv igen",
|
||||
"ssh.update": "Opdater og genopret forbindelse",
|
||||
"ssh.openProject": "Åbent projekt",
|
||||
"ssh.project": "Åbent projekt på {{host}}",
|
||||
"ssh.disconnect": "Afbryd forbindelsen",
|
||||
"ssh.forget": "Glem forbindelsen",
|
||||
"ssh.stage.disconnected": "Afbrudt. Fjernserveren efterlades kørende.",
|
||||
"ssh.stage.connecting": "Opretter forbindelse via SSH...",
|
||||
"ssh.stage.checking": "Tjekker OpenCode...",
|
||||
"ssh.stage.downloading": "Downloader server...",
|
||||
"ssh.stage.uploading": "Uploader server...",
|
||||
"ssh.stage.starting": "Opretter forbindelse til OpenCode...",
|
||||
"ssh.stage.ready": "Forbundet",
|
||||
"ssh.stage.authentication": "Godkendelse påkrævet",
|
||||
"ssh.stage.incompatible": "Serveropdatering påkrævet",
|
||||
"ssh.stage.failed": "Forbindelsen mislykkedes",
|
||||
"ssh.error.input":
|
||||
"Indtast en værts- eller SSH-forbindelseskommando. Fjernkommandoer og ikke-understøttede SSH-indstillinger er ikke tilladt.",
|
||||
"ssh.error.connection": "Kunne ikke etablere SSH-forbindelsen. Tjek dit netværk og din SSH-konfiguration.",
|
||||
"ssh.error.platform":
|
||||
"Denne fjernplatform er ikke understøttet. Automatisk opsætning kræver i øjeblikket Linux eller macOS på x64 eller arm64.",
|
||||
"ssh.error.version": "Fjerntjenesten skal matche denne Desktop-version, før der oprettes forbindelse.",
|
||||
"ssh.error.install":
|
||||
"Fjernserveren kunne ikke installeres. Tjek tilslutningsmuligheder, diskplads, og at tar er installeret.",
|
||||
"ssh.error.unpublished":
|
||||
"Denne desktopversion har ingen offentliggjort fjernserver. For udviklingsbuilds, installer og start V2 på værten, og prøv derefter igen.",
|
||||
"ssh.error.service": "SSH tilsluttet, men OpenCode-serveren blev ikke klar.",
|
||||
"ssh.error.host-key":
|
||||
"Værtens identitet kunne ikke bekræftes. Bekræft dets fingeraftryk, før du opdaterer dine SSH kendte værter.",
|
||||
"ssh.error.ssh-missing":
|
||||
"OpenSSH blev ikke fundet. Installer en OpenSSH-klient, og sørg for, at ssh er tilgængelig på PATH.",
|
||||
"command.browser.open": "Åbn browser",
|
||||
"command.browser.reload": "Genindlæs browsersiden",
|
||||
"command.session.summary.toggle": "Skift sammendrag",
|
||||
"mcp.auth.interactiveForm": "MCP server {{name}} kræver en interaktiv godkendelsesformular",
|
||||
"server.connect.title": "Opret forbindelse til en server",
|
||||
"server.connect.description": "Indtast din serveradresse og adgangskode for at komme i gang.",
|
||||
"server.connect.button": "Forbind",
|
||||
"server.connect.address.invalid": "Indtast en gyldig HTTP- eller HTTPS-serveradresse.",
|
||||
"server.connect.failed":
|
||||
"Kunne ikke oprette forbindelse. Tjek serveradressen og adgangskoden, og prøv derefter igen.",
|
||||
"server.connect.pair.description": "Kør denne kommando på din computer for at få dine forbindelsesdetaljer.",
|
||||
"server.connect.scan": "Scan QR kode",
|
||||
"server.connect.scan.description": "Ret dit kamera mod QR-koden vist af opencode pair.",
|
||||
"server.connect.scan.invalid": "Dette er ikke en OpenCode-parringskode. Scan koden vist af opencode pair.",
|
||||
"server.connect.camera": "Parring af kamera",
|
||||
"server.connect.camera.starting": "Åbner kamera...",
|
||||
"server.connect.mixedContent":
|
||||
"Kunne ikke oprette forbindelse til denne HTTP-server fra en HTTPS-side. Brug i stedet en HTTPS-serveradresse.",
|
||||
"server.connect.camera.insecure": "QR-scanning kræver, at denne side åbnes over HTTPS eller på localhost.",
|
||||
"server.connect.camera.unavailable":
|
||||
"Intet kamera er tilgængeligt for denne browser. Indtast dine forbindelsesoplysninger manuelt.",
|
||||
"server.connect.camera.error":
|
||||
"Kunne ikke åbne kameraet. Tillad kameraadgang, eller indtast dine forbindelsesoplysninger manuelt.",
|
||||
"dialog.server.menu.remove": "Fjern",
|
||||
"file.error.notFound": "Filen blev ikke fundet: {{name}}",
|
||||
"home.workspaceTip": "Start næste session i et nyt arbejdsområde for at holde ændringer isoleret",
|
||||
"session.tab.browser": "Browser",
|
||||
"session.tab.add": "Tilføj fane",
|
||||
"session.queue.attachments.one": "Plus {{count}} vedhæftning",
|
||||
"session.queue.attachments.other": "Plus {{count}} vedhæftede filer",
|
||||
"session.browser.address": "Browser adresse",
|
||||
"session.browser.replaced": "Browserkontrol flyttet til et andet skrivebordsvindue.",
|
||||
"session.browser.suspended": "Browser suspenderet. Interager med denne session for at genoprette forbindelsen.",
|
||||
"session.browser.address.placeholder": "Indtast URL",
|
||||
"settings.backToSettings": "Tilbage til indstillinger",
|
||||
"settings.backToProjects": "Tilbage til projekter",
|
||||
"settings.search.placeholder": "Søg",
|
||||
"settings.search.results": "Indstillinger resultater",
|
||||
"settings.search.group.pages": "Sider",
|
||||
"settings.search.group.settings": "Indstillinger",
|
||||
"settings.search.group.projects": "Projekter",
|
||||
"settings.search.group.servers": "Servere",
|
||||
"settings.search.result": "{{title}}, {{scope}}, {{page}}",
|
||||
"settings.search.page": "{{title}}, {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}, {{page}}",
|
||||
"settings.search.empty": "Ingen resultater for {{query}}",
|
||||
"settings.search.empty.query": '"{{query}}"',
|
||||
"settings.search.refine": "Begræns din søgning for at se mere specifikke resultater.",
|
||||
"settings.server.description": "Administrer denne servers forbindelse og præferencer",
|
||||
"settings.server.section.connection": "Forbindelse",
|
||||
"settings.server.preferences.websearch.title": "Tredjepartssøgning",
|
||||
"settings.server.preferences.websearch.description": "Vælg den søgeudbyder, som agenter bruger til at søge på nettet",
|
||||
"settings.projects.search.placeholder": "Søg efter projekter",
|
||||
"project.settings.name.title": "Projektnavn",
|
||||
"project.settings.name.description": "Navnet vist for dette projekt i hele OpenCode",
|
||||
"project.settings.icon.description": "Anbefalet: 128×128px. Klik eller træk for at uploade et billede.",
|
||||
"project.settings.color.description":
|
||||
"Bruges til projektikonet, når der ikke er indstillet et brugerdefineret billede",
|
||||
"project.settings.worktree.startup.description": "Kører én gang efter oprettelse af et nyt arbejdsområde",
|
||||
"project.settings.worktree.startup.hint.base": "Brug $OPENCODE_WORKTREE_BASE til basisarbejdsområdet.",
|
||||
"project.settings.worktree.startup.hint.new": "Brug $OPENCODE_WORKTREE_PATH til det nye arbejdsområde.",
|
||||
"project.settings.extensions.empty.mcps.title": "Ingen MCPs endnu",
|
||||
"project.settings.extensions.empty.mcps.description": "MCPs tilgængelig for OpenCode vises her",
|
||||
"project.settings.extensions.empty.plugins.title": "Ingen plugins endnu",
|
||||
"project.settings.extensions.empty.plugins.description": "Plugins, der er tilgængelige for OpenCode, vises her",
|
||||
"project.settings.extensions.empty.skills.title": "Ingen færdigheder endnu",
|
||||
"project.settings.extensions.empty.skills.description": "De færdigheder, der er tilgængelige for OpenCode, vises her",
|
||||
"project.settings.extensions.lsp.configured": "Konfigurerede sprogservere",
|
||||
"project.settings.extensions.lsp.status.enabled": "Aktiveret i config",
|
||||
"project.settings.extensions.lsp.status.disabled": "Deaktiveret i config",
|
||||
"project.settings.extensions.lsp.empty.title": "Ingen sprogservere konfigureret",
|
||||
"project.settings.extensions.lsp.empty.description": "Sprogservere, der er konfigureret til dette projekt, vises her",
|
||||
"project.settings.extensions.lsp.disabled.title": "Sprogservere deaktiveret",
|
||||
"project.settings.extensions.lsp.disabled.description": "LSP er deaktiveret i dette projekts konfiguration",
|
||||
"project.settings.extensions.lsp.loadFailed": "Kunne ikke indlæse sprogserverkonfigurationen",
|
||||
"project.settings.extensions.lsp.retry": "Prøv igen",
|
||||
"settings.timeline.summary": "{{preset}}:",
|
||||
"settings.timeline.group": "Gruppe",
|
||||
"settings.timeline.collapse": "Kollaps",
|
||||
"settings.timeline.visibility.show": "Vis",
|
||||
"settings.timeline.visibility.hide": "Skjul",
|
||||
"settings.timeline.visibility.label": "{{activity}} synlighed",
|
||||
"settings.timeline.grouped.label": "{{activity}} grupperet",
|
||||
"settings.timeline.collapsed.label": "{{activity}} kollapsede",
|
||||
"session.new.workspace.search.empty": "Ingen matchende arbejdsområder",
|
||||
"settings.workspaces.description": "Gennemgå arbejdsområder og administrer diskbrug",
|
||||
"settings.workspaces.empty.description": "Arbejdstræer oprettet i OpenCode vises her",
|
||||
"settings.workspaces.sessions.filtered.one": "{{count}} session",
|
||||
"settings.workspaces.sessions.filtered.other": "{{count}} sessioner",
|
||||
"settings.workspaces.deleteAll.confirm.one": "Dette vil permanent slette {{count}} valgte arbejdsområde.",
|
||||
"settings.workspaces.deleteAll.confirm.other": "Dette vil permanent slette {{count}} valgte arbejdsområder.",
|
||||
"settings.workspaces.deleteWithoutSessions": "Slet arbejdsområder uden sessioner",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"Dette vil permanent slette {{count}} arbejdsområde uden tilknyttede sessioner.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"Dette vil permanent slette {{count}} arbejdsområder uden linkede sessioner.",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"Arbejdstræer med usammenflettede ændringer eller aktive placeringer bevares.",
|
||||
"settings.workspaces.delete.button": "Slet arbejdsområder",
|
||||
"workspace.lifecycle.deleting": "Sletter...",
|
||||
"session.summary.tooltip": "Resumé",
|
||||
"session.summary.server": "Udvidelser",
|
||||
"session.summary.chooseProject": "Vælg et projekt",
|
||||
"session.summary.mcp.onCreation": "Gælder, når arbejdsområdet er oprettet",
|
||||
"session.summary.mcp.prepareFailed": "Kunne ikke forberede MCP-servere",
|
||||
"session.summary.mcp.unavailable": "MCP-serveren {{name}} er ikke tilgængelig i dette arbejdsområde.",
|
||||
"session.summary.mcp.signInBeforeSend": "Log ind på {{name}}, før du sender prompten.",
|
||||
"session.summary.mcp.notReady": "MCP-serveren {{name}} er ikke klar. Løs dens forbindelse, før du sender prompten.",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "Konfigurerede MCP-servere",
|
||||
"session.summary.plugins": "Plugins",
|
||||
"session.summary.plugins.configured": "Konfigurerede plugins",
|
||||
"session.summary.skills": "Færdigheder",
|
||||
"session.summary.skills.configured": "Konfigurerede færdigheder",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "Mislykkedes",
|
||||
"session.summary.retry": "Prøv igen",
|
||||
"session.summary.connecting": "Opretter forbindelse...",
|
||||
"session.summary.needsAuth": "Log ind påkrævet",
|
||||
"session.summary.configure": "Konfigurationsfil",
|
||||
"session.summary.copyConfigPath": "Kopiér konfigurationsfilstien",
|
||||
"session.summary.configFileMissing": "Ingen konfigurationsfil fundet",
|
||||
"session.summary.mcp.empty": "Ingen MCP-servere konfigureret",
|
||||
"session.summary.mcp.add": "Tilføj servere i opencode.json",
|
||||
"session.summary.plugins.manage": "Administrer plugins i opencode.json",
|
||||
"session.summary.plugins.empty": "Ingen plugins konfigureret",
|
||||
"session.summary.plugins.add": "Tilføj plugins i opencode.json",
|
||||
"session.summary.skills.manage": "Administrer færdigheder i opencode.json",
|
||||
"session.summary.skills.empty": "Ingen færdigheder konfigureret",
|
||||
"session.summary.skills.add": "Tilføj færdigheder i opencode.json",
|
||||
"session.summary.lsp.configured": "Konfigureret LSPs",
|
||||
"session.summary.lsp.empty": "Ingen LSP-servere konfigureret",
|
||||
"session.summary.lsp.manage": "Administrer LSP i opencode.json",
|
||||
"workspace.delete.location": "Beliggenhed",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"Arbejdsområder med ikke-flettede ændringer, tilknyttede sessioner eller aktive placeringer bevares.",
|
||||
"provider.connect.error.unsupportedFields": "Denne godkendelsesformular indeholder felter, der ikke understøttes",
|
||||
"session.review.filesChangedCount.one": "{{count}} fil ændret",
|
||||
"session.review.filesChangedCount.other": "{{count}} filer ændret",
|
||||
"settings.about.writtenByNames": "Skrevet af {{names}}",
|
||||
"settings.about.illustratedByNames": "Illustreret af {{names}}",
|
||||
"home.projects.all": "Alle projekter",
|
||||
"session.tab.files": "Filer",
|
||||
"session.files.openTabs": "Åbne filer",
|
||||
"session.tab.usage": "Brug",
|
||||
"session.view.select": "Sessionsvisning",
|
||||
"session.background.moveTasks": "Flyt {{tasks}} til baggrunden",
|
||||
"session.background.moveRunning": "Flyt til baggrunden",
|
||||
"session.background.inBackground": "Kører {{tasks}} i baggrunden",
|
||||
"session.background.tasksRunning.one": "{{count}} baggrundsopgave kører",
|
||||
"session.background.tasksRunning.other": "{{count}} baggrundsopgaver kører",
|
||||
"session.background.combine": "{{first}} og {{second}}",
|
||||
"session.background.shell.one": "{{count}} shell",
|
||||
"session.background.shell.other": "{{count}} shells",
|
||||
"session.background.subagent.one": "{{count}} underagent",
|
||||
"session.background.subagent.other": "{{count}} underagenter",
|
||||
"session.timeline.working": "Arbejder",
|
||||
"session.review.wrapLines": "Ombryd linjer",
|
||||
"session.websearch.title": "Websøgning fra tredjepart",
|
||||
"session.websearch.description": "Vælg den søgeudbyder, som agenter bruger til at søge på nettet",
|
||||
"session.websearch.provider": "Søgeudbyder",
|
||||
"session.websearch.any": "Alle",
|
||||
"session.websearch.disable": "Brug ikke søgning",
|
||||
"session.websearch.enable": "Aktivér",
|
||||
"session.websearch.loadFailed": "Søgeudbydere kunne ikke indlæses.",
|
||||
"session.websearch.empty": "Ingen søgeudbydere er tilgængelige.",
|
||||
"session.websearch.failed": "Dit valg kunne ikke gemmes. Prøv igen.",
|
||||
"session.websearch.retry": "Prøv igen",
|
||||
"session.new.worktree.draftPlaceholder": "Skriv en opfølgning, mens worktree'et klargøres…",
|
||||
"session.search.placeholder": "Find...",
|
||||
"session.search.noResults": "Ingen resultater",
|
||||
"titlebar.tabs": "Faner",
|
||||
"titlebar.channel.local": "Lokal",
|
||||
"titlebar.channel.dev": "Dev",
|
||||
"titlebar.channel.beta": "Beta",
|
||||
"titlebar.toggleDebugTools": "Slå fejlfindingsværktøjer til/fra",
|
||||
"settings.tab.experimental": "Eksperimentel",
|
||||
"settings.experimental.description": "Prøv eksperimentelle funktioner",
|
||||
"settings.tab.about": "Om",
|
||||
"settings.about.version": "Version {{version}}",
|
||||
"settings.about.devVersion": "udvikling",
|
||||
"settings.about.license": "Udgivet under MIT-licensen",
|
||||
"settings.about.writtenBy": "Skrevet af",
|
||||
"settings.about.illustratedBy": "Illustreret af",
|
||||
"settings.about.and": "og",
|
||||
"settings.about.otherContributor.one": "{{count}} anden",
|
||||
"settings.about.otherContributor.other": "{{count}} andre",
|
||||
"settings.about.firstPublished": "Først udgivet i Missouri, USA",
|
||||
"settings.about.firstIllustrated": "Først illustreret i London, England",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode, open source-kodningsagenten",
|
||||
"settings.about.trademark": "OpenCode er et registreret varemærke tilhørende Anomaly Innovations, Inc.",
|
||||
"settings.about.typeset": "Sat med Inter og IBM Plex Mono",
|
||||
"settings.about.tagline": "AI kan ikke bygge fantastisk software uden dig",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "Rediger projekt",
|
||||
"settings.timeline.title": "Tidslinje",
|
||||
"settings.timeline.detail": "Tidslinjedetaljer",
|
||||
"settings.timeline.description": "Vælg, hvor meget aktivitet der vises på tidslinjen. Beskeder forbliver synlige.",
|
||||
"settings.timeline.preset.everything": "Alt",
|
||||
"settings.timeline.preset.detailed": "Detaljeret",
|
||||
"settings.timeline.preset.compact": "Kompakt",
|
||||
"settings.timeline.preset.quiet": "Stille",
|
||||
"settings.timeline.preset.text-only": "Kun tekst",
|
||||
"settings.timeline.description.everything": "Vis al aktivitet separat. Udvid shell-output, redigeringer og tænkning.",
|
||||
"settings.timeline.description.detailed":
|
||||
"Udvid shell-output og redigeringer. Vis underagenter separat, og gruppér anden aktivitet under Brugt.",
|
||||
"settings.timeline.description.compact": "Gruppér al aktivitet under Brugt med detaljer skjult.",
|
||||
"settings.timeline.description.quiet": "Gruppér redigeringer og underagenter under Brugt. Skjul anden aktivitet.",
|
||||
"settings.timeline.description.text-only": "Skjul al aktivitet. Vis kun beskeder.",
|
||||
"settings.timeline.description.custom":
|
||||
"Brug den valgte placering og de valgte detaljer for hver aktivitetskategori.",
|
||||
"settings.timeline.custom": "Tilpasset",
|
||||
"settings.timeline.advanced": "Avanceret",
|
||||
"settings.timeline.advanced.description": "Angiv placering og detaljer for hver aktivitetskategori.",
|
||||
"settings.timeline.category.shell": "Shell",
|
||||
"settings.timeline.category.edit": "Redigeringer",
|
||||
"settings.timeline.category.thinking": "Tænkning",
|
||||
"settings.timeline.category.subagents": "Underagenter",
|
||||
"settings.timeline.category.notices": "Meddelelser",
|
||||
"settings.timeline.category.tools": "Andre værktøjer",
|
||||
"settings.general.row.mobileDiffWrap.description": "Ombryd lange linjer i mobile diffs i stedet for at rulle vandret",
|
||||
"toast.migration.progress.clearingOldEvents": "Rydder gamle hændelser",
|
||||
"toast.migration.progress.migratingSessions": "Migrerer sessioner",
|
||||
"session.new.workspace.existingLabel": "Worktree",
|
||||
"desktop.onboarding.defaultProject": "Standardprojekt",
|
||||
"session.location.unavailable": "Sessionens placering er ikke tilgængelig",
|
||||
"session.location.description": "Vælg en anden mappe for at fortsætte denne session.",
|
||||
"session.location.choose": "Vælg mappe",
|
||||
"session.location.worktree": "Vælg worktree",
|
||||
"session.location.worktreesFailed": "Kunne ikke indlæse worktrees",
|
||||
"session.location.moving": "Flytter session…",
|
||||
"dialog.server.menu.hide": "Skjul på projektlisten",
|
||||
"dialog.server.menu.show": "Vis på projektlisten",
|
||||
"session.queue.count.one": "{{count}} i kø",
|
||||
"session.queue.count.other": "{{count}} i kø",
|
||||
"session.queue.steer": "Styr",
|
||||
"session.queue.send": "Send",
|
||||
"session.queue.steerTooltip": "Send uden at afbryde",
|
||||
"session.queue.remove": "Fjern",
|
||||
"session.queue.reorder": "Omarranger prompt i køen",
|
||||
"session.new.worktree.creating": "Opretter worktree",
|
||||
"settings.backToApp": "Tilbage til appen",
|
||||
"settings.appearance.section.experimental": "Eksperimentelt",
|
||||
"settings.appearance.row.tabs.title": "Faner",
|
||||
"settings.appearance.row.tabs.description": "Vælg, hvordan sessionsfaner arrangeres",
|
||||
"settings.appearance.row.tabs.horizontal": "Vandret",
|
||||
"settings.appearance.row.tabs.vertical": "Lodret",
|
||||
"settings.general.row.followUpBehavior.title": "Håndtering af opfølgninger",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"Vælg, om opfølgninger skal sættes i kø eller styre den aktuelle tur. Brug {{keybind}} til at skifte.",
|
||||
"settings.general.row.followUpBehavior.queue": "Sæt i kø",
|
||||
"settings.general.row.followUpBehavior.steer": "Styr",
|
||||
"settings.general.row.reasoningMode.title": "Modellens ræsonnering",
|
||||
"settings.general.row.reasoningMode.description": "Vælg, hvordan modellens ræsonnering vises på tidslinjen",
|
||||
"settings.general.row.reasoningMode.hidden": "Skjult",
|
||||
"settings.general.row.reasoningMode.compact": "Kompakt",
|
||||
"settings.general.row.reasoningMode.full": "Fuld",
|
||||
"session.new.workspace.createFrom": "Opret fra gren",
|
||||
"session.new.workspace.branch.search.placeholder": "Søg efter grene",
|
||||
"command.category.suggested": "Foreslået",
|
||||
"command.category.view": "Vis",
|
||||
"command.category.project": "Projekt",
|
||||
@@ -1180,4 +1504,136 @@ export const dict = {
|
||||
"desktop.picker.error.sizeLimit": "De valgte vedhæftede filer overskrider grænsen på {{limit}} MB",
|
||||
|
||||
"command.logs.export": "Eksportér logfiler",
|
||||
|
||||
"provider.disconnect.toast.noCredentials.description":
|
||||
"Der blev ikke fundet nogen flytbare legitimationsoplysninger for {{provider}}.",
|
||||
"provider.disconnect.toast.failed.description": "Kunne ikke afbryde {{provider}}.",
|
||||
"toast.migration.failed.title": "Datamigrering mislykkedes",
|
||||
"command.session.background": "Flyt til baggrunden",
|
||||
"session.timeline.notice.finished": "{{actor}} færdig",
|
||||
"session.timeline.notice.failed": "{{actor}} mislykkedes",
|
||||
"session.timeline.notice.cancelled": "{{actor}} annulleret",
|
||||
"settings.tab.preferences": "Præferencer",
|
||||
"settings.tab.notifications": "Meddelelser",
|
||||
"settings.tab.projects": "Projekter",
|
||||
"settings.tab.extensions": "Udvidelser",
|
||||
"settings.preferences.description": "Tilpas præferencer og tema og standardadfærd",
|
||||
"settings.appearance.description": "Tilpas tema og skrifttyper",
|
||||
"settings.notifications.description": "Vælg, hvornår du vil modtage notifikationer og høre lyde",
|
||||
"settings.shortcuts.description": "Tilpas genveje til almindelige handlinger",
|
||||
"settings.servers.description": "Administrer serverforbindelser",
|
||||
"settings.projects.title": "Projekter",
|
||||
"settings.projects.description": "Administrer projektindstillinger på denne server",
|
||||
"settings.projects.empty": "Ingen projekter fundet",
|
||||
"settings.projects.server.all": "Alle servere",
|
||||
"settings.mcps.description": "Administrer Model Context Protocol (MCP) servere og værktøjer",
|
||||
"settings.extensions.description": "Administrer udvidelser, der er tilgængelige på denne server",
|
||||
"settings.extensions.tab.mcps": "MCP'er",
|
||||
"settings.extensions.tab.skills": "Færdigheder",
|
||||
"settings.extensions.availableAll": "Tilgængelig til alle projekter",
|
||||
"settings.extensions.manageConfig": "Administrer i opencode.json",
|
||||
"settings.extensions.addSkills": "Sådan tilføjer du færdigheder",
|
||||
"dialog.server.authenticate.title": "Godkend",
|
||||
"project.settings.general.description": "Administrer projektnavn og udseende",
|
||||
"project.settings.scripts": "Scripts",
|
||||
"project.settings.scripts.description": "Konfigurer scripts til dette projekt",
|
||||
"project.settings.extensions.description": "Se tilgængelige udvidelser til dette projekt",
|
||||
"project.settings.extensions.tab.lsps": "LSP'er",
|
||||
"project.settings.extensions.added": "Tilføjet til dette projekt",
|
||||
"project.settings.extensions.shared": "Deles med alle projekter",
|
||||
"project.settings.extensions.lsp.detected": "Detekterede sprogservere",
|
||||
"project.settings.extensions.lsp.description": "Auto-detekteret fra filtyper",
|
||||
"project.settings.extensions.setupRequired": "Opsætning påkrævet",
|
||||
"settings.general.section.general": "Generel",
|
||||
"common.viewAll": "Se alle",
|
||||
"session.new.workspace.local.tooltip": "Brug det aktuelle checkout",
|
||||
"session.new.workspace.new.tooltip": "Opret et isoleret checkout",
|
||||
"session.new.workspace.fromBranch": "fra {{branch}}",
|
||||
"session.new.workspace.trigger.tooltip": "Vælg, hvor sessionen skal køres",
|
||||
"session.new.workspace.search.placeholder": "Søg i arbejdsområder",
|
||||
"settings.tab.workspaces": "Arbejdsrum",
|
||||
"settings.workspaces.filter.all": "Alle projekter",
|
||||
"settings.workspaces.empty": "Ingen arbejdsområder",
|
||||
"settings.workspaces.count.one": "{{count}} arbejdsområde",
|
||||
"settings.workspaces.count.other": "{{count}} arbejdsområder",
|
||||
"settings.workspaces.sessions.one": "{{count}} session i {{project}}",
|
||||
"settings.workspaces.sessions.other": "{{count}}-sessioner i {{project}}",
|
||||
"settings.workspaces.lastActiveSession": "Sidste aktive session",
|
||||
"settings.workspaces.deleteAll": "Slet alle arbejdsområder",
|
||||
"settings.workspaces.delete.warning":
|
||||
"Arbejdsområdets bibliotek og filial vil blive permanent fjernet, inklusive eventuelle ikke-sammenflettede ændringer vist nedenfor.",
|
||||
"settings.workspaces.delete.blocked.active": "Det aktive arbejdsområde kan ikke slettes.",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"Linkede sessioner forbliver, men deres arbejdsmappe vil blive permanent fjernet.",
|
||||
"settings.workspaces.default.title": "Standard miljø",
|
||||
"settings.workspaces.default.description": "Vælg, hvor nye sessioner starter",
|
||||
"settings.workspaces.default.lastUsed": "Sidst brugt pr. projekt",
|
||||
"settings.workspaces.default.local": "Lokal vejviser",
|
||||
"settings.workspaces.default.new": "Nyt arbejdsrum",
|
||||
"workspace.move.title": "Flyt til arbejdsområdet",
|
||||
"workspace.move.menu.title": "Flyt session til",
|
||||
"workspace.move.failed": "Sessionen kunne ikke flyttes",
|
||||
"workspace.lifecycle.creating": "Oprettelse af arbejdsrum",
|
||||
"workspace.lifecycle.created": "Arbejdsområde oprettet",
|
||||
"workspace.lifecycle.starting": "Start session",
|
||||
"workspace.onboarding.title": "Isoler sessioner med arbejdsområder",
|
||||
"workspace.onboarding.description": "Hver får sit eget checkout, så intet forstyrrer dit lokale repository",
|
||||
"workspace.lifecycle.moving": "Flytter til arbejdsområde",
|
||||
"workspace.lifecycle.set": "Arbejdsområde angivet",
|
||||
"session.summary.title": "Session detaljer",
|
||||
"session.summary.noBranch": "Ingen gren",
|
||||
"session.summary.basedOn": "Baseret på {{branch}}",
|
||||
"desktop.menu.installCli": "Installér CLI...",
|
||||
"desktop.cli.installed.title": "CLI installeret",
|
||||
"desktop.cli.installed.message":
|
||||
"CLI installeret i {{path}}\n\nGenstart terminalen for at bruge kommandoen 'opencode2'.",
|
||||
"desktop.cli.failed.title": "Installationen mislykkedes",
|
||||
"desktop.cli.failed.message": "CLI kunne ikke installeres: {{error}}",
|
||||
"command.project.copyID": "Kopier projekt-id",
|
||||
"command.session.copyID": "Kopier sessions-id",
|
||||
"server.row.incompatible":
|
||||
"Denne server kører OpenCode {{version}}, som ikke er kompatibel med denne app. Opgrader den til OpenCode V2 for at fortsætte.",
|
||||
"toast.session.copyID.failed.title": "Sessions-id'et kunne ikke kopieres",
|
||||
"toast.session.copyID.failed.description": "Der opstod en fejl under kopiering af sessions-id'et",
|
||||
"toast.project.copyID.failed.title": "Projekt-id'et kunne ikke kopieres",
|
||||
"toast.project.copyID.failed.description": "Der opstod en fejl under kopiering af projekt-id'et",
|
||||
"error.page.title.status": "Serveranmodningen mislykkedes",
|
||||
"error.page.description.status": "Serveren returnerede et HTTP {{status}}-svar.",
|
||||
"error.page.action.reload": "Genindlæs",
|
||||
"session.error.incompatible": "Denne serverversion understøttes ikke",
|
||||
"session.error.incompatible.description":
|
||||
"{{server}} kører OpenCode {{version}}, som ikke er kompatibel med denne app. Opgrader serveren til OpenCode V2 for at fortsætte.",
|
||||
"session.background.moveInline": "Tryk på {{keybind}} for at flytte igangværende arbejde til baggrunden",
|
||||
"session.background.running": "Arbejde kører i baggrunden",
|
||||
"session.background.runningCount.one": "{{count}} element kører i baggrunden",
|
||||
"session.background.runningCount.other": "{{count}} elementer kører i baggrunden",
|
||||
"settings.general.row.terminalPlacement.title": "Terminalplacering",
|
||||
"settings.general.row.terminalPlacement.description": "Vælg, hvor terminalen åbnes i sessioner",
|
||||
"settings.general.row.terminalPlacement.side": "Side",
|
||||
"settings.general.row.terminalPlacement.bottom": "Nederst",
|
||||
"command.debugBar.toggle": "Slå fejlfindingslinjen til eller fra",
|
||||
"command.session.location.cycle": "Skift mellem sessionsplaceringer",
|
||||
"dialog.provider.anthropic.note": "Direkte adgang til Claude-modeller via API-nøgle",
|
||||
"provider.connect.title.anthropicProMax": "Log ind med Anthropic",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"prompt.toast.uploading.cancel": "Annuller upload",
|
||||
"prompt.toast.uploading.cancelFile": "Annuller upload af {{filename}}",
|
||||
"prompt.toast.uploadFailed.title": "Upload mislykkedes",
|
||||
"session.browser.empty.title": "Indtast URL",
|
||||
"session.browser.empty.description": "Eller bed om ”Åbn i appbrowseren”",
|
||||
"session.browser.failed.title": "URL-adressen kan ikke nås",
|
||||
"session.browser.failed.description": "Kontrollér URL-adressen og din forbindelse, og prøv igen.",
|
||||
"debugBar.providerAriaLabel": "Diagnosticering af udbyderens ydeevne",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttft.tip": "Tid fra afsendelse af udbyderanmodningen til modellens første output.",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.ttfa.tip": "Tid fra afsendelse af udbyderanmodningen til den første svartekst.",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.tps.tip": "Outputtokens pr. sekund efter modellens første output.",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
"debugBar.e2e.tip": "Tid fra afsendelse af udbyderanmodningen, til dens svarstream sluttede.",
|
||||
"settings.updates.action.download": "Hent OpenCode",
|
||||
"settings.updates.migration.title": "Skift fra Beta til Stabil",
|
||||
"settings.updates.migration.description":
|
||||
"OpenCode Beta flyttes indtil videre til OpenCode Stabil. Download version {{version}}, og installer derefter OpenCode fra diskaftrykket for fortsat at modtage opdateringer.",
|
||||
}
|
||||
|
||||
@@ -3,6 +3,349 @@ import en from "./en"
|
||||
type Keys = keyof typeof en
|
||||
|
||||
export const dict = {
|
||||
"common.color.orange": "orange",
|
||||
"common.color.yellow": "gelb",
|
||||
"common.color.cyan": "cyan",
|
||||
"common.color.green": "grün",
|
||||
"common.color.red": "rot",
|
||||
"common.color.pink": "rosa",
|
||||
"common.color.blue": "blau",
|
||||
"common.color.purple": "lila",
|
||||
"common.color.gray": "grau",
|
||||
"toast.migration.progress.migratingSessions.current": "Sitzungen werden migriert: {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "Sitzungen werden migriert: {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "Daten werden migriert",
|
||||
"toast.migration.progress.working.current": "Daten werden migriert: {{current}}",
|
||||
"toast.migration.progress.working.progress": "Daten werden migriert: {{current}}/{{total}}",
|
||||
"session.browser.unsupported": "Diese Desktop-App unterstützt den Browserbereich nicht.",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline":
|
||||
"Nicht mit {{host}} verbunden. Ihr Entwurf bleibt erhalten; Möglicherweise läuft die Remote-Arbeit noch.",
|
||||
"ssh.placeholder": "ssh user@example.com",
|
||||
"ssh.add": "Fügen Sie den SSH-Server hinzu",
|
||||
"ssh.server.menu.label": "SSH-Server",
|
||||
"ssh.target": "Host- oder SSH-Befehl",
|
||||
"ssh.connect": "Verbinden",
|
||||
"ssh.connectTo": "An {{host}} anschließen",
|
||||
"ssh.authenticate": "SSH-Authentifizierung",
|
||||
"ssh.action.authenticate": "Authentifizieren",
|
||||
"ssh.session.disconnected": "SSH-Verbindung inaktiv",
|
||||
"ssh.session.connecting": "Verbindung zum SSH-Server herstellen",
|
||||
"ssh.session.reconnectDescription":
|
||||
"Stellen Sie die Verbindung wieder her, um diese Sitzung anzuzeigen und mit der Arbeit fortzufahren. Ihre Remote-Sitzung bleibt erhalten.",
|
||||
"ssh.session.reconnect": "Wieder verbinden",
|
||||
"ssh.authenticationRequired": "Für {{host}} ist eine Authentifizierung erforderlich",
|
||||
"ssh.trust": "Vertrauen und verbinden",
|
||||
"ssh.continue": "Weiter",
|
||||
"ssh.retry": "Versuchen Sie es noch einmal",
|
||||
"ssh.update": "Aktualisieren und erneut verbinden",
|
||||
"ssh.openProject": "Projekt öffnen",
|
||||
"ssh.project": "Projekt auf {{host}} öffnen",
|
||||
"ssh.disconnect": "Trennen",
|
||||
"ssh.forget": "Vergiss die Verbindung",
|
||||
"ssh.stage.disconnected": "Nicht verbunden. Der Remote-Server bleibt aktiv.",
|
||||
"ssh.stage.connecting": "Verbindung über SSH…",
|
||||
"ssh.stage.checking": "Überprüfung OpenCode…",
|
||||
"ssh.stage.downloading": "Server wird heruntergeladen…",
|
||||
"ssh.stage.uploading": "Server wird hochgeladen…",
|
||||
"ssh.stage.starting": "Verbindung mit OpenCode herstellen…",
|
||||
"ssh.stage.ready": "Verbunden",
|
||||
"ssh.stage.authentication": "Authentifizierung erforderlich",
|
||||
"ssh.stage.incompatible": "Server-Update erforderlich",
|
||||
"ssh.stage.failed": "Verbindung fehlgeschlagen",
|
||||
"ssh.error.input":
|
||||
"Geben Sie einen Host- oder SSH-Verbindungsbefehl ein. Fernbefehle und nicht unterstützte SSH-Optionen sind nicht zulässig.",
|
||||
"ssh.error.connection":
|
||||
"Die SSH-Verbindung konnte nicht hergestellt werden. Überprüfen Sie Ihr Netzwerk und die SSH-Konfiguration.",
|
||||
"ssh.error.platform":
|
||||
"Diese Remote-Plattform wird nicht unterstützt. Für die automatische Einrichtung ist derzeit Linux oder macOS auf x64 oder arm64 erforderlich.",
|
||||
"ssh.error.version": "Der Remote-Dienst muss vor der Verbindung mit dieser Desktop-Version übereinstimmen.",
|
||||
"ssh.error.install":
|
||||
"Der Remote-Server konnte nicht installiert werden. Überprüfen Sie die Konnektivität, den Speicherplatz und ob tar installiert ist.",
|
||||
"ssh.error.unpublished":
|
||||
"Diese Desktop-Version verfügt über keinen veröffentlichten Remote-Server. Installieren und starten Sie für Entwicklungs-Builds V2 auf dem Host und versuchen Sie es dann erneut.",
|
||||
"ssh.error.service": "SSH ist verbunden, aber der OpenCode-Server ist nicht bereit.",
|
||||
"ssh.error.host-key":
|
||||
"Die Identität des Hosts konnte nicht überprüft werden. Überprüfen Sie den Fingerabdruck, bevor Sie Ihre bekannten SSH-Hosts aktualisieren.",
|
||||
"ssh.error.ssh-missing":
|
||||
"OpenSSH wurde nicht gefunden. Installieren Sie einen OpenSSH-Client und stellen Sie sicher, dass SSH auf PATH verfügbar ist.",
|
||||
"command.browser.open": "Browser öffnen",
|
||||
"command.browser.reload": "Browserseite neu laden",
|
||||
"command.session.summary.toggle": "Zusammenfassung umschalten",
|
||||
"mcp.auth.interactiveForm": "Der MCP-Server {{name}} erfordert ein interaktives Authentifizierungsformular",
|
||||
"server.connect.title": "Stellen Sie eine Verbindung zu einem Server her",
|
||||
"server.connect.description": "Geben Sie Ihre Serveradresse und Ihr Passwort ein, um zu beginnen.",
|
||||
"server.connect.button": "Verbinden",
|
||||
"server.connect.address.invalid": "Geben Sie eine gültige HTTP- oder HTTPS-Serveradresse ein.",
|
||||
"server.connect.failed":
|
||||
"Es konnte keine Verbindung hergestellt werden. Überprüfen Sie die Serveradresse und das Passwort und versuchen Sie es dann erneut.",
|
||||
"server.connect.pair.description":
|
||||
"Führen Sie diesen Befehl auf Ihrem Computer aus, um Ihre Verbindungsdetails abzurufen.",
|
||||
"server.connect.scan": "Scannen Sie den QR-Code",
|
||||
"server.connect.scan.description": "Richten Sie Ihre Kamera auf den von opencode pair angezeigten Code QR.",
|
||||
"server.connect.scan.invalid":
|
||||
"Dies ist kein OpenCode-Pairing-Code. Scannen Sie den von opencode pair angezeigten Code.",
|
||||
"server.connect.camera": "Kamera koppeln",
|
||||
"server.connect.camera.starting": "Kamera wird geöffnet…",
|
||||
"server.connect.mixedContent":
|
||||
"Es konnte keine Verbindung zu diesem HTTP-Server von einer HTTPS-Seite hergestellt werden. Verwenden Sie stattdessen eine HTTPS-Serveradresse.",
|
||||
"server.connect.camera.insecure":
|
||||
"Zum Scannen mit QR muss diese Seite über HTTPS oder auf localhost geöffnet werden.",
|
||||
"server.connect.camera.unavailable":
|
||||
"Für diesen Browser ist keine Kamera verfügbar. Geben Sie Ihre Verbindungsdaten manuell ein.",
|
||||
"server.connect.camera.error":
|
||||
"Die Kamera konnte nicht geöffnet werden. Erlauben Sie den Kamerazugriff oder geben Sie Ihre Verbindungsdaten manuell ein.",
|
||||
"dialog.server.menu.remove": "Entfernen",
|
||||
"file.error.notFound": "Datei nicht gefunden: {{name}}",
|
||||
"home.workspaceTip":
|
||||
"Starten Sie die nächste Sitzung in einem neuen Arbeitsbereich, um Änderungen isoliert zu halten",
|
||||
"session.tab.browser": "Browser",
|
||||
"session.tab.add": "Registerkarte hinzufügen",
|
||||
"session.queue.attachments.one": "Plus {{count}}-Aufsatz",
|
||||
"session.queue.attachments.other": "Plus {{count}}-Anbaugeräte",
|
||||
"session.browser.address": "Browseradresse",
|
||||
"session.browser.replaced": "Die Browsersteuerung wurde in ein anderes Desktop-Fenster verschoben.",
|
||||
"session.browser.suspended":
|
||||
"Browser angehalten. Interagieren Sie mit dieser Sitzung, um die Verbindung wiederherzustellen.",
|
||||
"session.browser.address.placeholder": "Geben Sie URL ein",
|
||||
"settings.backToSettings": "Zurück zu den Einstellungen",
|
||||
"settings.backToProjects": "Zurück zu Projekten",
|
||||
"settings.search.placeholder": "Suchen",
|
||||
"settings.search.results": "Einstellungsergebnisse",
|
||||
"settings.search.group.pages": "Seiten",
|
||||
"settings.search.group.settings": "Einstellungen",
|
||||
"settings.search.group.projects": "Projekte",
|
||||
"settings.search.group.servers": "Server",
|
||||
"settings.search.result": "{{title}}, {{scope}}, {{page}}",
|
||||
"settings.search.page": "{{title}}, {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}, {{page}}",
|
||||
"settings.search.empty": "Keine Ergebnisse für {{query}}",
|
||||
"settings.search.empty.query": "„{{query}}“",
|
||||
"settings.search.refine": "Grenzen Sie Ihre Suche ein, um spezifischere Ergebnisse anzuzeigen.",
|
||||
"settings.server.description": "Verwalten Sie die Verbindung und Einstellungen dieses Servers",
|
||||
"settings.server.section.connection": "Verbindung",
|
||||
"settings.server.preferences.websearch.title": "Suche durch Dritte",
|
||||
"settings.server.preferences.websearch.description":
|
||||
"Wählen Sie den Suchanbieter aus, den Agenten zum Durchsuchen des Webs verwenden",
|
||||
"settings.projects.search.placeholder": "Projekte suchen",
|
||||
"project.settings.name.title": "Projektname",
|
||||
"project.settings.name.description": "Der für dieses Projekt durchgehend angezeigte Name OpenCode",
|
||||
"project.settings.icon.description": "Empfohlen: 128×128px. Klicken oder ziehen Sie, um ein Bild hochzuladen.",
|
||||
"project.settings.color.description":
|
||||
"Wird für das Projektsymbol verwendet, wenn kein benutzerdefiniertes Bild festgelegt ist",
|
||||
"project.settings.worktree.startup.description":
|
||||
"Wird einmal ausgeführt, nachdem ein neuer Arbeitsbereich erstellt wurde",
|
||||
"project.settings.worktree.startup.hint.base": "Verwenden Sie $OPENCODE_WORKTREE_BASE für den Basisarbeitsbaum.",
|
||||
"project.settings.worktree.startup.hint.new": "Verwenden Sie $OPENCODE_WORKTREE_PATH für den neuen Arbeitsbereich.",
|
||||
"project.settings.extensions.empty.mcps.title": "Noch kein MCPs",
|
||||
"project.settings.extensions.empty.mcps.description": "MCPs verfügbar für OpenCode wird hier angezeigt",
|
||||
"project.settings.extensions.empty.plugins.title": "Noch keine Plugins",
|
||||
"project.settings.extensions.empty.plugins.description": "Für OpenCode verfügbare Plugins werden hier angezeigt",
|
||||
"project.settings.extensions.empty.skills.title": "Noch keine Fähigkeiten",
|
||||
"project.settings.extensions.empty.skills.description":
|
||||
"Hier werden die für OpenCode verfügbaren Fähigkeiten angezeigt",
|
||||
"project.settings.extensions.lsp.configured": "Konfigurierte Sprachserver",
|
||||
"project.settings.extensions.lsp.status.enabled": "In der Konfiguration aktiviert",
|
||||
"project.settings.extensions.lsp.status.disabled": "In der Konfiguration deaktiviert",
|
||||
"project.settings.extensions.lsp.empty.title": "Keine Sprachserver konfiguriert",
|
||||
"project.settings.extensions.lsp.empty.description":
|
||||
"Hier werden die für dieses Projekt konfigurierten Sprachserver angezeigt",
|
||||
"project.settings.extensions.lsp.disabled.title": "Sprachserver deaktiviert",
|
||||
"project.settings.extensions.lsp.disabled.description": "LSP ist in der Konfiguration dieses Projekts deaktiviert",
|
||||
"project.settings.extensions.lsp.loadFailed": "Die Sprachserverkonfiguration konnte nicht geladen werden",
|
||||
"project.settings.extensions.lsp.retry": "Versuchen Sie es noch einmal",
|
||||
"settings.timeline.summary": "{{preset}}:",
|
||||
"settings.timeline.group": "Gruppe",
|
||||
"settings.timeline.collapse": "Zusammenbruch",
|
||||
"settings.timeline.visibility.show": "Zeigen",
|
||||
"settings.timeline.visibility.hide": "Verstecken",
|
||||
"settings.timeline.visibility.label": "{{activity}} Sichtbarkeit",
|
||||
"settings.timeline.grouped.label": "{{activity}} gruppiert",
|
||||
"settings.timeline.collapsed.label": "{{activity}} ist zusammengebrochen",
|
||||
"session.new.workspace.search.empty": "Keine passenden Arbeitsbereiche",
|
||||
"settings.workspaces.description": "Überprüfen Sie Arbeitsbereiche und verwalten Sie die Festplattennutzung",
|
||||
"settings.workspaces.empty.description": "In OpenCode erstellte Arbeitsbereiche werden hier angezeigt",
|
||||
"settings.workspaces.sessions.filtered.one": "{{count}}-Sitzung",
|
||||
"settings.workspaces.sessions.filtered.other": "{{count}}-Sitzungen",
|
||||
"settings.workspaces.deleteAll.confirm.one":
|
||||
"Dadurch wird der ausgewählte {{count}}-Arbeitsbereich dauerhaft gelöscht.",
|
||||
"settings.workspaces.deleteAll.confirm.other":
|
||||
"Dadurch werden die ausgewählten {{count}}-Arbeitsbereiche dauerhaft gelöscht.",
|
||||
"settings.workspaces.deleteWithoutSessions": "Arbeitsbereiche ohne Sitzungen löschen",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"Dadurch wird der {{count}}-Arbeitsbereich ohne verknüpfte Sitzungen dauerhaft gelöscht.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"Dadurch werden {{count}}-Arbeitsbereiche ohne verknüpfte Sitzungen dauerhaft gelöscht.",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"Arbeitsbereiche mit nicht zusammengeführten Änderungen oder aktiven Standorten bleiben erhalten.",
|
||||
"settings.workspaces.delete.button": "Arbeitsbereiche löschen",
|
||||
"workspace.lifecycle.deleting": "Löschen…",
|
||||
"session.summary.tooltip": "Zusammenfassung",
|
||||
"session.summary.server": "Erweiterungen",
|
||||
"session.summary.chooseProject": "Wählen Sie ein Projekt",
|
||||
"session.summary.mcp.onCreation": "Gilt, wenn der Arbeitsbereich erstellt wird",
|
||||
"session.summary.mcp.prepareFailed": "MCP-Server konnten nicht vorbereitet werden",
|
||||
"session.summary.mcp.unavailable": "Der MCP-Server {{name}} ist in diesem Arbeitsbereich nicht verfügbar.",
|
||||
"session.summary.mcp.signInBeforeSend": "Melden Sie sich bei {{name}} an, bevor Sie die Aufforderung senden.",
|
||||
"session.summary.mcp.notReady":
|
||||
"MCP-Server {{name}} ist nicht bereit. Lösen Sie die Verbindung, bevor Sie die Eingabeaufforderung senden.",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "Konfigurierte MCP-Server",
|
||||
"session.summary.plugins": "Plugins",
|
||||
"session.summary.plugins.configured": "Konfigurierte Plugins",
|
||||
"session.summary.skills": "Fähigkeiten",
|
||||
"session.summary.skills.configured": "Konfigurierte Fähigkeiten",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "Fehlgeschlagen",
|
||||
"session.summary.retry": "Versuchen Sie es noch einmal",
|
||||
"session.summary.connecting": "Verbinden…",
|
||||
"session.summary.needsAuth": "Anmeldung erforderlich",
|
||||
"session.summary.configure": "Konfigurationsdatei",
|
||||
"session.summary.copyConfigPath": "Pfad der Konfigurationsdatei kopieren",
|
||||
"session.summary.configFileMissing": "Keine Konfigurationsdatei gefunden",
|
||||
"session.summary.mcp.empty": "Keine MCP-Server konfiguriert",
|
||||
"session.summary.mcp.add": "Fügen Sie Server in opencode.json hinzu",
|
||||
"session.summary.plugins.manage": "Verwalten Sie Plugins in opencode.json",
|
||||
"session.summary.plugins.empty": "Keine Plugins konfiguriert",
|
||||
"session.summary.plugins.add": "Fügen Sie Plugins in opencode.json hinzu",
|
||||
"session.summary.skills.manage": "Verwalten Sie Fähigkeiten in opencode.json",
|
||||
"session.summary.skills.empty": "Keine Fähigkeiten konfiguriert",
|
||||
"session.summary.skills.add": "Fügen Sie Fähigkeiten in opencode.json hinzu",
|
||||
"session.summary.lsp.configured": "Konfiguriert LSPs",
|
||||
"session.summary.lsp.empty": "Keine LSP-Server konfiguriert",
|
||||
"session.summary.lsp.manage": "Verwalten Sie LSP in opencode.json",
|
||||
"workspace.delete.location": "Standort",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"Arbeitsbereiche mit nicht zusammengeführten Änderungen, verknüpften Sitzungen oder aktiven Speicherorten bleiben erhalten.",
|
||||
"provider.connect.error.unsupportedFields": "Dieses Authentifizierungsformular enthält nicht unterstützte Felder",
|
||||
"session.review.filesChangedCount.one": "{{count}} Datei geändert",
|
||||
"session.review.filesChangedCount.other": "{{count}} Dateien geändert",
|
||||
"settings.about.writtenByNames": "Geschrieben von {{names}}",
|
||||
"settings.about.illustratedByNames": "Illustriert von {{names}}",
|
||||
"home.projects.all": "Alle Projekte",
|
||||
"session.tab.files": "Dateien",
|
||||
"session.files.openTabs": "Geöffnete Dateien",
|
||||
"session.tab.usage": "Nutzung",
|
||||
"session.view.select": "Sitzungsansicht",
|
||||
"session.background.moveTasks": "{{tasks}} in den Hintergrund verschieben",
|
||||
"session.background.moveRunning": "In den Hintergrund verschieben",
|
||||
"session.background.inBackground": "{{tasks}} werden im Hintergrund ausgeführt",
|
||||
"session.background.tasksRunning.one": "{{count}} Hintergrundaufgabe wird ausgeführt",
|
||||
"session.background.tasksRunning.other": "{{count}} Hintergrundaufgaben werden ausgeführt",
|
||||
"session.background.combine": "{{first}} und {{second}}",
|
||||
"session.background.shell.one": "{{count}} Shell",
|
||||
"session.background.shell.other": "{{count}} Shells",
|
||||
"session.background.subagent.one": "{{count}} Unteragent",
|
||||
"session.background.subagent.other": "{{count}} Unteragenten",
|
||||
"session.timeline.working": "In Arbeit",
|
||||
"session.review.wrapLines": "Zeilen umbrechen",
|
||||
"session.websearch.title": "Websuche von Drittanbietern",
|
||||
"session.websearch.description": "Wählen Sie den Suchanbieter aus, den Agenten für die Websuche verwenden",
|
||||
"session.websearch.provider": "Suchanbieter",
|
||||
"session.websearch.any": "Beliebig",
|
||||
"session.websearch.disable": "Suche nicht verwenden",
|
||||
"session.websearch.enable": "Aktivieren",
|
||||
"session.websearch.loadFailed": "Suchanbieter konnten nicht geladen werden.",
|
||||
"session.websearch.empty": "Keine Suchanbieter verfügbar.",
|
||||
"session.websearch.failed": "Ihre Auswahl konnte nicht gespeichert werden. Versuchen Sie es erneut.",
|
||||
"session.websearch.retry": "Erneut versuchen",
|
||||
"session.new.worktree.draftPlaceholder": "Verfassen Sie eine Folgenachricht, während der Worktree vorbereitet wird…",
|
||||
"session.search.placeholder": "Suchen...",
|
||||
"session.search.noResults": "Keine Treffer",
|
||||
"titlebar.tabs": "Tabs",
|
||||
"titlebar.channel.local": "Lokal",
|
||||
"titlebar.channel.dev": "Dev",
|
||||
"titlebar.channel.beta": "Beta",
|
||||
"titlebar.toggleDebugTools": "Debugging-Tools umschalten",
|
||||
"settings.tab.experimental": "Experimentell",
|
||||
"settings.experimental.description": "Experimentelle Funktionen ausprobieren",
|
||||
"settings.tab.about": "Über",
|
||||
"settings.about.version": "Version {{version}}",
|
||||
"settings.about.devVersion": "Entwicklung",
|
||||
"settings.about.license": "Unter der MIT-Lizenz veröffentlicht",
|
||||
"settings.about.writtenBy": "Geschrieben von",
|
||||
"settings.about.illustratedBy": "Illustriert von",
|
||||
"settings.about.and": "und",
|
||||
"settings.about.otherContributor.one": "{{count}} weiterer",
|
||||
"settings.about.otherContributor.other": "{{count}} weitere",
|
||||
"settings.about.firstPublished": "Erstmals veröffentlicht in Missouri, USA",
|
||||
"settings.about.firstIllustrated": "Erstmals illustriert in London, England",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode, der Open-Source-Coding-Agent",
|
||||
"settings.about.trademark": "OpenCode ist eine eingetragene Marke von Anomaly Innovations, Inc.",
|
||||
"settings.about.typeset": "Gesetzt in Inter und IBM Plex Mono",
|
||||
"settings.about.tagline": "KI kann ohne Sie keine großartige Software entwickeln",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "Projekt bearbeiten",
|
||||
"settings.timeline.title": "Timeline",
|
||||
"settings.timeline.detail": "Timeline-Detailgrad",
|
||||
"settings.timeline.description":
|
||||
"Wählen Sie aus, wie viele Aktivitäten in der Timeline angezeigt werden. Nachrichten bleiben sichtbar.",
|
||||
"settings.timeline.preset.everything": "Alles",
|
||||
"settings.timeline.preset.detailed": "Detailliert",
|
||||
"settings.timeline.preset.compact": "Kompakt",
|
||||
"settings.timeline.preset.quiet": "Ruhig",
|
||||
"settings.timeline.preset.text-only": "Nur Text",
|
||||
"settings.timeline.description.everything":
|
||||
"Alle Aktivitäten separat anzeigen. Shell-Ausgabe, Bearbeitungen und Gedankengänge ausklappen.",
|
||||
"settings.timeline.description.detailed":
|
||||
"Shell-Ausgabe und Bearbeitungen ausklappen. Unteragenten separat anzeigen und andere Aktivitäten unter Verwendet gruppieren.",
|
||||
"settings.timeline.description.compact": "Alle Aktivitäten unter Verwendet gruppieren und Details einklappen.",
|
||||
"settings.timeline.description.quiet":
|
||||
"Bearbeitungen und Unteragenten unter Verwendet gruppieren. Andere Aktivitäten ausblenden.",
|
||||
"settings.timeline.description.text-only": "Alle Aktivitäten ausblenden. Nur Nachrichten anzeigen.",
|
||||
"settings.timeline.description.custom":
|
||||
"Die ausgewählte Platzierung und Detailansicht für jede Aktivitätskategorie verwenden.",
|
||||
"settings.timeline.custom": "Benutzerdefiniert",
|
||||
"settings.timeline.advanced": "Erweitert",
|
||||
"settings.timeline.advanced.description": "Platzierung und Details für jede Aktivitätskategorie festlegen.",
|
||||
"settings.timeline.category.shell": "Shell",
|
||||
"settings.timeline.category.edit": "Bearbeitungen",
|
||||
"settings.timeline.category.thinking": "Gedankengänge",
|
||||
"settings.timeline.category.subagents": "Unteragenten",
|
||||
"settings.timeline.category.notices": "Hinweise",
|
||||
"settings.timeline.category.tools": "Andere Tools",
|
||||
"settings.general.row.mobileDiffWrap.description":
|
||||
"Lange Zeilen in mobilen Diffs umbrechen, statt horizontal zu scrollen",
|
||||
"toast.migration.progress.clearingOldEvents": "Alte Ereignisse werden gelöscht",
|
||||
"toast.migration.progress.migratingSessions": "Sitzungen werden migriert",
|
||||
"session.new.workspace.existingLabel": "Worktree",
|
||||
"desktop.onboarding.defaultProject": "Standardprojekt",
|
||||
"session.location.unavailable": "Sitzungspfad nicht verfügbar",
|
||||
"session.location.description": "Wählen Sie ein anderes Verzeichnis aus, um diese Sitzung fortzusetzen.",
|
||||
"session.location.choose": "Verzeichnis auswählen",
|
||||
"session.location.worktree": "Worktree auswählen",
|
||||
"session.location.worktreesFailed": "Worktrees konnten nicht geladen werden",
|
||||
"session.location.moving": "Sitzung wird verschoben…",
|
||||
"dialog.server.menu.hide": "Aus Projektliste ausblenden",
|
||||
"dialog.server.menu.show": "In Projektliste anzeigen",
|
||||
"session.queue.count.one": "{{count}} in der Warteschlange",
|
||||
"session.queue.count.other": "{{count}} in der Warteschlange",
|
||||
"session.queue.steer": "Steuern",
|
||||
"session.queue.send": "Senden",
|
||||
"session.queue.steerTooltip": "Senden, ohne zu unterbrechen",
|
||||
"session.queue.remove": "Entfernen",
|
||||
"session.queue.reorder": "Prompt in der Warteschlange neu anordnen",
|
||||
"session.new.worktree.creating": "Worktree wird erstellt",
|
||||
"settings.backToApp": "Zurück zur App",
|
||||
"settings.appearance.section.experimental": "Experimentell",
|
||||
"settings.appearance.row.tabs.title": "Tabs",
|
||||
"settings.appearance.row.tabs.description": "Anordnung der Sitzungs-Tabs auswählen",
|
||||
"settings.appearance.row.tabs.horizontal": "Horizontal",
|
||||
"settings.appearance.row.tabs.vertical": "Vertikal",
|
||||
"settings.general.row.followUpBehavior.title": "Verhalten bei Folgenachrichten",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"Wählen Sie, ob Folgenachrichten in die Warteschlange gestellt werden oder die aktuelle Runde steuern. Mit {{keybind}} wechseln.",
|
||||
"settings.general.row.followUpBehavior.queue": "In Warteschlange stellen",
|
||||
"settings.general.row.followUpBehavior.steer": "Steuern",
|
||||
"settings.general.row.reasoningMode.title": "Modell-Reasoning",
|
||||
"settings.general.row.reasoningMode.description":
|
||||
"Wählen Sie, wie das Modell-Reasoning in der Timeline angezeigt wird",
|
||||
"settings.general.row.reasoningMode.hidden": "Ausgeblendet",
|
||||
"settings.general.row.reasoningMode.compact": "Kompakt",
|
||||
"settings.general.row.reasoningMode.full": "Vollständig",
|
||||
"session.new.workspace.createFrom": "Aus Branch erstellen",
|
||||
"session.new.workspace.branch.search.placeholder": "Branches durchsuchen",
|
||||
"command.category.suggested": "Vorgeschlagen",
|
||||
"command.category.view": "Ansicht",
|
||||
"command.category.project": "Projekt",
|
||||
@@ -1117,4 +1460,137 @@ export const dict = {
|
||||
"desktop.picker.error.notSelected": "Im Auswahldialog wurde keine Datei ausgewählt",
|
||||
"desktop.picker.error.sizeLimit": "Die ausgewählten Anhänge überschreiten das Limit von {{limit}} MB",
|
||||
"command.logs.export": "Protokolle exportieren",
|
||||
|
||||
"provider.disconnect.toast.noCredentials.description":
|
||||
"Für {{provider}} wurden keine entfernbaren Anmeldeinformationen gefunden.",
|
||||
"provider.disconnect.toast.failed.description": "{{provider}} konnte nicht getrennt werden.",
|
||||
"toast.migration.failed.title": "Die Datenmigration ist fehlgeschlagen",
|
||||
"command.session.background": "In den Hintergrund wechseln",
|
||||
"session.timeline.notice.finished": "{{actor}} fertig",
|
||||
"session.timeline.notice.failed": "{{actor}} ist fehlgeschlagen",
|
||||
"session.timeline.notice.cancelled": "{{actor}} abgebrochen",
|
||||
"settings.tab.preferences": "Präferenzen",
|
||||
"settings.tab.notifications": "Benachrichtigungen",
|
||||
"settings.tab.projects": "Projekte",
|
||||
"settings.tab.extensions": "Erweiterungen",
|
||||
"settings.preferences.description": "Passen Sie Einstellungen, Design und Standardverhalten an",
|
||||
"settings.appearance.description": "Passen Sie Design und Schriftarten an",
|
||||
"settings.notifications.description": "Wählen Sie aus, wann Sie Benachrichtigungen erhalten und Töne hören möchten",
|
||||
"settings.shortcuts.description": "Passen Sie Verknüpfungen für häufige Aktionen an",
|
||||
"settings.servers.description": "Serververbindungen verwalten",
|
||||
"settings.projects.title": "Projekte",
|
||||
"settings.projects.description": "Projekteinstellungen auf diesem Server verwalten",
|
||||
"settings.projects.empty": "Keine Projekte gefunden",
|
||||
"settings.projects.server.all": "Alle Server",
|
||||
"settings.mcps.description": "Verwalten Sie Model Context Protocol (MCP)-Server und -Tools",
|
||||
"settings.extensions.description": "Verwalten Sie die auf diesem Server verfügbaren Erweiterungen",
|
||||
"settings.extensions.tab.mcps": "MCPs",
|
||||
"settings.extensions.tab.skills": "Fähigkeiten",
|
||||
"settings.extensions.availableAll": "Verfügbar für alle Projekte",
|
||||
"settings.extensions.manageConfig": "Verwalten Sie in opencode.json",
|
||||
"settings.extensions.addSkills": "So fügen Sie Fähigkeiten hinzu",
|
||||
"dialog.server.authenticate.title": "Authentifizieren",
|
||||
"project.settings.general.description": "Verwalten Sie den Namen und das Erscheinungsbild des Projekts",
|
||||
"project.settings.scripts": "Skripte",
|
||||
"project.settings.scripts.description": "Konfigurieren Sie Skripte für dieses Projekt",
|
||||
"project.settings.extensions.description": "Für dieses Projekt verfügbare Erweiterungen anzeigen",
|
||||
"project.settings.extensions.tab.lsps": "LSPs",
|
||||
"project.settings.extensions.added": "Zu diesem Projekt hinzugefügt",
|
||||
"project.settings.extensions.shared": "Mit allen Projekten geteilt",
|
||||
"project.settings.extensions.lsp.detected": "Erkannte Sprachserver",
|
||||
"project.settings.extensions.lsp.description": "Wird anhand der Dateitypen automatisch erkannt",
|
||||
"project.settings.extensions.setupRequired": "Einrichtung erforderlich",
|
||||
"settings.general.section.general": "Allgemein",
|
||||
"common.viewAll": "Alle anzeigen",
|
||||
"session.new.workspace.local.tooltip": "Aktuellen Checkout verwenden",
|
||||
"session.new.workspace.new.tooltip": "Isolierten Checkout erstellen",
|
||||
"session.new.workspace.fromBranch": "von {{branch}}",
|
||||
"session.new.workspace.trigger.tooltip": "Wählen Sie aus, wo die Sitzung ausgeführt werden soll",
|
||||
"session.new.workspace.search.placeholder": "Arbeitsbereiche durchsuchen",
|
||||
"settings.tab.workspaces": "Arbeitsbereiche",
|
||||
"settings.workspaces.filter.all": "Alle Projekte",
|
||||
"settings.workspaces.empty": "Keine Arbeitsbereiche",
|
||||
"settings.workspaces.count.one": "{{count}}-Arbeitsbereich",
|
||||
"settings.workspaces.count.other": "{{count}} Arbeitsbereiche",
|
||||
"settings.workspaces.sessions.one": "{{count}}-Sitzung in {{project}}",
|
||||
"settings.workspaces.sessions.other": "{{count}}-Sitzungen in {{project}}",
|
||||
"settings.workspaces.lastActiveSession": "Letzte aktive Sitzung",
|
||||
"settings.workspaces.deleteAll": "Löschen Sie alle Arbeitsbereiche",
|
||||
"settings.workspaces.delete.warning":
|
||||
"Das Arbeitsbereichsverzeichnis und der Zweig werden dauerhaft entfernt, einschließlich aller unten aufgeführten nicht zusammengeführten Änderungen.",
|
||||
"settings.workspaces.delete.blocked.active": "Der aktive Arbeitsbereich kann nicht gelöscht werden.",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"Verknüpfte Sitzungen bleiben bestehen, ihr Arbeitsverzeichnis wird jedoch dauerhaft entfernt.",
|
||||
"settings.workspaces.default.title": "Standardumgebung",
|
||||
"settings.workspaces.default.description": "Wählen Sie, wo neue Sitzungen beginnen",
|
||||
"settings.workspaces.default.lastUsed": "Zuletzt pro Projekt verwendet",
|
||||
"settings.workspaces.default.local": "Lokales Verzeichnis",
|
||||
"settings.workspaces.default.new": "Neuer Arbeitsbereich",
|
||||
"workspace.move.title": "Wechseln Sie zum Arbeitsbereich",
|
||||
"workspace.move.menu.title": "Sitzung verschieben nach",
|
||||
"workspace.move.failed": "Sitzung konnte nicht verschoben werden",
|
||||
"workspace.lifecycle.creating": "Arbeitsbereich erstellen",
|
||||
"workspace.lifecycle.created": "Arbeitsbereich erstellt",
|
||||
"workspace.lifecycle.starting": "Beginn der Sitzung",
|
||||
"workspace.onboarding.title": "Isolieren Sie Sitzungen mit Arbeitsbereichen",
|
||||
"workspace.onboarding.description":
|
||||
"Jeder erhält seinen eigenen Checkout, sodass Ihr lokales Repository nicht beeinträchtigt wird",
|
||||
"workspace.lifecycle.moving": "In Arbeitsbereich verschieben",
|
||||
"workspace.lifecycle.set": "Arbeitsbereich eingestellt",
|
||||
"session.summary.title": "Sitzungsdetails",
|
||||
"session.summary.noBranch": "Kein Branch",
|
||||
"session.summary.basedOn": "Basierend auf {{branch}}",
|
||||
"desktop.menu.installCli": "CLI installieren...",
|
||||
"desktop.cli.installed.title": "CLI installiert",
|
||||
"desktop.cli.installed.message":
|
||||
"CLI wurde unter {{path}} installiert.\n\nStarten Sie Ihr Terminal neu, um den Befehl 'opencode2' zu verwenden.",
|
||||
"desktop.cli.failed.title": "Installation fehlgeschlagen",
|
||||
"desktop.cli.failed.message": "CLI konnte nicht installiert werden: {{error}}",
|
||||
"command.project.copyID": "Projekt-ID kopieren",
|
||||
"command.session.copyID": "Sitzungs-ID kopieren",
|
||||
"server.row.incompatible":
|
||||
"Auf diesem Server wird OpenCode {{version}} ausgeführt, das mit dieser App nicht kompatibel ist. Aktualisieren Sie ihn auf OpenCode V2, um fortzufahren.",
|
||||
"toast.session.copyID.failed.title": "Sitzungs-ID konnte nicht kopiert werden",
|
||||
"toast.session.copyID.failed.description": "Beim Kopieren der Sitzungs-ID ist ein Fehler aufgetreten",
|
||||
"toast.project.copyID.failed.title": "Projekt-ID konnte nicht kopiert werden",
|
||||
"toast.project.copyID.failed.description": "Beim Kopieren der Projekt-ID ist ein Fehler aufgetreten",
|
||||
"error.page.title.status": "Serveranfrage fehlgeschlagen",
|
||||
"error.page.description.status": "Der Server hat eine HTTP-Antwort mit dem Status {{status}} zurückgegeben.",
|
||||
"error.page.action.reload": "Neu laden",
|
||||
"session.error.incompatible": "Diese Serverversion wird nicht unterstützt",
|
||||
"session.error.incompatible.description":
|
||||
"Auf {{server}} wird OpenCode {{version}} ausgeführt, das mit dieser App nicht kompatibel ist. Aktualisieren Sie den Server auf OpenCode V2, um fortzufahren.",
|
||||
"session.background.moveInline": "Drücken Sie {{keybind}}, um laufende Arbeit in den Hintergrund zu verschieben",
|
||||
"session.background.running": "Arbeit wird im Hintergrund ausgeführt",
|
||||
"session.background.runningCount.one": "{{count}} Element wird im Hintergrund ausgeführt",
|
||||
"session.background.runningCount.other": "{{count}} Elemente werden im Hintergrund ausgeführt",
|
||||
"settings.general.row.terminalPlacement.title": "Terminalposition",
|
||||
"settings.general.row.terminalPlacement.description": "Wählen Sie aus, wo das Terminal in Sitzungen geöffnet wird",
|
||||
"settings.general.row.terminalPlacement.side": "Seitlich",
|
||||
"settings.general.row.terminalPlacement.bottom": "Unten",
|
||||
"command.debugBar.toggle": "Debug-Leiste ein-/ausblenden",
|
||||
"command.session.location.cycle": "Sitzungsort wechseln",
|
||||
"dialog.provider.anthropic.note": "Direkter Zugriff auf Claude-Modelle per API-Schlüssel",
|
||||
"provider.connect.title.anthropicProMax": "Bei Anthropic anmelden",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"prompt.toast.uploading.cancel": "Upload abbrechen",
|
||||
"prompt.toast.uploading.cancelFile": "Upload von {{filename}} abbrechen",
|
||||
"prompt.toast.uploadFailed.title": "Upload fehlgeschlagen",
|
||||
"session.browser.empty.title": "URL eingeben",
|
||||
"session.browser.empty.description": "Oder „Im App-Browser öffnen“ eingeben",
|
||||
"session.browser.failed.title": "URL ist nicht erreichbar",
|
||||
"session.browser.failed.description": "Überprüfen Sie die URL und Ihre Verbindung und versuchen Sie es erneut.",
|
||||
"debugBar.providerAriaLabel": "Leistungsdiagnose des Anbieters",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttft.tip": "Zeit vom Senden der Anbieteranfrage bis zur ersten Modellausgabe.",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.ttfa.tip": "Zeit vom Senden der Anbieteranfrage bis zum ersten Antworttext.",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.tps.tip": "Ausgabetokens pro Sekunde nach der ersten Modellausgabe.",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
"debugBar.e2e.tip": "Zeit vom Senden der Anbieteranfrage bis zum Ende ihres Antwortstreams.",
|
||||
"settings.updates.action.download": "OpenCode herunterladen",
|
||||
"settings.updates.migration.title": "Von Beta zu Stabil wechseln",
|
||||
"settings.updates.migration.description":
|
||||
"OpenCode Beta wird vorerst zu OpenCode Stabil verschoben. Laden Sie Version {{version}} herunter und installieren Sie OpenCode anschließend über das Disk-Image, um weiterhin Updates zu erhalten.",
|
||||
} satisfies Partial<Record<Keys, string>>
|
||||
|
||||
@@ -305,6 +305,7 @@ export const DESKTOP_NATIVE_ENGLISH = {
|
||||
"desktop.dialog.saveFile": "Save file",
|
||||
"desktop.dialog.files": "Files",
|
||||
"desktop.server.local": "Local Server",
|
||||
"desktop.onboarding.defaultProject": "Default Project",
|
||||
|
||||
"desktop.wsl.error.windowsOnly": "WSL is only available on Windows",
|
||||
"desktop.wsl.error.unavailable": "WSL is unavailable",
|
||||
|
||||
+588
-102
@@ -48,7 +48,8 @@ export const dict = {
|
||||
"desktop.updater.dialog.checkFailed.title": "އަޕްޑޭޓް އެރަރ",
|
||||
"desktop.updater.dialog.upToDate.message": "ޔޫ އާ އަޕް ޓު ޑޭޓް.",
|
||||
"desktop.updater.dialog.upToDate.title": "ނޯ އަޕްޑޭޓްސް",
|
||||
"desktop.updater.dialog.ready.message": "އަޕްޑޭޓް {{version}} ޑައުންލޯޑް ކޮށްފިއެވެ. މިހާރު ރީސްޓާޓް ކުރަންތަ؟",
|
||||
"desktop.updater.dialog.ready.message":
|
||||
"އަޕްޑޭޓް \u2068{{version}}\u2069 ޑައުންލޯޑް ކޮށްފިއެވެ. މިހާރު ރީސްޓާޓް ކުރަންތަ؟",
|
||||
"desktop.updater.dialog.ready.title": "އަޕްޑޭޓް ރެޑީ",
|
||||
"desktop.updater.dialog.restart": "އަލުން ފަށާށެވެ",
|
||||
"desktop.updater.dialog.later": "ފަހުން",
|
||||
@@ -61,8 +62,10 @@ export const dict = {
|
||||
"desktop.recovery.unresponsive": "OpenCode އިން ޖަވާބެއް ނުދެއެވެ",
|
||||
"desktop.recovery.unresponsive.detail":
|
||||
"އެޕް އަލުން ލޯންޗްކޮށް، ލޮގްތައް ހުޅުވައި، ނުވަތަ މަޑުކޮށްގެން ތިބެވޭނެ އެވެ.",
|
||||
"desktop.recovery.loadFailed.detail": "ވިންޑޯ: {{window}}\nURL: {{url}}\nއެރަރ: {{code}} {{description}}",
|
||||
"desktop.recovery.terminated.detail": "ވިންޑޯ: {{window}}\nސަބަބު: {{reason}}\nކޯޑް: {{code}}",
|
||||
"desktop.recovery.loadFailed.detail":
|
||||
"ވިންޑޯ: \u2068{{window}}\u2069\nURL: \u2068{{url}}\u2069\nއެރަރ: \u2068{{code}}\u2069 \u2068{{description}}\u2069",
|
||||
"desktop.recovery.terminated.detail":
|
||||
"ވިންޑޯ: \u2068{{window}}\u2069\nސަބަބު: \u2068{{reason}}\u2069\nކޯޑް: \u2068{{code}}\u2069",
|
||||
"desktop.recovery.unknown": "<ނޭނގޭ>",
|
||||
"desktop.dialog.chooseFolder": "ފޯލްޑަރެއް ހޮވާށެވެ",
|
||||
"desktop.dialog.chooseFile": "ފައިލެއް ހޮވާށެވެ",
|
||||
@@ -75,25 +78,27 @@ export const dict = {
|
||||
"desktop.wsl.error.listOnline": "އޮންލައިންކޮށް WSL ޑިސްޓްރޯސް ލިސްޓް ނުކުރެވިއްޖެއެވެ",
|
||||
"desktop.wsl.error.executeDistro": "ޑިސްޓްރޯގައި ކޮމާންޑްތައް އެގްޒެކެޓް ނުކުރެވޭނެއެވެ",
|
||||
"desktop.wsl.error.installWsl": "WSL އިންސްޓޯލް ކުރުން ނާކާމިޔާބުވެއްޖެ",
|
||||
"desktop.wsl.error.installDistro": "ޑިސްޓްރޯ: {{distro}} އިންސްޓޯލް ކުރަން ނާކާމިޔާބު",
|
||||
"desktop.wsl.error.installDistro": "ޑިސްޓްރޯ: \u2068{{distro}}\u2069 އިންސްޓޯލް ކުރަން ނާކާމިޔާބު",
|
||||
"desktop.wsl.error.installOpencode": "OpenCode އިންސްޓޯލް ކުރުން ނާކާމިޔާބުވެއްޖެ",
|
||||
"desktop.wsl.error.alreadyAdded": "{{distro}} މިހާރުވެސް އިތުރުކޮށްފައިވެއެވެ",
|
||||
"desktop.wsl.error.alreadyAdded": "\u2068{{distro}}\u2069 މިހާރުވެސް އިތުރުކޮށްފައިވެއެވެ",
|
||||
"desktop.wsl.error.opencodeMissing": "މި ޑިސްޓްރޯގައި opencode އިންސްޓޯލްކޮށްފައެއް ނުވެއެވެ",
|
||||
"desktop.wsl.error.opencodeCannotRun": "opencode އިންސްޓޯލް ކޮށްފައި އޮތް ނަމަވެސް ހިންގޭ ގޮތެއް ނުވިއެވެ",
|
||||
"desktop.wsl.error.opencodeNotInstalled": "OpenCode އަކީ {{distro}} ގައި އިންސްޓޯލް ކުރެވިފައިވާ އެއްޗެއް ނޫނެވެ",
|
||||
"desktop.wsl.error.opencodeNotInstalled":
|
||||
"OpenCode އަކީ \u2068{{distro}}\u2069 ގައި އިންސްޓޯލް ކުރެވިފައިވާ އެއްޗެއް ނޫނެވެ",
|
||||
"desktop.wsl.error.updateVersion":
|
||||
"OpenCode އަޕްޑޭޓް ނިމުނު ނަމަވެސް {{distro}} އަދިވެސް ރިޕޯޓް ކުރަނީ {{installed}}؛ ލަފާކުރެވޭ ގޮތުގައި {{expected}}",
|
||||
"OpenCode އަޕްޑޭޓް ނިމުނު ނަމަވެސް \u2068{{distro}}\u2069 އަދިވެސް ރިޕޯޓް ކުރަނީ \u2068{{installed}}\u2069؛ ލަފާކުރެވޭ ގޮތުގައި \u2068{{expected}}\u2069",
|
||||
"desktop.wsl.error.noVersion": "އެއްވެސް ވަރޝަނެއް ނެތެވެ",
|
||||
"desktop.wsl.error.serverExited":
|
||||
"ސްޓާޓްއަޕް ކުރުމަށްފަހު WSL ސަރވަރ އިން ނުކުމެއްޖެ (code={{code}} signal={{signal}})",
|
||||
"ސްޓާޓްއަޕް ކުރުމަށްފަހު WSL ސަރވަރ އިން ނުކުމެއްޖެ (code=\u2068{{code}}\u2069 signal=\u2068{{signal}}\u2069)",
|
||||
"desktop.wsl.error.serverExitedBeforeHealthy":
|
||||
"WSL ސަރވަރ އިން ނުކުތީ ދުޅަހެޔޮ ސިއްހަތެއްގައި ހުރުމުގެ ކުރިން (code={{code}} signal={{signal}}){{output}}",
|
||||
"WSL ސަރވަރ އިން ނުކުތީ ދުޅަހެޔޮ ސިއްހަތެއްގައި ހުރުމުގެ ކުރިން (code=\u2068{{code}}\u2069 signal=\u2068{{signal}}\u2069)\u2068{{output}}\u2069",
|
||||
"desktop.wsl.error.healthTimeout":
|
||||
"{{distro}} ހެލްތު ޗެކް ކުރުމަށް ސައިޑްކާރ ޓައިމް އައުޓް ކޮށްފައިވަނީ {{timeout}}ms އަށް ފަހުގައެވެ",
|
||||
"desktop.wsl.error.commandTimeout": "{{command}} {{args}} ޓައިމް އައުޓް ކޮށްފައިވަނީ {{timeout}}ms އަށް ފަހުގައެވެ",
|
||||
"\u2068{{distro}}\u2069 ހެލްތު ޗެކް ކުރުމަށް ސައިޑްކާރ ޓައިމް އައުޓް ކޮށްފައިވަނީ \u2068{{timeout}}\u2069ms އަށް ފަހުގައެވެ",
|
||||
"desktop.wsl.error.commandTimeout":
|
||||
"\u2068{{command}}\u2069 \u2068{{args}}\u2069 ޓައިމް އައުޓް ކޮށްފައިވަނީ \u2068{{timeout}}\u2069ms އަށް ފަހުގައެވެ",
|
||||
"desktop.wsl.error.failedPort": "ބަނދަރު ހޯދުމަށް ނާކާމިޔާބުވިއެވެ",
|
||||
"desktop.picker.error.notSelected": "ފައިލް ހޮވާފައިވަނީ ޕިކަރ އިން ނޫނެވެ",
|
||||
"desktop.picker.error.sizeLimit": "ހޮވާލެވޭ އެޓޭޗްމަންޓްތައް {{limit}} MB ލިމިޓަށްވުރެ މަތިވެއެވެ",
|
||||
"desktop.picker.error.sizeLimit": "ހޮވާލެވޭ އެޓޭޗްމަންޓްތައް \u2068{{limit}}\u2069 MB ލިމިޓަށްވުރެ މަތިވެއެވެ",
|
||||
"command.category.suggested": "ލަފާދީފިއެވެ",
|
||||
"command.category.view": "މަންޒަރު",
|
||||
"command.category.project": "ޕްރޮޖެކްޓް",
|
||||
@@ -119,7 +124,7 @@ export const dict = {
|
||||
"command.project.open": "އޯޕަން ޕްރޮޖެކްޓް",
|
||||
"command.project.previous": "ކުރީގެ މަޝްރޫޢު",
|
||||
"command.project.next": "ދެން އޮތް މަޝްރޫޢެވެ",
|
||||
"command.project.index": "ޕްރޮޖެކްޓް {{index}} އަށް ބަދަލުވާށެވެ",
|
||||
"command.project.index": "ޕްރޮޖެކްޓް \u2068{{index}}\u2069 އަށް ބަދަލުވާށެވެ",
|
||||
"command.provider.connect": "ޕްރޮވައިޑަރ ގުޅުވާށެވެ",
|
||||
"command.server.switch": "ސަރވަރ ބަދަލުކުރުން",
|
||||
"command.settings.open": "ސެޓިންގސް ހުޅުވާލާށެވެ",
|
||||
@@ -130,11 +135,11 @@ export const dict = {
|
||||
"command.session.archive": "އަރުޝީފް ސެޝަން",
|
||||
"command.palette": "ކޮމާންޑް ޕެލެޓް",
|
||||
"command.theme.cycle": "ސައިކަލް ތީމް",
|
||||
"command.theme.set": "ތީމް ބޭނުންކުރުން: {{theme}}",
|
||||
"command.theme.set": "ތީމް ބޭނުންކުރުން: \u2068{{theme}}\u2069",
|
||||
"command.theme.scheme.cycle": "ސައިކަލް ކުލަ ސްކީމް",
|
||||
"command.theme.scheme.set": "ކުލަ ސްކީމް ބޭނުންކުރުން: {{scheme}}",
|
||||
"command.theme.scheme.set": "ކުލަ ސްކީމް ބޭނުންކުރުން: \u2068{{scheme}}\u2069",
|
||||
"command.language.cycle": "ސައިކަލް ބަސް",
|
||||
"command.language.set": "ބަސް ބޭނުންކުރުން: {{language}}",
|
||||
"command.language.set": "ބަސް ބޭނުންކުރުން: \u2068{{language}}\u2069",
|
||||
"command.session.new": "އާ ޖަލްސާއެއް",
|
||||
"command.session.import": "ޖަލްސާ އިމްޕޯޓް ކުރައްވާ",
|
||||
"command.file.open": "ފައިލް ހުޅުވާލާށެވެ",
|
||||
@@ -205,22 +210,23 @@ export const dict = {
|
||||
"dialog.model.empty": "މޮޑެލް ނަތީޖާއެއް ނެތެވެ",
|
||||
"dialog.model.manage": "މޮޑެލްތައް މެނޭޖްކުރުން",
|
||||
"dialog.model.manage.description": "މޮޑެލް ސެލެކްޓަރގައި ފެންނަނީ ކޮން މޮޑެލްތަކެއްކަން ކަސްޓަމައިޒް ކުރުން.",
|
||||
"dialog.model.manage.provider.toggle": "ހުރިހާ {{provider}} މޮޑެލްތަކެއް ޓޮގްލް ކުރާށެވެ",
|
||||
"dialog.model.manage.provider.toggle": "ހުރިހާ \u2068{{provider}}\u2069 މޮޑެލްތަކެއް ޓޮގްލް ކުރާށެވެ",
|
||||
"dialog.model.unpaid.freeModels.title": "ހިލޭ މޮޑެލްތައް ފޯރުކޮށްދެނީ OpenCode އިންނެވެ",
|
||||
"dialog.model.unpaid.addMore.title": "މަޝްހޫރު ޕްރޮވައިޑަރުންގެ އިތުރު މޮޑެލްތައް އިތުރުކުރުން",
|
||||
"dialog.model.unpaid.viewMoreProviders": "އިތުރު 70+ ޕްރޮވައިޑަރުން ބައްލަވާށެވެ",
|
||||
"dialog.provider.viewAll": "އިތުރު ޕްރޮވައިޑަރުން ދައްކާށެވެ",
|
||||
"provider.connect.title": "{{provider}} ގުޅުވާށެވެ",
|
||||
"provider.connect.selectMethod": "{{provider}} އަށް ލޮގިން މެތޯޑް ހޮވާށެވެ.",
|
||||
"provider.connect.title": "\u2068{{provider}}\u2069 ގުޅުވާށެވެ",
|
||||
"provider.connect.title.anthropicProMax": "Anthropic އާއެކު ލޮގިން ވާށެވެ",
|
||||
"provider.connect.selectMethod": "\u2068{{provider}}\u2069 އަށް ލޮގިން މެތޯޑް ހޮވާށެވެ.",
|
||||
"provider.connect.method.apiKey": "API ކީ އެވެ",
|
||||
"provider.connect.method.browser": "ބްރައުޒާ އެވެ",
|
||||
"provider.connect.method.headless": "އިންޓަފޭސް ނެތި",
|
||||
"provider.connect.status.inProgress": "ހުއްދަ ދިނުމުގެ މަސައްކަތް ކުރިއަށްދާ…",
|
||||
"provider.connect.status.waiting": "ހުއްދައަށް އިންތިޒާރު ކުރަމުން…",
|
||||
"provider.connect.status.failed": "ހުއްދަ ދިނުން ނާކާމިޔާބު: {{error}}",
|
||||
"provider.connect.status.failed": "ހުއްދަ ދިނުން ނާކާމިޔާބު: \u2068{{error}}\u2069",
|
||||
"provider.connect.apiKey.description":
|
||||
"ތިބާގެ އެކައުންޓް ގުޅުވައި، OpenCode ގައި {{provider}} މޮޑެލްތައް ބޭނުންކުރުމަށް {{provider}} API ކީ ލިޔުއްވާ.",
|
||||
"provider.connect.apiKey.label": "{{provider}} API ކީ އެވެ",
|
||||
"ތިބާގެ އެކައުންޓް ގުޅުވައި، OpenCode ގައި \u2068{{provider}}\u2069 މޮޑެލްތައް ބޭނުންކުރުމަށް \u2068{{provider}}\u2069 API ކީ ލިޔުއްވާ.",
|
||||
"provider.connect.apiKey.label": "\u2068{{provider}}\u2069 API ކީ އެވެ",
|
||||
"provider.connect.apiKey.placeholder": "API ކީ އެވެ",
|
||||
"provider.connect.apiKey.required": "API ކީ ބޭނުންވެއެވެ",
|
||||
"provider.connect.opencodeZen.line1":
|
||||
@@ -233,18 +239,18 @@ export const dict = {
|
||||
"provider.connect.oauth.code.visit.prefix": "ޒިޔާރަތްކުރުން ",
|
||||
"provider.connect.oauth.code.visit.link": "މި ލިންކެވެ",
|
||||
"provider.connect.oauth.code.visit.suffix":
|
||||
" އެކައުންޓް ގުޅުވައިދިނުމަށާއި OpenCode ގައި {{provider}} މޮޑެލްތައް ބޭނުންކުރުމަށް އޮތޯރައިޒޭޝަން ކޯޑް އެއްކުރުމަށްޓަކައެވެ.",
|
||||
"provider.connect.oauth.code.label": "{{method}} ހުއްދަ ކޯޑް",
|
||||
" އެކައުންޓް ގުޅުވައިދިނުމަށާއި OpenCode ގައި \u2068{{provider}}\u2069 މޮޑެލްތައް ބޭނުންކުރުމަށް އޮތޯރައިޒޭޝަން ކޯޑް އެއްކުރުމަށްޓަކައެވެ.",
|
||||
"provider.connect.oauth.code.label": "\u2068{{method}}\u2069 ހުއްދަ ކޯޑް",
|
||||
"provider.connect.oauth.code.placeholder": "ހުއްދަ ކޯޑް",
|
||||
"provider.connect.oauth.code.required": "އޮތޯރިޒޭޝަން ކޯޑް ބޭނުންވެއެވެ",
|
||||
"provider.connect.oauth.code.invalid": "ސައްހަ ނޫން އޮތޯރިޒޭޝަން ކޯޑެކެވެ",
|
||||
"provider.connect.oauth.auto.visit.prefix": "ޒިޔާރަތްކުރުން ",
|
||||
"provider.connect.oauth.auto.visit.link": "މި ލިންކެވެ",
|
||||
"provider.connect.oauth.auto.visit.suffix":
|
||||
" އަދި ތިރީގައިވާ ކޯޑް ޖައްސަވައިގެން އެކައުންޓް ގުޅުވައި، OpenCode ގައި {{provider}} މޮޑެލްތައް ބޭނުން ކުރައްވާށެވެ.",
|
||||
" އަދި ތިރީގައިވާ ކޯޑް ޖައްސަވައިގެން އެކައުންޓް ގުޅުވައި، OpenCode ގައި \u2068{{provider}}\u2069 މޮޑެލްތައް ބޭނުން ކުރައްވާށެވެ.",
|
||||
"provider.connect.oauth.auto.confirmationCode": "ކޮންފަރމަންސް ކޯޑް",
|
||||
"provider.connect.toast.connected.title": "{{provider}} ގުޅިފައިވެއެވެ",
|
||||
"provider.connect.toast.connected.description": "{{provider}} މޮޑެލްތައް މިހާރު ބޭނުންކުރެވޭނެ އެވެ.",
|
||||
"provider.connect.toast.connected.title": "\u2068{{provider}}\u2069 ގުޅިފައިވެއެވެ",
|
||||
"provider.connect.toast.connected.description": "\u2068{{provider}}\u2069 މޮޑެލްތައް މިހާރު ބޭނުންކުރެވޭނެ އެވެ.",
|
||||
"provider.custom.title": "ކަސްޓަމް ޕްރޮވައިޑަރެވެ",
|
||||
"provider.custom.unavailable": "މި ސަރވަރގައި ކަސްޓަމް ޕްރޮވައިޑަރުން ނުލިބެއެވެ",
|
||||
"provider.custom.description.prefix": "OpenAI އާއި އެއްގޮތްވާ ޕްރޮވައިޑަރެއް ކޮންފިގްރޭޓްކުރުން. ބަލާށެވެ ",
|
||||
@@ -284,8 +290,8 @@ export const dict = {
|
||||
"provider.custom.error.baseURL.format": "ފަށަން ޖެހޭނީ http:// ނުވަތަ https:// އިންނެވެ.",
|
||||
"provider.custom.error.required": "ބޭނުންވާ",
|
||||
"provider.custom.error.duplicate": "ޑަބިލިކޭޓް ކުރުން",
|
||||
"provider.disconnect.toast.disconnected.title": "{{provider}} ކަނެކްޓް ވެއްޖެއެވެ",
|
||||
"provider.disconnect.toast.disconnected.description": "{{provider}} މޮޑެލްތައް މިހާރު ލިބެން ނެތެވެ.",
|
||||
"provider.disconnect.toast.disconnected.title": "\u2068{{provider}}\u2069 ކަނެކްޓް ވެއްޖެއެވެ",
|
||||
"provider.disconnect.toast.disconnected.description": "\u2068{{provider}}\u2069 މޮޑެލްތައް މިހާރު ލިބެން ނެތެވެ.",
|
||||
"model.tag.free": "ހިލޭ",
|
||||
"model.tag.latest": "އެންމެފަހުގެ",
|
||||
"model.provider.anthropic": "Anthropic އެވެ",
|
||||
@@ -298,7 +304,7 @@ export const dict = {
|
||||
"model.input.audio": "އޯޑިއޯ އެވެ",
|
||||
"model.input.video": "ވިޑިއޯ",
|
||||
"model.input.pdf": "ޕީޑީއެފް",
|
||||
"model.tooltip.allows": "ހުއްދަ ދެނީ: {{inputs}}",
|
||||
"model.tooltip.allows": "ހުއްދަ ދެނީ: \u2068{{inputs}}\u2069",
|
||||
"model.tooltip.context.label": "ކޮންޓެކްސްޓް",
|
||||
"model.tooltip.inputs": "އިންޕުޓްސް",
|
||||
"model.tooltip.model": "މޮޑެލް",
|
||||
@@ -306,7 +312,7 @@ export const dict = {
|
||||
"model.tooltip.reasoning": "ރިޒަނިންގ އެވެ",
|
||||
"model.tooltip.reasoning.allowed": "ރިޒަނިންގ އަށް ހުއްދަދެއެވެ",
|
||||
"model.tooltip.reasoning.none": "އެއްވެސް ވިސްނުމެއް ނެތެވެ",
|
||||
"model.tooltip.context": "ކޮންޓެކްސްޓް ލިމިޓް {{limit}}",
|
||||
"model.tooltip.context": "ކޮންޓެކްސްޓް ލިމިޓް \u2068{{limit}}\u2069",
|
||||
"common.search.placeholder": "ހޯދުން",
|
||||
"common.goBack": "ފަހަތަށް ދަތުރުކޮށްލާށެވެ",
|
||||
"common.goForward": "ކުރިއަށް ދަތުރުކޮށްލާށެވެ",
|
||||
@@ -323,8 +329,8 @@ export const dict = {
|
||||
"common.saving": "ސޭވިންގ…",
|
||||
"common.default": "ޑީފޯލްޓް",
|
||||
"common.attachment": "އެކުލެވުން",
|
||||
"prompt.placeholder.shell": "ޝެލް ކޮމާންޑް ލިޔުއްވާ… {{example}}",
|
||||
"prompt.placeholder.normal": 'ކޮންމެ އެއްޗަކާ އަހާލަން… "{{example}}".',
|
||||
"prompt.placeholder.shell": "ޝެލް ކޮމާންޑް ލިޔުއްވާ… \u2068{{example}}\u2069",
|
||||
"prompt.placeholder.normal": 'ކޮންމެ އެއްޗަކާ އަހާލަން… "\u2068{{example}}\u2069".',
|
||||
"prompt.placeholder.simple": "ކޮންމެ އެއްޗެއް އަހާލަން…",
|
||||
"prompt.placeholder.summarizeComments": "ކޮމެންޓްތައް ޚުލާޞާކޮށްލައްވާ…",
|
||||
"prompt.placeholder.summarizeComment": "ކޮމެންޓް ޚުލާޞާކޮށްލައްވާ…",
|
||||
@@ -388,7 +394,7 @@ export const dict = {
|
||||
"prompt.toast.promptSendFailed.title": "ޕްރޮމްޕްޓް ފޮނުވަން ނާކާމިޔާބުވިއެވެ",
|
||||
"prompt.toast.promptSendFailed.description": "ސެޝަން ހޯދުމަށް ނުކުޅެދިއްޖެއެވެ",
|
||||
"dialog.mcp.title": "MCPs އެވެ",
|
||||
"dialog.mcp.description": "{{enabled}} ގެ {{total}} އެނެބަލްކޮށްފައިވެއެވެ",
|
||||
"dialog.mcp.description": "\u2068{{enabled}}\u2069 ގެ \u2068{{total}}\u2069 އެނެބަލްކޮށްފައިވެއެވެ",
|
||||
"dialog.mcp.empty": "އެއްވެސް MCPs ކޮންފިގްރޭޓް ކުރެވިފައެއް ނުވެއެވެ",
|
||||
"dialog.lsp.empty": "LSPs ފައިލް ވައްތަރުތަކުން އޮޓޯ ޑިޓެކްޓް ކުރެވިފައިވެއެވެ",
|
||||
"dialog.plugins.empty": "opencode.json ގައި ކޮންފިގްރޭޓް ކުރެވިފައިވާ ޕްލަގިންސް",
|
||||
@@ -405,7 +411,7 @@ export const dict = {
|
||||
"dialog.directory.root": "މޫ",
|
||||
"dialog.directory.parent": "ބެލެނިވެރިޔާއެވެ",
|
||||
"dialog.directory.readError": "މި ފޯލްޑަރ ކިޔަން ނުކުޅެދިއްޖެއެވެ",
|
||||
"app.server.unreachable": "{{server}} އަށް ވާސިލްވެވޭ ގޮތެއް ނުވިއެވެ",
|
||||
"app.server.unreachable": "\u2068{{server}}\u2069 އަށް ވާސިލްވެވޭ ގޮތެއް ނުވިއެވެ",
|
||||
"app.server.retrying": "އޮޓޮމެޓިކުން އަލުން މަސައްކަތް ކުރަނީ…",
|
||||
"app.server.otherServers": "އެހެން ސަރވަރތަކެވެ",
|
||||
"dialog.server.title": "ސަރވަރސް",
|
||||
@@ -449,23 +455,23 @@ export const dict = {
|
||||
"wsl.onboarding.ready": "WSL ތައްޔާރުވެއްޖެއެވެ.",
|
||||
"wsl.onboarding.required": "WSL ކުރިއަށް ގެންދަން ޖެހެ އެވެ.",
|
||||
"wsl.onboarding.checkingDistros": "ޗެކިންގ ޑިސްޓްރޯސް…",
|
||||
"wsl.onboarding.installingDistro": "{{distro}} އިންސްޓޯލް ކުރަމުން…",
|
||||
"wsl.onboarding.checkingDistro": "ޗެކް ކުރަމުންދަނީ {{distro}}…",
|
||||
"wsl.onboarding.installingDistro": "\u2068{{distro}}\u2069 އިންސްޓޯލް ކުރަމުން…",
|
||||
"wsl.onboarding.checkingDistro": "ޗެކް ކުރަމުންދަނީ \u2068{{distro}}\u2069…",
|
||||
"wsl.onboarding.listingDistros": "ލިސްޓިން ޑިސްޓްރޯސް…",
|
||||
"wsl.onboarding.distroReady": "{{distro}} ތައްޔާރުވެއްޖެއެވެ.",
|
||||
"wsl.onboarding.distroNotInstalled": "{{distro}} އަދި އިންސްޓޯލްކޮށްފައެއް ނުވެއެވެ.",
|
||||
"wsl.onboarding.openDistroOnce": "ސެޓަޕް ނިންމާލުމަށްޓަކައި {{distro}} އެއްފަހަރު ހުޅުވާލާށެވެ.",
|
||||
"wsl.onboarding.finishingDistro": "{{distro}} އަށް ފިނިޝިންގ ސެޓަޕް.",
|
||||
"wsl.onboarding.distroReady": "\u2068{{distro}}\u2069 ތައްޔާރުވެއްޖެއެވެ.",
|
||||
"wsl.onboarding.distroNotInstalled": "\u2068{{distro}}\u2069 އަދި އިންސްޓޯލްކޮށްފައެއް ނުވެއެވެ.",
|
||||
"wsl.onboarding.openDistroOnce": "ސެޓަޕް ނިންމާލުމަށްޓަކައި \u2068{{distro}}\u2069 އެއްފަހަރު ހުޅުވާލާށެވެ.",
|
||||
"wsl.onboarding.finishingDistro": "\u2068{{distro}}\u2069 އަށް ފިނިޝިންގ ސެޓަޕް.",
|
||||
"wsl.onboarding.pickDistro": "ޑިސްޓްރޯއެއް ހޮވާ ނުވަތަ ތިރީގައިވާ ޑިސްޓްރޯއެއް އިންސްޓޯލް ކުރާށެވެ.",
|
||||
"wsl.onboarding.checkingOpencode": "ޗެކް ކުރަމުންދަނީ OpenCode…",
|
||||
"wsl.onboarding.checkingOpencodeIn": "{{distro}} ގައި OpenCode ޗެކްކުރަނީ…",
|
||||
"wsl.onboarding.checkingOpencodeIn": "\u2068{{distro}}\u2069 ގައި OpenCode ޗެކްކުރަނީ…",
|
||||
"wsl.onboarding.updatingOpencode": "އަޕްޑޭޓް ކުރަމުންދަނީ OpenCode…",
|
||||
"wsl.onboarding.updatingOpencodeIn": "{{distro}} ގައި OpenCode އަޕްޑޭޓް ކުރަމުންދާ…",
|
||||
"wsl.onboarding.updateOpencodeIn": "{{distro}} ގައި OpenCode އަޕްޑޭޓް ކުރާށެވެ.",
|
||||
"wsl.onboarding.updatingOpencodeIn": "\u2068{{distro}}\u2069 ގައި OpenCode އަޕްޑޭޓް ކުރަމުންދާ…",
|
||||
"wsl.onboarding.updateOpencodeIn": "\u2068{{distro}}\u2069 ގައި OpenCode އަޕްޑޭޓް ކުރާށެވެ.",
|
||||
"wsl.onboarding.updateOpencode": "OpenCode އަޕްޑޭޓް ކުރާށެވެ",
|
||||
"wsl.onboarding.opencodeReadyIn": "OpenCode ތައްޔާރުކޮށްފައިވަނީ {{distro}} ގައެވެ.",
|
||||
"wsl.onboarding.opencodeReadyIn": "OpenCode ތައްޔާރުކޮށްފައިވަނީ \u2068{{distro}}\u2069 ގައެވެ.",
|
||||
"wsl.onboarding.opencodeReady": "OpenCode ތައްޔާރުވެއްޖެއެވެ.",
|
||||
"wsl.onboarding.installOpencodeIn": "{{distro}} ގައި OpenCode އިންސްޓޯލް ކުރާށެވެ.",
|
||||
"wsl.onboarding.installOpencodeIn": "\u2068{{distro}}\u2069 ގައި OpenCode އިންސްޓޯލް ކުރާށެވެ.",
|
||||
"wsl.onboarding.installOpencode": "OpenCode އިންސްޓޯލް ކުރާށެވެ",
|
||||
"wsl.onboarding.chooseDistroFirst": "ފުރަތަމަ ޑިސްޓްރޯއެއް ހޮވާށެވެ.",
|
||||
"wsl.onboarding.loadFailed": "WSL ސްޓޭޓް ލޯޑް ނުކުރެވިއްޖެއެވެ.",
|
||||
@@ -498,11 +504,11 @@ export const dict = {
|
||||
"wsl.onboarding.wsl2Required": "WSL 2 ބޭނުންވެއެވެ.",
|
||||
"wsl.onboarding.toolsRequired": "މި ޑިސްޓްރޯއަށް ބޭނުންވަނީ bash އަދި curl އެވެ.",
|
||||
"wsl.onboarding.openTerminal": "އޯޕަން ޓާމިނަލް",
|
||||
"wsl.onboarding.path": "މަގު: {{path}}",
|
||||
"wsl.onboarding.path": "މަގު: \u2068{{path}}\u2069",
|
||||
"wsl.onboarding.notFound": "ނުފެނެއެވެ",
|
||||
"wsl.onboarding.version": "ވަރޝަން: {{version}}",
|
||||
"wsl.onboarding.version": "ވަރޝަން: \u2068{{version}}\u2069",
|
||||
"wsl.onboarding.unknown": "ނޭނގޭ އެއްޗެއް",
|
||||
"wsl.onboarding.desktopVersion": "ޑެސްކްޓޮޕް {{version}} އެވެ",
|
||||
"wsl.onboarding.desktopVersion": "ޑެސްކްޓޮޕް \u2068{{version}}\u2069 އެވެ",
|
||||
"wsl.onboarding.versionMismatch": "އިންސްޓޯލް ކޮށްފައިވާ ވަރޝަން ޑެސްކްޓޮޕް އެޕް ވަރޝަން އާއި އެއްގޮތެއް ނުވެއެވެ.",
|
||||
"wsl.onboarding.adding": "އިތުރުކުރަނީ…",
|
||||
"dialog.project.edit.title": "އެޑިޓް ޕްރޮޖެކްޓް",
|
||||
@@ -512,7 +518,7 @@ export const dict = {
|
||||
"dialog.project.edit.icon.hint": "ތަސްވީރަކަށް ކްލިކް ނުވަތަ ދަމާލާށެވެ",
|
||||
"dialog.project.edit.icon.recommended": "ލަފާދެނީ: 128x128px",
|
||||
"dialog.project.edit.color": "ކުލަ",
|
||||
"dialog.project.edit.color.select": "{{color}} ކުލަ ހޮވާށެވެ",
|
||||
"dialog.project.edit.color.select": "\u2068{{color}}\u2069 ކުލަ ހޮވާށެވެ",
|
||||
"dialog.project.edit.worktree.startup": "ވޯކްސްޕޭސް ސްޓާޓްއަޕް ސްކްރިޕްޓް",
|
||||
"dialog.project.edit.worktree.startup.description": "އާ ވޯކްސްޕޭސް (ވޯކްޓްރީ) އުފެއްދުމަށްފަހު ހިނގައެވެ.",
|
||||
"dialog.project.edit.worktree.startup.placeholder": "މ. bun install އެވެ",
|
||||
@@ -571,7 +577,7 @@ export const dict = {
|
||||
"language.th": "ไทย",
|
||||
"language.tr": "ތުރުކްޗޭ އެވެ",
|
||||
"toast.language.title": "ބަސް",
|
||||
"toast.language.description": "{{language}} އަށް ބަދަލުވެއްޖެއެވެ",
|
||||
"toast.language.description": "\u2068{{language}}\u2069 އަށް ބަދަލުވެއްޖެއެވެ",
|
||||
"toast.theme.title": "ތީމް ބަދަލުވިއެވެ",
|
||||
"toast.scheme.title": "ކުލަ ސްކީމް",
|
||||
"toast.workspace.enabled.title": "ވޯކްސްޕޭސްތައް އެނެބަލްކޮށްފައިވެއެވެ",
|
||||
@@ -593,13 +599,13 @@ export const dict = {
|
||||
"toast.session.unshare.failed.title": "ސެޝަން އަންޝެއާ ކުރަން ފެއިލްވެއްޖެ",
|
||||
"toast.session.unshare.failed.description": "ސެޝަން އަންޝެއަރ ކުރަމުން ދިޔައިރު ގޯހެއް ދިމާވިއެވެ",
|
||||
"toast.session.export.success.title": "ސެޝަން އެކްސްޕޯޓް ކޮށްފި",
|
||||
"toast.session.export.success.description": "ސެޝަން ސޭވްކޮށްފައިވަނީ {{filename}} އަށެވެ",
|
||||
"toast.session.export.success.description": "ސެޝަން ސޭވްކޮށްފައިވަނީ \u2068{{filename}}\u2069 އަށެވެ",
|
||||
"toast.session.export.failed.title": "އެކްސްޕޯޓް ސެޝަން ނާކާމިޔާބުވެއްޖެ",
|
||||
"toast.session.export.failed.description": "ސެޝަން އެކްސްޕޯޓް ކުރަމުން ދިޔައިރު ގޯހެއް ދިމާވިއެވެ",
|
||||
"toast.session.listFailed.title": "{{project}} އަށް ސެޝަންތައް ލޯޑް ނުކުރެވިއްޖެއެވެ",
|
||||
"toast.project.reloadFailed.title": "{{project}} ރީލޯޑް ނުކުރެވިއްޖެއެވެ",
|
||||
"toast.session.listFailed.title": "\u2068{{project}}\u2069 އަށް ސެޝަންތައް ލޯޑް ނުކުރެވިއްޖެއެވެ",
|
||||
"toast.project.reloadFailed.title": "\u2068{{project}}\u2069 ރީލޯޑް ނުކުރެވިއްޖެއެވެ",
|
||||
"toast.update.title": "އަޕްޑޭޓް ލިބެން ހުރެއެވެ",
|
||||
"toast.update.description": "OpenCode ({{version}}) ގެ އާ ވަރޝަނެއް މިހާރު އިންސްޓޯލް ކުރެވޭނެއެވެ.",
|
||||
"toast.update.description": "OpenCode (\u2068{{version}}\u2069) ގެ އާ ވަރޝަނެއް މިހާރު އިންސްޓޯލް ކުރެވޭނެއެވެ.",
|
||||
"toast.update.action.installRestart": "އިންސްޓޯލްކޮށް އަލުން ސްޓާޓްކުރުން",
|
||||
"toast.update.action.notYet": "އަދި ނޫން",
|
||||
"error.page.title": "ކަމެއް ގޯސްވީއެވެ",
|
||||
@@ -612,15 +618,15 @@ export const dict = {
|
||||
"error.page.action.exportLogs": "އެކްސްޕޯޓް ލޮގްސް",
|
||||
"error.page.action.checking": "ޗެކް ކުރަމުން…",
|
||||
"error.page.action.checkUpdates": "އަޕްޑޭޓްތައް ހުރިތޯ ބަލާށެވެ",
|
||||
"error.page.action.updateTo": "{{version}} އަށް އަޕްޑޭޓް ކުރާށެވެ",
|
||||
"error.page.action.updateTo": "\u2068{{version}}\u2069 އަށް އަޕްޑޭޓް ކުރާށެވެ",
|
||||
"error.page.circular": "[ސާކިއުލާ]",
|
||||
"error.page.report.prefix": "މި އެރަރ OpenCode ޓީމަށް ރިޕޯޓް ކުރައްވާށެވެ",
|
||||
"error.page.report.discord": "Discord ގައި",
|
||||
"error.page.version": "ވަރޝަން: {{version}}",
|
||||
"error.page.version": "ވަރޝަން: \u2068{{version}}\u2069",
|
||||
"error.dev.rootNotFound":
|
||||
"ރޫޓް އެލިމެންޓް ނުފެނެއެވެ. ތިބާގެ index.html އަށް އެޑް ކުރަން ހަނދާން ނެތުނީ ހެއްޔެވެ؟ ނުވަތަ id އެޓްރިބިއުޓް ގޯސްކޮށް އިމްތިހާނު ވެދާނެ ހެއްޔެވެ؟",
|
||||
"error.serverSync.connectFailed":
|
||||
"ސަރވަރ އާއި ގުޅެވޭ ގޮތެއް ނުވިއެވެ. `{{url}}` ގައި ސަރވަރެއް ހިނގަމުންދާ ހެއްޔެވެ؟",
|
||||
"ސަރވަރ އާއި ގުޅެވޭ ގޮތެއް ނުވިއެވެ. `\u2068{{url}}\u2069` ގައި ސަރވަރެއް ހިނގަމުންދާ ހެއްޔެވެ؟",
|
||||
"error.serverSDK.noServerAvailable": "ސަރވަރެއް ނުލިބެއެވެ",
|
||||
"error.serverSDK.serverNotAvailable": "ސަރވަރ ނުލިބޭ",
|
||||
"error.childStore.persistedCacheCreateFailed": "ޕަރސިސްޓެޑް ކެޝް އުފެއްދުމަށް ނާކާމިޔާބުވިއެވެ",
|
||||
@@ -633,29 +639,34 @@ export const dict = {
|
||||
"error.server.invalidConfiguration": "ސައްހަ ނޫން ކޮންފިގްރޭޝަން",
|
||||
"error.chain.causedBy": "ސަބަބަކީ:",
|
||||
"error.chain.apiError": "API ގެ ގޯހެއް",
|
||||
"error.chain.status": "ސްޓޭޓަސް: {{status}}",
|
||||
"error.chain.retryable": "އަލުން ޓްރައި ކުރެވޭނީ: {{retryable}}",
|
||||
"error.chain.responseBody": "ޖަވާބުދާރީވާ ހަށިގަނޑު:\n{{body}} އެވެ",
|
||||
"error.chain.didYouMean": "ތިޔަ މާނަކުރީ: {{suggestions}} ހެއްޔެވެ",
|
||||
"error.chain.modelNotFound": "މޮޑެލް ނުފެނޭ: {{provider}}/{{model}}",
|
||||
"error.chain.status": "ސްޓޭޓަސް: \u2068{{status}}\u2069",
|
||||
"error.chain.retryable": "އަލުން ޓްރައި ކުރެވޭނީ: \u2068{{retryable}}\u2069",
|
||||
"error.chain.responseBody": "ޖަވާބުދާރީވާ ހަށިގަނޑު:\n\u2068{{body}}\u2069 އެވެ",
|
||||
"error.chain.didYouMean": "ތިޔަ މާނަކުރީ: \u2068{{suggestions}}\u2069 ހެއްޔެވެ",
|
||||
"error.chain.modelNotFound": "މޮޑެލް ނުފެނޭ: \u2068{{provider}}\u2069/\u2068{{model}}\u2069",
|
||||
"error.chain.checkConfig": "ތިބާގެ ކޮންފިގް (opencode.json) ޕްރޮވައިޑަރ/މޮޑެލް ނަންތައް ޗެކްކުރުން",
|
||||
"error.chain.mcpFailed":
|
||||
'MCP ސަރވަރ "{{name}}" ފޭލްވެއްޖެއެވެ. ނޯޓް، OpenCode އިން އަދި MCP އޮތެންޓިކޭޝަން އަށް ސަޕޯޓް ނުކުރެއެވެ.',
|
||||
"error.chain.providerAuthFailed": "ޕްރޮވައިޑަރ އޮތެންޓިކޭޝަން ފެއިލްވެއްޖެ ({{provider}}): {{message}}",
|
||||
'MCP ސަރވަރ "\u2068{{name}}\u2069" ފޭލްވެއްޖެއެވެ. ނޯޓް، OpenCode އިން އަދި MCP އޮތެންޓިކޭޝަން އަށް ސަޕޯޓް ނުކުރެއެވެ.',
|
||||
"error.chain.providerAuthFailed":
|
||||
"ޕްރޮވައިޑަރ އޮތެންޓިކޭޝަން ފެއިލްވެއްޖެ (\u2068{{provider}}\u2069): \u2068{{message}}\u2069",
|
||||
"error.chain.providerInitFailed":
|
||||
'ޕްރޮވައިޑަރ "{{provider}}" އިނިޝިއަލައިޒް ނުކުރެވުނެވެ. ކްރެޑެންޝިއަލްސް އަދި ކޮންފިގްރޭޝަން ޗެކްކުރުން.',
|
||||
"error.chain.configJsonInvalid": "{{path}} ގައި ކޮންފިގް ފައިލަކީ ސައްހަ JSON(C) އެއް ނޫނެވެ",
|
||||
'ޕްރޮވައިޑަރ "\u2068{{provider}}\u2069" އިނިޝިއަލައިޒް ނުކުރެވުނެވެ. ކްރެޑެންޝިއަލްސް އަދި ކޮންފިގްރޭޝަން ޗެކްކުރުން.',
|
||||
"error.chain.configJsonInvalid": "\u2068{{path}}\u2069 ގައި ކޮންފިގް ފައިލަކީ ސައްހަ JSON(C) އެއް ނޫނެވެ",
|
||||
"error.chain.configJsonInvalidWithMessage":
|
||||
"{{path}} ގައި ކޮންފިގް ފައިލަކީ ސައްހަ ފައިލެއް ނޫން JSON(C): {{message}}",
|
||||
"\u2068{{path}}\u2069 ގައި ކޮންފިގް ފައިލަކީ ސައްހަ ފައިލެއް ނޫން JSON(C): \u2068{{message}}\u2069",
|
||||
"error.chain.configDirectoryTypo":
|
||||
'{{path}} ގައިވާ ޑައިރެކްޓަރީ "{{dir}}" އަކީ ސައްހަ އެއްޗެއް ނޫނެވެ. ޑައިރެކްޓަރީގެ ނަން "{{suggestion}}" އަށް ބަދަލުކޮށް ނުވަތަ ނައްތާލާށެވެ. މިއީ އާންމު ޓައިޕޯއެކެވެ.',
|
||||
"error.chain.configFrontmatterError": "{{path}} ގައި ފްރޮންޓްމެޓަރ ޕާރސް ކުރަން ނާކާމިޔާބު:\n{{message}}",
|
||||
"error.chain.configInvalid": "{{path}} ގައި ކޮންފިގް ފައިލް އަކީ ސައްހަ ފައިލްއެކެވެ",
|
||||
"error.chain.configInvalidWithMessage": "{{path}} ގައި ކޮންފިގް ފައިލް ސައްހަ ނޫން: {{message}}",
|
||||
'\u2068{{path}}\u2069 ގައިވާ ޑައިރެކްޓަރީ "\u2068{{dir}}\u2069" އަކީ ސައްހަ އެއްޗެއް ނޫނެވެ. ޑައިރެކްޓަރީގެ ނަން "\u2068{{suggestion}}\u2069" އަށް ބަދަލުކޮށް ނުވަތަ ނައްތާލާށެވެ. މިއީ އާންމު ޓައިޕޯއެކެވެ.',
|
||||
"error.chain.configFrontmatterError":
|
||||
"\u2068{{path}}\u2069 ގައި ފްރޮންޓްމެޓަރ ޕާރސް ކުރަން ނާކާމިޔާބު:\n\u2068{{message}}\u2069",
|
||||
"error.chain.configInvalid": "\u2068{{path}}\u2069 ގައި ކޮންފިގް ފައިލް އަކީ ސައްހަ ފައިލްއެކެވެ",
|
||||
"error.chain.configInvalidWithMessage":
|
||||
"\u2068{{path}}\u2069 ގައި ކޮންފިގް ފައިލް ސައްހަ ނޫން: \u2068{{message}}\u2069",
|
||||
"notification.permission.title": "ހުއްދަ ބޭނުންވެއެވެ",
|
||||
"notification.permission.description": "{{sessionTitle}} އިން {{projectName}} އަށް ހުއްދަ ބޭނުންވެއެވެ",
|
||||
"notification.permission.description":
|
||||
"\u2068{{sessionTitle}}\u2069 އިން \u2068{{projectName}}\u2069 އަށް ހުއްދަ ބޭނުންވެއެވެ",
|
||||
"notification.question.title": "ސުވާލު",
|
||||
"notification.question.description": "{{sessionTitle}} އިން {{projectName}} ގައި ސުވާލެއް އެބައޮތެވެ",
|
||||
"notification.question.description":
|
||||
"\u2068{{sessionTitle}}\u2069 އިން \u2068{{projectName}}\u2069 ގައި ސުވާލެއް އެބައޮތެވެ",
|
||||
"notification.action.goToSession": "ސެޝަނަށް ދާށެވެ",
|
||||
"notification.session.responseReady.title": "ޖަވާބުދާރީވާން ތައްޔާރު",
|
||||
"notification.session.error.title": "ސެޝަން އެރަރ",
|
||||
@@ -670,9 +681,9 @@ export const dict = {
|
||||
"home.server.collapse": "ސަރވަރ ޕްރޮޖެކްޓްތައް ކޮލަޕްސް ކުރުން",
|
||||
"home.server.expand": "ސަރވަރ ޕްރޮޖެކްޓްތައް ފުޅާކުރުން",
|
||||
"home.sessions.search.placeholder": "ސަރޗް ސެޝަންތަކެވެ",
|
||||
"home.sessions.search.placeholder.scoped": "{{scope}} ގައި ސަރޗް ސެޝަންތައް",
|
||||
"home.sessions.search.placeholder.scoped": "\u2068{{scope}}\u2069 ގައި ސަރޗް ސެޝަންތައް",
|
||||
"home.sessions.search.sessions": "ސެޝަންތައް",
|
||||
"home.sessions.search.noResults": "{{query}} އަށް އެއްވެސް ސެޝަނެއް ނުފެނެއެވެ",
|
||||
"home.sessions.search.noResults": "\u2068{{query}}\u2069 އަށް އެއްވެސް ސެޝަނެއް ނުފެނެއެވެ",
|
||||
"home.sessions.empty": "މިތާ އަދި އެއްވެސް ކަމެއް ނެތެވެ",
|
||||
"home.sessions.empty.description": "ފެށުމަށްޓަކައި ސެޝަނެއް އުފެއްދުން",
|
||||
"home.sessions.group.today": "މިއަދު",
|
||||
@@ -689,7 +700,7 @@ export const dict = {
|
||||
"session.error.notFound.description": "މި ޓެބުން އިޝާރާތް ކުރަނީ މި ސަރވަރގައި މިހާރު ނެތް ސެޝަނަކަށެވެ.",
|
||||
"session.error.notFound.closeTab": "Tab ބަންދުކުރުން",
|
||||
"session.error.serverConnection": "މި ސަރވަރ އާއި ގުޅެވޭކަށް ނެތެވެ",
|
||||
"session.review.filesChanged": "ފައިލްތައް ބަދަލުވެއްޖެ {{count}}",
|
||||
"session.review.filesChanged": "ފައިލްތައް ބަދަލުވެއްޖެ \u2068{{count}}\u2069",
|
||||
"session.review.change.one": "ބަދަލު",
|
||||
"session.review.change.other": "ބަދަލުތައް",
|
||||
"session.review.loadingChanges": "ބަދަލުތައް ލޯޑް ކުރަނީ…",
|
||||
@@ -713,22 +724,22 @@ export const dict = {
|
||||
"session.messages.loadEarlier": "ކުރީގެ މެސެޖުތައް ލޯޑް ކުރާށެވެ",
|
||||
"session.messages.loading": "މެސެޖުތައް ލޯޑް ކުރަނީ…",
|
||||
"session.messages.jumpToLatest": "އެންމެ ފަހުގެ ވާހަކައަށް ފުންމާލާށެވެ",
|
||||
"session.context.addToContext": "ކޮންޓެކްސްޓަށް {{selection}} އިތުރުކުރުން",
|
||||
"session.context.addToContext": "ކޮންޓެކްސްޓަށް \u2068{{selection}}\u2069 އިތުރުކުރުން",
|
||||
"session.todo.title": "ޓޮޑޯސް އެވެ",
|
||||
"session.todo.collapse": "ހޭނެތިގެން ވެއްޓުން",
|
||||
"session.todo.expand": "އިތުރުކުރުން",
|
||||
"session.todo.progress": "{{done}} ގެ {{total}} ޓޯޑޯސް ނިމިއްޖެއެވެ",
|
||||
"session.question.progress": "{{current}} ގެ {{total}} ސުވާލުތަކެވެ",
|
||||
"session.todo.progress": "\u2068{{done}}\u2069 ގެ \u2068{{total}}\u2069 ޓޯޑޯސް ނިމިއްޖެއެވެ",
|
||||
"session.question.progress": "\u2068{{current}}\u2069 ގެ \u2068{{total}}\u2069 ސުވާލުތަކެވެ",
|
||||
"session.question.minimize": "ސުވާލު އެންމެ ކުޑަކުރުން",
|
||||
"session.question.restore": "ސުވާލު އަލުން އާލާކުރުން",
|
||||
"session.question.pending.one": "{{count}} ކުރިއަށް އޮތް ސުވާލު",
|
||||
"session.question.pending.other": "{{count}} ކުރިއަށް އޮތް ސުވާލުތައް",
|
||||
"session.question.pending.one": "\u2068{{count}}\u2069 ކުރިއަށް އޮތް ސުވާލު",
|
||||
"session.question.pending.other": "\u2068{{count}}\u2069 ކުރިއަށް އޮތް ސުވާލުތައް",
|
||||
"session.new.title": "ކޮންމެ އެއްޗެއް ބިނާކުރާށެވެ",
|
||||
"session.new.project.new": "އާ މަޝްރޫއެއް",
|
||||
"session.new.project.search": "ޕްރޮޖެކްޓްތައް ހޯދުން",
|
||||
"session.new.project.add": "ޕްރޮޖެކްޓް އިތުރުކުރުން",
|
||||
"session.new.worktree.main": "މައި ބްރާންޗް",
|
||||
"session.new.worktree.mainWithBranch": "މައި ގޮފި ({{branch}})",
|
||||
"session.new.worktree.mainWithBranch": "މައި ގޮފި (\u2068{{branch}}\u2069)",
|
||||
"session.new.worktree.create": "އާ ވޯކްޓްރީ އުފެއްދުން",
|
||||
"session.new.workspace.runIn": "ރަން ސެޝަން އިން",
|
||||
"session.new.workspace.triggerLocal": "ލޯކަލް",
|
||||
@@ -736,11 +747,11 @@ export const dict = {
|
||||
"session.new.workspace.existing": "ވޯކްސްޕޭސް…",
|
||||
"session.new.git.none": "އެއްވެސް Git އެއް ނެތެވެ",
|
||||
"session.new.lastModified": "އެންމެ ފަހުން ބަދަލުކުރީ",
|
||||
"session.header.search.placeholder": "{{project}} ހޯދުން",
|
||||
"session.header.search.placeholder": "\u2068{{project}}\u2069 ހޯދުން",
|
||||
"session.header.searchFiles": "ފައިލްތައް ހޯދުން",
|
||||
"session.header.openIn": "ހުޅުވާފައި އިން",
|
||||
"session.header.open.action": "{{app}} ހުޅުވާލާށެވެ",
|
||||
"session.header.open.ariaLabel": "{{app}} ގައި ހުޅުވާފައި ހުރެއެވެ",
|
||||
"session.header.open.action": "\u2068{{app}}\u2069 ހުޅުވާލާށެވެ",
|
||||
"session.header.open.ariaLabel": "\u2068{{app}}\u2069 ގައި ހުޅުވާފައި ހުރެއެވެ",
|
||||
"session.header.open.menu": "އޮޕްޝަންސް ހުޅުވާލާށެވެ",
|
||||
"session.header.open.copyPath": "ކޮޕީ މަގު",
|
||||
"session.header.open.finder": "Finder އެވެ",
|
||||
@@ -771,24 +782,24 @@ export const dict = {
|
||||
"status.popover.action.manageServers": "ސަރވަރތައް މެނޭޖްކުރުން",
|
||||
"common.copied": "ކޮޕީކޮށްފައި",
|
||||
"lsp.tooltip.none": "LSP ސަރވަރެއް ނެތެވެ",
|
||||
"lsp.label.connected": "{{count}} LSP އެވެ",
|
||||
"lsp.label.connected": "\u2068{{count}}\u2069 LSP އެވެ",
|
||||
"prompt.loading": "ލޯޑިންގ ޕްރޮމްޕްޓް…",
|
||||
"terminal.loading": "ލޯޑިންގ ޓާމިނަލް…",
|
||||
"terminal.title": "ޓާމިނަލް އެވެ",
|
||||
"terminal.title.numbered": "ޓާމިނަލް {{number}} އެވެ",
|
||||
"terminal.title.numbered": "ޓާމިނަލް \u2068{{number}}\u2069 އެވެ",
|
||||
"terminal.close": "ޓާމިނަލް ބަންދުކުރުން",
|
||||
"terminal.connectionLost.title": "ގުޅުން ގެއްލިއްޖެއެވެ",
|
||||
"terminal.connectionLost.abnormalClose": "WebSocket އާދަޔާ ހިލާފަށް ބަންދުވެފައި: {{code}}",
|
||||
"terminal.connectionLost.abnormalClose": "WebSocket އާދަޔާ ހިލާފަށް ބަންދުވެފައި: \u2068{{code}}\u2069",
|
||||
"terminal.connectionLost.description":
|
||||
"ޓާމިނަލް ކަނެކްޝަން މެދުކެނޑުނެވެ. މިއީ ސަރވަރ އަލުން ސްޓާޓް ކުރުމުން ދިމާވެދާނެ ކަމެކެވެ.",
|
||||
"terminal.connectTicket.csrfError":
|
||||
"PTY ކަނެކްޓް ޓިކެޓް ރިޖެކްޓް ކޮށްފައިވަނީ އޮރިޖިން ނުވަތަ CSRF ޗެކްތަކުންނެވެ. ސަރވަރ CORS ކޮންފިގް ޗެކްކުރުން.",
|
||||
"terminal.connectTicket.statusError": "PTY ކަނެކްޓް ޓިކެޓް {{status}} އާއެކު ފެއިލްވެއްޖެއެވެ",
|
||||
"terminal.connectTicket.statusError": "PTY ކަނެކްޓް ޓިކެޓް \u2068{{status}}\u2069 އާއެކު ފެއިލްވެއްޖެއެވެ",
|
||||
"titlebar.update": "އަޕްޑޭޓް",
|
||||
"titlebar.updateVersion": "{{version}} އަޕްޑޭޓް ކުރާށެވެ",
|
||||
"titlebar.updateVersion": "\u2068{{version}}\u2069 އަޕްޑޭޓް ކުރާށެވެ",
|
||||
"common.closeTab": "ޓެބް ބަންދުކުރުން",
|
||||
"common.dismiss": "ދުރުކޮށްލުން",
|
||||
"common.moreCountSuffix": " (+{{count}} އިތުރަށް)",
|
||||
"common.moreCountSuffix": " (+\u2068{{count}}\u2069 އިތުރަށް)",
|
||||
"common.requestFailed": "ރިކުއެސްޓް ފެއިލްވިއެވެ",
|
||||
"common.moreOptions": "އިތުރު އިޚްތިޔާރުތަކެކެވެ",
|
||||
"common.learnMore": "އިތުރަށް ދަސްކުރައްވާށެވެ",
|
||||
@@ -817,9 +828,9 @@ export const dict = {
|
||||
"common.key.insert": "Insert އެވެ",
|
||||
"common.unknown": "ނޭނގޭ އެއްޗެއް",
|
||||
"common.time.justNow": "ހަމަ މިހާރު",
|
||||
"common.time.minutesAgo.short": "{{count}}m މީގެ ކުރިން",
|
||||
"common.time.hoursAgo.short": "{{count}}h މީގެ ކުރިން",
|
||||
"common.time.daysAgo.short": "{{count}}d ކުރިން",
|
||||
"common.time.minutesAgo.short": "\u2068{{count}}\u2069m މީގެ ކުރިން",
|
||||
"common.time.hoursAgo.short": "\u2068{{count}}\u2069h މީގެ ކުރިން",
|
||||
"common.time.daysAgo.short": "\u2068{{count}}\u2069d ކުރިން",
|
||||
"sidebar.menu.toggle": "ޓޮގްލް މެނޫ",
|
||||
"sidebar.nav.projectsAndSessions": "ޕްރޮޖެކްޓްތަކާއި ސެޝަންތައް",
|
||||
"sidebar.settings": "ސެޓިންގސް",
|
||||
@@ -848,7 +859,7 @@ export const dict = {
|
||||
"debugBar.jank.tip": "ފަހު 5 ސިކުންތުގައި 32ms އަށް ވުރެ ގިނަ ވަގުތު ފްރޭމް ކުރެއެވެ.",
|
||||
"debugBar.long.label": "LONG އެވެ",
|
||||
"debugBar.long.tip":
|
||||
"އެންމެ ފަހު 5 ސިކުންތުގައި ބްލޮކް ކުރެވިފައިވާ ވަގުތާއި ލޯންގް-ޓާސްކް ކައުންޓް. މެކްސް ޓާސްކް: {{max}}.",
|
||||
"އެންމެ ފަހު 5 ސިކުންތުގައި ބްލޮކް ކުރެވިފައިވާ ވަގުތާއި ލޯންގް-ޓާސްކް ކައުންޓް. މެކްސް ޓާސްކް: \u2068{{max}}\u2069.",
|
||||
"debugBar.delay.label": "DELAY އެވެ",
|
||||
"debugBar.delay.tip": "އެންމެ ގޯސްކޮށް ފެނުނު އިންޕުޓް ޑިލޭ ވޭތުވެދިޔަ 5 ސިކުންތުގެ ތެރޭގައި.",
|
||||
"debugBar.inp.label": "INP އެވެ",
|
||||
@@ -858,7 +869,8 @@ export const dict = {
|
||||
"debugBar.cls.tip": "މިހާރު ބޭނުންކުރާ އެޕް ލައިފްޓައިމް އަށް ކިއުމިއުލެޓިވް ލޭއައުޓް ޝިފްޓް.",
|
||||
"debugBar.mem.label": "MEM އެވެ",
|
||||
"debugBar.mem.tipUnavailable": "ބޭނުންކޮށްފައިވަނީ ޖޭއެސް ހީޕް އާއި ހީޕް ލިމިޓެވެ. Chromium އެކަނި.",
|
||||
"debugBar.mem.tip": "ބޭނުންކޮށްފައިވަނީ ޖޭއެސް ހީޕް އާއި ހީޕް ލިމިޓެވެ. {{used}} ގެ {{limit}} އެވެ.",
|
||||
"debugBar.mem.tip":
|
||||
"ބޭނުންކޮށްފައިވަނީ ޖޭއެސް ހީޕް އާއި ހީޕް ލިމިޓެވެ. \u2068{{used}}\u2069 ގެ \u2068{{limit}}\u2069 އެވެ.",
|
||||
"debugBar.focus.label": "FOCUS އެވެ",
|
||||
"debugBar.focus.tip": "ފޯސް ފޯކަސް ސްޓައިލްސް ހުރިހާ އިންޓަރެކްޓިވް އެލިމެންޓްތަކަށް",
|
||||
"debugBar.focus.on": "ON އެވެ",
|
||||
@@ -1010,7 +1022,8 @@ export const dict = {
|
||||
"settings.shortcuts.reset.toast.title": "ޝޯޓްކަޓްސް ރީސެޓް ކުރުން",
|
||||
"settings.shortcuts.reset.toast.description": "ކީބޯޑް ޝޯޓްކަޓްތައް ޑިފޯލްޓްތަކަށް ރީސެޓްކޮށްފައިވެއެވެ.",
|
||||
"settings.shortcuts.conflict.title": "މިހާރުވެސް ބޭނުން ކުރަމުންދާ ޝޯޓްކަޓެވެ",
|
||||
"settings.shortcuts.conflict.description": "{{keybind}} މިހާރުވެސް ޙަވާލުކުރެވިފައިވަނީ {{titles}} އަށެވެ.",
|
||||
"settings.shortcuts.conflict.description":
|
||||
"\u2068{{keybind}}\u2069 މިހާރުވެސް ޙަވާލުކުރެވިފައިވަނީ \u2068{{titles}}\u2069 އަށެވެ.",
|
||||
"settings.shortcuts.unassigned": "ޙަވާލުނުކުރެވިގެންނެވެ",
|
||||
"settings.shortcuts.pressKeys": "ކީސް އަށް ފިތާލާށެވެ",
|
||||
"settings.shortcuts.search.placeholder": "ސަރޗް ޝޯޓްކަޓްސް",
|
||||
@@ -1079,7 +1092,7 @@ export const dict = {
|
||||
"settings.permissions.tool.doom_loop.description": "އެއްގޮތް އިންޕުޓެއް އެކުލެވޭ ތަކުރާރުކޮށް ޓޫލް ކޯލްތައް ހޯދުން",
|
||||
"session.delete.failed.title": "ސެޝަން ޑިލީޓް ކުރަން ނާކާމިޔާބުވިއެވެ",
|
||||
"session.delete.title": "ސެޝަން ފުހެލުން",
|
||||
"session.delete.confirm": 'ސެޝަން "{{name}}" ފުހެލަންތަ؟',
|
||||
"session.delete.confirm": 'ސެޝަން "\u2068{{name}}\u2069" ފުހެލަންތަ؟',
|
||||
"session.delete.button": "ސެޝަން ފުހެލުން",
|
||||
"workspace.new": "އާ ވޯކްސްޕޭސް",
|
||||
"workspace.type.local": "ލޯކަލް",
|
||||
@@ -1097,14 +1110,487 @@ export const dict = {
|
||||
"workspace.status.clean": "އެއްނުވާ ބަދަލެއް ފާހަގަކުރެވިފައެއް ނުވެއެވެ.",
|
||||
"workspace.status.dirty": "މި ވޯކްސްޕޭސްގައި ފާހަގަ ނުކުރެވި ހުރި ބަދަލުތައް.",
|
||||
"workspace.delete.title": "ވޯކްސްޕޭސް ފުހެލުން",
|
||||
"workspace.delete.confirm": 'ވޯކްސްޕޭސް "{{name}}" ފުހެލަންތަ؟',
|
||||
"workspace.delete.confirm": 'ވޯކްސްޕޭސް "\u2068{{name}}\u2069" ފުހެލަންތަ؟',
|
||||
"workspace.delete.button": "ވޯކްސްޕޭސް ފުހެލުން",
|
||||
"workspace.reset.title": "ވޯކްސްޕޭސް ރީސެޓްކުރުން",
|
||||
"workspace.reset.confirm": 'ވޯކްސްޕޭސް "{{name}}" ރީސެޓްކުރުން؟',
|
||||
"workspace.reset.confirm": 'ވޯކްސްޕޭސް "\u2068{{name}}\u2069" ރީސެޓްކުރުން؟',
|
||||
"workspace.reset.button": "ވޯކްސްޕޭސް ރީސެޓްކުރުން",
|
||||
"workspace.reset.archived.none": "އެއްވެސް އެކްޓިވް ސެޝަނެއް އަރުޝީފް ނުކުރެވޭނެއެވެ.",
|
||||
"workspace.reset.archived.one": "1 ސެޝަން އަރުޝީފް ކުރެވޭނެއެވެ.",
|
||||
"workspace.reset.archived.many": "{{count}} ސެޝަންތައް އަރުޝީފް ކުރެވޭނެއެވެ.",
|
||||
"workspace.reset.archived.many": "\u2068{{count}}\u2069 ސެޝަންތައް އަރުޝީފް ކުރެވޭނެއެވެ.",
|
||||
"workspace.reset.note": "މިއީ ޑިފޯލްޓް ބްރާންޗާ އެއްގޮތްވާ ގޮތަށް ވޯކްސްޕޭސް ރީސެޓް ކުރާނެ ކަމެކެވެ.",
|
||||
"dialog.usageExceeded.dontShowAgain": "އަލުން ނުދައްކާ",
|
||||
"provider.disconnect.toast.noCredentials.description":
|
||||
"\u2068{{provider}}\u2069 އަށް ނައްތާލެވޭ އެއްވެސް ކްރެޑެންޝަލެއް ނުފެނުނެވެ.",
|
||||
"provider.disconnect.toast.failed.description": "\u2068{{provider}}\u2069 ޑިސްކަނެކްޓް ނުކުރެވުނެވެ.",
|
||||
"toast.migration.failed.title": "ޑޭޓާ މައިގްރޭޝަން ފެއިލްވެއްޖެއެވެ",
|
||||
"command.session.background": "ބެކްގްރައުންޑަށް ބަދަލުކުރުން",
|
||||
"session.timeline.notice.finished": "\u2068{{actor}}\u2069 ނިންމައިފިއެވެ",
|
||||
"session.timeline.notice.failed": "\u2068{{actor}}\u2069 ފެއިލްވެއްޖެއެވެ",
|
||||
"session.timeline.notice.cancelled": "\u2068{{actor}}\u2069 ކެންސަލްވެއްޖެއެވެ",
|
||||
"settings.tab.preferences": "ޕްރެފަރެންސްތައް",
|
||||
"settings.tab.notifications": "ނޮޓިފިކޭޝަންތައް",
|
||||
"settings.tab.projects": "ޕްރޮޖެކްޓްތައް",
|
||||
"settings.tab.extensions": "އެކްސްޓެންޝަންތައް",
|
||||
"settings.preferences.description": "ޕްރެފަރެންސް، ތީމް އަދި ޑިފޯލްޓް ސުލޫކު ކަސްޓަމައިޒް ކުރާށެވެ",
|
||||
"settings.appearance.description": "ތީމް އަދި ފޮންޓްތައް ކަސްޓަމައިޒް ކުރާށެވެ",
|
||||
"settings.notifications.description": "ނޮޓިފިކޭޝަން ލިބޭ އަދި އަޑު އިވޭ ވަގުތު ހޮވާށެވެ",
|
||||
"settings.shortcuts.description": "އާންމު އެކްޝަންތަކުގެ ޝޯޓްކަޓްތައް ކަސްޓަމައިޒް ކުރާށެވެ",
|
||||
"settings.servers.description": "ސަރވަރ ކަނެކްޝަންތައް މެނޭޖްކުރާށެވެ",
|
||||
"settings.projects.title": "ޕްރޮޖެކްޓްތައް",
|
||||
"settings.projects.description": "މި ސަރވަރުގައި ޕްރޮޖެކްޓް ސެޓިންގްސް މެނޭޖްކުރާށެވެ",
|
||||
"settings.projects.empty": "އެއްވެސް ޕްރޮޖެކްޓެއް ނުފެނުނެވެ",
|
||||
"settings.projects.server.all": "ހުރިހާ ސަރވަރުތައް",
|
||||
"settings.mcps.description": "Model Context Protocol (MCP) ސަރވަރތަކާއި ޓޫލްތައް މެނޭޖްކުރާށެވެ",
|
||||
"settings.extensions.description": "މި ސަރވަރުގައި ލިބެންހުރި އެކްސްޓެންޝަންތައް މެނޭޖްކުރާށެވެ",
|
||||
"settings.extensions.tab.mcps": "MCPs",
|
||||
"settings.extensions.tab.skills": "ހުނަރުތައް",
|
||||
"settings.extensions.availableAll": "ހުރިހާ ޕްރޮޖެކްޓަކަށް ލިބެންހުރި",
|
||||
"settings.extensions.manageConfig": "opencode.json ގައި މެނޭޖްކުރާށެވެ",
|
||||
"settings.extensions.addSkills": "ހުނަރުތައް އިތުރުކުރާނެ ގޮތް",
|
||||
"dialog.server.authenticate.title": "އޮތެންޓިކޭޓް ކުރާށެވެ",
|
||||
"project.settings.general.description": "ޕްރޮޖެކްޓްގެ ނަމާއި މަލަމަތި މެނޭޖްކުރާށެވެ",
|
||||
"project.settings.scripts": "ސްކްރިޕްޓްތައް",
|
||||
"project.settings.scripts.description": "މި ޕްރޮޖެކްޓަށް ސްކްރިޕްޓްތައް ކޮންފިގަރކުރާށެވެ",
|
||||
"project.settings.extensions.description": "މި ޕްރޮޖެކްޓަށް ލިބެންހުރި އެކްސްޓެންޝަންތައް ބަލާށެވެ",
|
||||
"project.settings.extensions.tab.lsps": "LSPs",
|
||||
"project.settings.extensions.added": "މި ޕްރޮޖެކްޓަށް އިތުރުކޮށްފައި",
|
||||
"project.settings.extensions.shared": "ހުރިހާ ޕްރޮޖެކްޓާއެކު ހިއްސާކޮށްފައި",
|
||||
"project.settings.extensions.lsp.detected": "ފާހަގަކުރެވުނު ލޭންގުއޭޖް ސަރވަރތައް",
|
||||
"project.settings.extensions.lsp.description": "ފައިލް ބާވަތްތަކުން އޮޓޮމެޓިކުން ފާހަގަކޮށްފައި",
|
||||
"project.settings.extensions.setupRequired": "ސެޓަޕް ބޭނުންވެއެވެ",
|
||||
"settings.general.section.general": "އާންމު",
|
||||
"common.viewAll": "ހުރިހާ އެއްޗެއް ބަލާށެވެ",
|
||||
"session.new.workspace.local.tooltip": "މިހާރުގެ ޗެކްއައުޓް ބޭނުންކުރާށެވެ",
|
||||
"session.new.workspace.new.tooltip": "ވަކި ޗެކްއައުޓެއް އުފައްދާށެވެ",
|
||||
"session.new.workspace.fromBranch": "\u2068{{branch}}\u2069 އިން",
|
||||
"session.new.workspace.trigger.tooltip": "ސެޝަން ހިންގާނެ ތަން ހޮވާށެވެ",
|
||||
"session.new.workspace.search.placeholder": "ވޯކްސްޕޭސްތައް ހޯދާށެވެ",
|
||||
"settings.tab.workspaces": "ވޯކްސްޕޭސްތައް",
|
||||
"settings.workspaces.filter.all": "ހުރިހާ ޕްރޮޖެކްޓްތައް",
|
||||
"settings.workspaces.empty": "އެއްވެސް ވޯކްސްޕޭސެއް ނެތެވެ",
|
||||
"settings.workspaces.count.one": "\u2068{{count}}\u2069 ވޯކްސްޕޭސް",
|
||||
"settings.workspaces.count.other": "\u2068{{count}}\u2069 ވޯކްސްޕޭސްތައް",
|
||||
"settings.workspaces.sessions.one": "\u2068{{project}}\u2069 ގައި \u2068{{count}}\u2069 ސެޝަން",
|
||||
"settings.workspaces.sessions.other": "\u2068{{project}}\u2069 ގައި \u2068{{count}}\u2069 ސެޝަންތައް",
|
||||
"settings.workspaces.lastActiveSession": "ފަހުގެ އެކްޓިވް ސެޝަން",
|
||||
"settings.workspaces.deleteAll": "ހުރިހާ ވޯކްސްޕޭސްތައް ފުހެލާށެވެ",
|
||||
"settings.workspaces.delete.warning":
|
||||
"ތިރީގައި ދައްކާ މާޖްނުކުރެވި ހުރި ބަދަލުތަކާއެކު ވޯކްސްޕޭސް ޑައިރެކްޓަރީ އަދި ބްރާންޗް ދާއިމީކޮށް ނައްތާލެވޭނެއެވެ.",
|
||||
"settings.workspaces.delete.blocked.active": "އެކްޓިވް ވޯކްސްޕޭސް ފުހެލެވޭނެ ގޮތެއް ނެތެވެ.",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"ލިންކްވެފައިވާ ސެޝަންތައް ހުންނާނެ، ނަމަވެސް އޭގެ ވޯކިންގ ޑައިރެކްޓަރީ ދާއިމީކޮށް ނައްތާލެވޭނެއެވެ.",
|
||||
"settings.workspaces.default.title": "ޑިފޯލްޓް މާޙައުލު",
|
||||
"settings.workspaces.default.description": "އާ ސެޝަންތައް ފަށާނެ ތަން ހޮވާށެވެ",
|
||||
"settings.workspaces.default.lastUsed": "ކޮންމެ ޕްރޮޖެކްޓަކަށް ވަކިން ފަހުން ބޭނުންކުރި",
|
||||
"settings.workspaces.default.local": "ލޯކަލް ޑައިރެކްޓަރީ",
|
||||
"settings.workspaces.default.new": "އާ ވޯކްސްޕޭސް",
|
||||
"workspace.move.title": "ވޯކްސްޕޭސަށް ބަދަލުކުރާށެވެ",
|
||||
"workspace.move.menu.title": "ސެޝަން ބަދަލުކުރާ ތަން",
|
||||
"workspace.move.failed": "ސެޝަން ބަދަލު ނުކުރެވުނެވެ",
|
||||
"workspace.lifecycle.creating": "ވޯކްސްޕޭސް އުފައްދަމުން",
|
||||
"workspace.lifecycle.created": "ވޯކްސްޕޭސް އުފެދިއްޖެއެވެ",
|
||||
"workspace.lifecycle.starting": "ސެޝަން ފަށަމުން",
|
||||
"workspace.onboarding.title": "ވޯކްސްޕޭސްތަކުން ސެޝަންތައް ވަކިކޮށް ބަހައްޓާށެވެ",
|
||||
"workspace.onboarding.description":
|
||||
"ކޮންމެ ސެޝަނަކަށް ވަކި ޗެކްއައުޓެއް ލިބޭތީ ތިޔަ ލޯކަލް ރިޕޮޒިޓަރީއަށް އެއްވެސް ހުރަހެއް ނާޅާނެއެވެ",
|
||||
"workspace.lifecycle.moving": "ވޯކްސްޕޭސަށް ބަދަލުކުރަމުން",
|
||||
"workspace.lifecycle.set": "ވޯކްސްޕޭސް ސެޓްވެއްޖެއެވެ",
|
||||
"session.summary.title": "ސެޝަންގެ ތަފްޞީލު",
|
||||
"session.summary.noBranch": "އެއްވެސް ބްރާންޗެއް ނެތެވެ",
|
||||
"session.summary.basedOn": "\u2068{{branch}}\u2069 އަށް ބިނާކޮށް",
|
||||
"desktop.menu.installCli": "CLI އިންސްޓޯލް ކުރާށެވެ...",
|
||||
"desktop.cli.installed.title": "CLI އިންސްޓޯލް ކުރެވިއްޖެ",
|
||||
"desktop.cli.installed.message":
|
||||
"CLI އިންސްޓޯލް ކުރެވިފައިވަނީ \u2068{{path}}\u2069 އަށެވެ\n\n'opencode2' ކޮމާންޑް ބޭނުންކުރުމަށް ޓާމިނަލް އަލުން ފަށާށެވެ.",
|
||||
"desktop.cli.failed.title": "އިންސްޓޯލް ކުރުން ނާކާމިޔާބުވެއްޖެ",
|
||||
"desktop.cli.failed.message": "CLI އިންސްޓޯލް ނުކުރެވުނެވެ: \u2068{{error}}\u2069",
|
||||
"command.project.copyID": "ޕްރޮޖެކްޓް ID ކޮޕީކުރުން",
|
||||
"command.session.copyID": "ސެޝަން ID ކޮޕީކުރުން",
|
||||
"server.row.incompatible":
|
||||
"މި ސަރވަރގައި ހިނގަނީ OpenCode \u2068{{version}}\u2069 އެވެ، އެއީ މި އެޕް އާއި އެއްގޮތް ނޫނެވެ. ކުރިއަށް ގެންދިއުމަށް OpenCode V2 އަށް އަޕްގްރޭޑް ކުރާށެވެ.",
|
||||
"toast.session.copyID.failed.title": "ސެޝަން ID ކޮޕީ ނުކުރެވުނެވެ",
|
||||
"toast.session.copyID.failed.description": "ސެޝަން ID ކޮޕީކުރަމުން ދިޔައިރު ގޯހެއް ދިމާވިއެވެ",
|
||||
"toast.project.copyID.failed.title": "ޕްރޮޖެކްޓް ID ކޮޕީ ނުކުރެވުނެވެ",
|
||||
"toast.project.copyID.failed.description": "ޕްރޮޖެކްޓް ID ކޮޕީކުރަމުން ދިޔައިރު ގޯހެއް ދިމާވިއެވެ",
|
||||
"error.page.title.status": "ސަރވަރގެ ރިކުއެސްޓް ނާކާމިޔާބުވިއެވެ",
|
||||
"error.page.description.status": "ސަރވަރުން HTTP \u2068{{status}}\u2069 ރެސްޕޮންސެއް ދީފިއެވެ.",
|
||||
"error.page.action.reload": "އަލުން ލޯޑްކުރުން",
|
||||
"session.error.incompatible": "މި ސަރވަރ ވަރޝަން ސަޕޯޓް ނުކުރެއެވެ",
|
||||
"session.error.incompatible.description":
|
||||
"\u2068{{server}}\u2069 ގައި ހިނގަނީ OpenCode \u2068{{version}}\u2069 އެވެ، އެއީ މި އެޕް އާއި އެއްގޮތް ނޫނެވެ. ކުރިއަށް ގެންދިއުމަށް ސަރވަރ OpenCode V2 އަށް އަޕްގްރޭޑް ކުރާށެވެ.",
|
||||
"session.background.moveInline": "ހިނގަމުންދާ މަސައްކަތް ބެކްގްރައުންޑަށް ލުމަށް \u2068{{keybind}}\u2069 ފިއްތާށެވެ",
|
||||
"session.background.running": "މަސައްކަތް ބެކްގްރައުންޑްގައި ހިނގަމުންދެއެވެ",
|
||||
"session.background.runningCount.one": "\u2068{{count}}\u2069 އައިޓަމެއް ބެކްގްރައުންޑްގައި ހިނގަމުންދެއެވެ",
|
||||
"session.background.runningCount.other": "\u2068{{count}}\u2069 އައިޓަމް ބެކްގްރައުންޑްގައި ހިނގަމުންދެއެވެ",
|
||||
"settings.general.row.terminalPlacement.title": "ޓާމިނަލް ބަހައްޓާ ތަން",
|
||||
"settings.general.row.terminalPlacement.description": "ސެޝަންތަކުގައި ޓާމިނަލް ހުޅުވާނެ ތަން ހޮވާށެވެ",
|
||||
"settings.general.row.terminalPlacement.side": "އަރިމަތީގައި",
|
||||
"settings.general.row.terminalPlacement.bottom": "ތިރީގައި",
|
||||
"session.location.unavailable": "ސެޝަންގެ ތަން ނުލިބެއެވެ",
|
||||
"session.location.description": "މި ސެޝަން ކުރިއަށް ގެންދިއުމަށް އެހެން ޑިރެކްޓަރީއެއް ހޮވާށެވެ.",
|
||||
"session.location.choose": "ޑިރެކްޓަރީ ހޮވާށެވެ",
|
||||
"session.location.worktree": "ވޯކްޓްރީ ހޮވާށެވެ",
|
||||
"session.location.worktreesFailed": "ވޯކްޓްރީތައް ލޯޑް ނުކުރެވުނެވެ",
|
||||
"session.location.moving": "ސެޝަން ބަދަލުކުރަމުން…",
|
||||
"dialog.server.menu.hide": "ޕްރޮޖެކްޓް ލިސްޓުން ފޮރުވާށެވެ",
|
||||
"dialog.server.menu.show": "ޕްރޮޖެކްޓް ލިސްޓުގައި ދައްކާށެވެ",
|
||||
"session.queue.count.one": "\u2068{{count}}\u2069 ކިއޫގައި",
|
||||
"session.queue.count.other": "\u2068{{count}}\u2069 ކިއޫގައި",
|
||||
"session.queue.steer": "މަގުދައްކާށެވެ",
|
||||
"session.queue.send": "ފޮނުވާށެވެ",
|
||||
"session.queue.steerTooltip": "ހުއްޓުވުމެއް ނެތި ފޮނުވާށެވެ",
|
||||
"session.queue.remove": "ނައްތާލާށެވެ",
|
||||
"session.queue.reorder": "ކިއޫގައިވާ ޕްރޮމްޕްޓް އަލުން ތަރުތީބުކުރާށެވެ",
|
||||
"session.new.worktree.creating": "ވޯކްޓްރީ އުފައްދަމުން",
|
||||
"settings.backToApp": "އެޕަށް އަނބުރާށެވެ",
|
||||
"settings.appearance.section.experimental": "ތަޖުރިބާކުރާ",
|
||||
"settings.appearance.row.tabs.title": "ޓެބްތައް",
|
||||
"settings.appearance.row.tabs.description": "ސެޝަން ޓެބްތައް ރޭވޭނެ ގޮތް ހޮވާށެވެ",
|
||||
"settings.appearance.row.tabs.horizontal": "އޮށްކޮށް",
|
||||
"settings.appearance.row.tabs.vertical": "ތިރިމަތިން",
|
||||
"settings.general.row.followUpBehavior.title": "ފޮލޯއަޕްގެ ހެދުން",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"ފޮލޯއަޕް ކިއޫކުރާނެތޯ ނުވަތަ މިހާރުގެ ޓަރން މަގުދައްކާނެތޯ ހޮވާށެވެ. ބަދަލުކުރުމަށް \u2068{{keybind}}\u2069 ބޭނުންކުރާށެވެ.",
|
||||
"settings.general.row.followUpBehavior.queue": "ކިއޫކުރާށެވެ",
|
||||
"settings.general.row.followUpBehavior.steer": "މަގުދައްކާށެވެ",
|
||||
"settings.general.row.reasoningMode.title": "މޮޑެލްގެ ރީޒަނިންގ",
|
||||
"settings.general.row.reasoningMode.description": "ޓައިމްލައިންގައި މޮޑެލްގެ ރީޒަނިންގ ދައްކާނެ ގޮތް ހޮވާށެވެ",
|
||||
"settings.general.row.reasoningMode.hidden": "ފޮރުވިފައި",
|
||||
"settings.general.row.reasoningMode.compact": "ކުރުކޮށް",
|
||||
"settings.general.row.reasoningMode.full": "ފުރިހަމަ",
|
||||
"session.new.workspace.createFrom": "މިއިން އުފައްދާށެވެ",
|
||||
"session.new.workspace.branch.search.placeholder": "ބްރާންޗް ހޯދާށެވެ",
|
||||
"toast.migration.progress.clearingOldEvents": "ކުރީގެ ހާދިސާތައް ސާފުކުރަމުން",
|
||||
"toast.migration.progress.migratingSessions": "ސެޝަންތައް މައިގްރޭޓްކުރަމުން",
|
||||
"session.new.workspace.existingLabel": "ވޯކްޓްރީ",
|
||||
"desktop.onboarding.defaultProject": "ޑީފޯލްޓް ޕްރޮޖެކްޓް",
|
||||
|
||||
"home.projects.all": "ހުރިހާ ޕްރޮޖެކްޓްތައް",
|
||||
"session.tab.files": "ފައިލްތައް",
|
||||
"session.files.openTabs": "ހުޅުވާލެވިފައިވާ ފައިލްތައް",
|
||||
"session.tab.usage": "ބޭނުންކުރުން",
|
||||
"session.view.select": "ސެޝަން ވިއު",
|
||||
"session.background.moveTasks": "\u2068{{tasks}}\u2069 ބެކްގްރައުންޑަށް ބަދަލުކުރައްވާ",
|
||||
"session.background.moveRunning": "ބެކްގްރައުންޑަށް ބަދަލުކުރައްވާ",
|
||||
"session.background.inBackground": "\u2068{{tasks}}\u2069 ބެކްގްރައުންޑުގައި ހިނގަމުންދެއެވެ",
|
||||
"session.background.tasksRunning.one": "\u2068{{count}}\u2069 ބެކްގްރައުންޑް މަސައްކަތް ހިނގަމުންދެއެވެ",
|
||||
"session.background.tasksRunning.other": "\u2068{{count}}\u2069 ބެކްގްރައުންޑް މަސައްކަތްތައް ހިނގަމުންދެއެވެ",
|
||||
"session.background.combine": "\u2068{{first}}\u2069 އަދި \u2068{{second}}\u2069",
|
||||
"session.background.shell.one": "\u2068{{count}}\u2069 ޝެލް",
|
||||
"session.background.shell.other": "\u2068{{count}}\u2069 ޝެލްތައް",
|
||||
"session.background.subagent.one": "\u2068{{count}}\u2069 ސަބްއޭޖެންޓް",
|
||||
"session.background.subagent.other": "\u2068{{count}}\u2069 ސަބްއޭޖެންޓްތައް",
|
||||
"session.timeline.working": "މަސައްކަތް ކުރަމުން",
|
||||
"session.review.wrapLines": "ރޮނގުތައް ވެށުވުން",
|
||||
"session.websearch.title": "ތިންވަނަ ފަރާތެއްގެ ވެބް ހޯދުން",
|
||||
"session.websearch.description": "އޭޖެންޓްތަކުން ވެބް ހޯދުމަށް ބޭނުންކުރާ ހޯދުމުގެ ޕްރޮވައިޑަރ ހޮވާށެވެ",
|
||||
"session.websearch.provider": "ހޯދުމުގެ ޕްރޮވައިޑަރ",
|
||||
"session.websearch.any": "ކޮންމެއެއް",
|
||||
"session.websearch.disable": "ހޯދުން ބޭނުން ނުކުރާށެވެ",
|
||||
"session.websearch.enable": "ހުއްދަދޭށެވެ",
|
||||
"session.websearch.loadFailed": "ހޯދުމުގެ ޕްރޮވައިޑަރތައް ލޯޑް ނުކުރެވުނެވެ.",
|
||||
"session.websearch.empty": "ހޯދުމުގެ ޕްރޮވައިޑަރއެއް ލިބެން ނެތެވެ.",
|
||||
"session.websearch.failed": "ތިޔަ ހޮވުން ސޭވް ނުކުރެވުނެވެ. އަލުން ޖައްސަވާ.",
|
||||
"session.websearch.retry": "އަލުން ޖައްސަވާ",
|
||||
"session.new.worktree.draftPlaceholder": "ވޯކްޓްރީ ތައްޔާރުވަންދެން ފޮލޯއަޕެއްގެ ޑްރާފްޓެއް ލިޔުއްވާ…",
|
||||
"session.search.placeholder": "ހޯދާ...",
|
||||
"session.search.noResults": "ދިމާވާއެއްޗެއް ނެތް",
|
||||
"titlebar.tabs": "ޓެބްތައް",
|
||||
"titlebar.channel.local": "ލޯކަލް",
|
||||
"titlebar.channel.dev": "ޑެވް",
|
||||
"titlebar.channel.beta": "ބީޓާ",
|
||||
"titlebar.toggleDebugTools": "ޑީބަގް ޓޫލްތައް ޓޮގްލްކުރައްވާ",
|
||||
"settings.tab.experimental": "ތަޖުރިބާގެ",
|
||||
"settings.experimental.description": "ތަޖުރިބާގެ ފީޗަރުތައް ބަލާލައްވާ",
|
||||
"settings.tab.about": "ތަޢާރަފް",
|
||||
"settings.about.version": "ވާޝަން \u2068{{version}}\u2069",
|
||||
"settings.about.devVersion": "ޑެވެލޮޕްމަންޓް",
|
||||
"settings.about.license": "MIT ލައިސަންސްގެ ދަށުން ނެރެފައި",
|
||||
"settings.about.writtenBy": "ލިޔުނީ",
|
||||
"settings.about.illustratedBy": "ކުރެހީ",
|
||||
"settings.about.and": "އަދި",
|
||||
"settings.about.otherContributor.one": "އެހެން \u2068{{count}}\u2069",
|
||||
"settings.about.otherContributor.other": "އެހެން \u2068{{count}}\u2069",
|
||||
"settings.about.firstPublished": "ފުރަތަމަ ޗާޕުކުރީ އެމެރިކާގެ މިޒޫރީގައެވެ",
|
||||
"settings.about.firstIllustrated": "ފުރަތަމަ ކުރެހީ އިނގިރޭސިވިލާތުގެ ލަންޑަންގައެވެ",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode، އޯޕަން ސޯސް ކޯޑިންގ އޭޖެންޓް",
|
||||
"settings.about.trademark": "OpenCode އަކީ Anomaly Innovations, Inc. ގެ ރަޖިސްޓަރޑް ޓްރޭޑްމާކެވެ.",
|
||||
"settings.about.typeset": "Inter އަދި IBM Plex Mono އިން ޓައިޕްސެޓްކޮށްފައި",
|
||||
"settings.about.tagline": "ތިބާ ނެތި AI އަށް ރަނގަޅު ސޮފްޓްވެއަރ ނުހެދޭނެ",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "ޕްރޮޖެކްޓް އެޑިޓްކުރައްވާ",
|
||||
"settings.timeline.title": "ޓައިމްލައިން",
|
||||
"settings.timeline.detail": "ޓައިމްލައިންގެ ތަފްޞީލް",
|
||||
"settings.timeline.description":
|
||||
"ޓައިމްލައިންގައި ފެންނަ ހަރަކާތުގެ މިންވަރު ހޮވާށެވެ. މެސެޖްތައް ފެންނަން ހުންނާނެއެވެ.",
|
||||
"settings.timeline.preset.everything": "ހުރިހާ އެއްޗެއް",
|
||||
"settings.timeline.preset.detailed": "ތަފްޞީލީ",
|
||||
"settings.timeline.preset.compact": "ކުރު",
|
||||
"settings.timeline.preset.quiet": "ހަމަޖެހިފައި",
|
||||
"settings.timeline.preset.text-only": "ލިޔުން އެކަނި",
|
||||
"settings.timeline.description.everything":
|
||||
"ހުރިހާ ހަރަކާތެއް ވަކިވަކިން ދައްކަވާ. ޝެލް އައުޓްޕުޓާއި، އެޑިޓާއި، ވިސްނުން ފުޅާކުރައްވާ.",
|
||||
"settings.timeline.description.detailed":
|
||||
"ޝެލް އައުޓްޕުޓާއި އެޑިޓްތައް ފުޅާކުރައްވާ. ސަބްއޭޖެންޓްތައް ވަކިން ދައްކައި، އެހެން ހަރަކާތް ‘ބޭނުންކުރި’ އަށް ގުރޫޕްކުރައްވާ.",
|
||||
"settings.timeline.description.compact":
|
||||
"ހުރިހާ ހަރަކާތެއް ‘ބޭނުންކުރި’ އަށް ގުރޫޕްކޮށް ތަފްޞީލް ކޮލެޕްސްކޮށް ބަހައްޓަވާ.",
|
||||
"settings.timeline.description.quiet":
|
||||
"އެޑިޓްތަކާއި ސަބްއޭޖެންޓްތައް ‘ބޭނުންކުރި’ އަށް ގުރޫޕްކުރައްވާ. އެހެން ހަރަކާތް ފޮރުވާ.",
|
||||
"settings.timeline.description.text-only": "ހުރިހާ ހަރަކާތެއް ފޮރުވާ. މެސެޖްތައް އެކަނި ދައްކަވާ.",
|
||||
"settings.timeline.description.custom":
|
||||
"ކޮންމެ ހަރަކާތެއްގެ ބައިވެރިކަމަށް ހޮވާފައިވާ ތަނާއި ތަފްޞީލް ބޭނުންކުރައްވާ.",
|
||||
"settings.timeline.custom": "ކަސްޓަމް",
|
||||
"settings.timeline.advanced": "އެޑްވާންސްޑް",
|
||||
"settings.timeline.advanced.description": "ކޮންމެ ހަރަކާތެއްގެ ބައިވެރިކަމަށް ތަނާއި ތަފްޞީލް ސެޓްކުރައްވާ.",
|
||||
"settings.timeline.category.shell": "ޝެލް",
|
||||
"settings.timeline.category.edit": "އެޑިޓްތައް",
|
||||
"settings.timeline.category.thinking": "ވިސްނުން",
|
||||
"settings.timeline.category.subagents": "ސަބްއޭޖެންޓްތައް",
|
||||
"settings.timeline.category.notices": "ނޯޓިސްތައް",
|
||||
"settings.timeline.category.tools": "އެހެން ޓޫލްތައް",
|
||||
"settings.general.row.mobileDiffWrap.description":
|
||||
"މޯބައިލް ޑިފްތަކުގައި އަރުދުކޮށް ސްކްރޯލްކުރުމުގެ ބަދަލުގައި ދިގު ރޮނގުތައް ވެށުވާ",
|
||||
|
||||
"provider.connect.error.unsupportedFields": "މި އޮތެންޓިކޭޝަން ފޯމުގައި ސަޕޯޓް ނުކުރާ ފީލްޑްތައް ހުރެއެވެ",
|
||||
"session.review.filesChangedCount.one": "\u2068{{count}}\u2069 ފައިލް ބަދަލުވެއްޖެއެވެ",
|
||||
"session.review.filesChangedCount.other": "\u2068{{count}}\u2069 ފައިލްތައް ބަދަލުވެއްޖެއެވެ",
|
||||
"settings.about.writtenByNames": "ލިޔުނީ \u2068{{names}}\u2069",
|
||||
"settings.about.illustratedByNames": "ކުރެހީ \u2068{{names}}\u2069",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"އެއްކޮށްފައި ނުވާ ބަދަލުތައް، ގުޅާފައިވާ ސެޝަންތައް ނުވަތަ އެކްޓިވް ލޮކޭޝަންތައް ހުރި ވޯކްޓްރީތައް ބެހެއްޓޭނެއެވެ.",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline":
|
||||
"\u2068{{host}}\u2069 އާއި ގުޅިފައެއް ނުވެއެވެ. ތިބާގެ ޑްރާފްޓް ރައްކާތެރިކޮށްފައި އޮވެއެވެ؛ ރިމޯޓް މަސައްކަތް އަދިވެސް ހިނގަމުންދާ ކަމަށް ވެދާނެއެވެ.",
|
||||
"ssh.placeholder": "ssh user@example.com އަށް ފޮނުއްވާށެވެ",
|
||||
"ssh.add": "SSH ސަރވަރ އިތުރުކުރުން",
|
||||
"ssh.server.menu.label": "SSH ސަރވަރ އެވެ",
|
||||
"ssh.target": "ހޯސްޓް ނުވަތަ SSH ކޮމާންޑެވެ",
|
||||
"ssh.connect": "ގުޅުވުން",
|
||||
"ssh.connectTo": "\u2068{{host}}\u2069 އާއި ގުޅާށެވެ.",
|
||||
"ssh.authenticate": "SSH ތަސްދީގުކުރުން",
|
||||
"ssh.action.authenticate": "ސައްހަކުރުން",
|
||||
"ssh.session.disconnected": "SSH ކަނެކްޝަން އިންއެކްޓިވް",
|
||||
"ssh.session.connecting": "SSH ސަރވަރ އާއި ގުޅުން",
|
||||
"ssh.session.reconnectDescription":
|
||||
"މި ސެޝަން ބަލާލުމަށްފަހު މަސައްކަތް ކުރިއަށް ގެންދިއުމަށް އަލުން ގުޅާށެވެ. ތިބާގެ ރިމޯޓް ސެޝަން ރައްކާތެރިކޮށްފައި ހުރެއެވެ.",
|
||||
"ssh.session.reconnect": "އަލުން ގުޅާލާށެވެ",
|
||||
"ssh.authenticationRequired": "\u2068{{host}}\u2069 އަށް އޮތެންޓިކޭޝަން ބޭނުންވާ",
|
||||
"ssh.trust": "އިތުބާރުކޮށް ގުޅާލާށެވެ",
|
||||
"ssh.continue": "ކުރިއަށްގެންދިޔުން",
|
||||
"ssh.retry": "އަލުން މަސައްކަތް ކުރާށެވެ",
|
||||
"ssh.update": "އަޕްޑޭޓްކޮށް އަލުން ގުޅާށެވެ",
|
||||
"ssh.openProject": "އޯޕަން ޕްރޮޖެކްޓް",
|
||||
"ssh.project": "\u2068{{host}}\u2069 ގައި ޕްރޮޖެކްޓް ހުޅުވާށެވެ.",
|
||||
"ssh.disconnect": "ގުޅުން ކަނޑާލާށެވެ",
|
||||
"ssh.forget": "ގުޅުން ހަނދާން ނައްތާލާށެވެ",
|
||||
"ssh.stage.disconnected": "ގުޅުން ކެނޑިއްޖެއެވެ. ރިމޯޓް ސަރވަރ ދޫކޮށްލާފައި އޮތީ ދުއްވާފައެވެ.",
|
||||
"ssh.stage.connecting": "SSH މެދުވެރިކޮށް ގުޅެމުން...",
|
||||
"ssh.stage.checking": "OpenCode ޗެކް ކުރަމުން...",
|
||||
"ssh.stage.downloading": "ޑައުންލޯޑް ކުރަނީ ސަރވަރ...",
|
||||
"ssh.stage.uploading": "ސަރވަރ އަޕްލޯޑް ކުރަނީ...",
|
||||
"ssh.stage.starting": "OpenCode އާއި ގުޅިގެން...",
|
||||
"ssh.stage.ready": "ގުޅިއްޖެއެވެ",
|
||||
"ssh.stage.authentication": "އޮތެންޓިކޭޝަން ބޭނުންވެއެވެ",
|
||||
"ssh.stage.incompatible": "ސަރވަރ އަޕްޑޭޓް ކުރަން ޖެހެއެވެ",
|
||||
"ssh.stage.failed": "ކަނެކްޝަން ފެއިލްވެއްޖެއެވެ",
|
||||
"ssh.error.input":
|
||||
"ހޯސްޓް ނުވަތަ SSH ކަނެކްޝަން ކޮމާންޑެއް ލިޔެލާށެވެ. ރިމޯޓް ކޮމާންޑްތަކާއި ސަޕޯޓް ނުކުރާ SSH އޮޕްޝަންތައް ހުއްދައެއް ނޫނެވެ.",
|
||||
"ssh.error.connection": "SSH ގުޅުން ގާއިމް ނުކުރެވުނެވެ. ތިބާގެ ނެޓްވޯކާއި SSH ކޮންފިގްރޭޝަން ޗެކްކުރުން.",
|
||||
"ssh.error.platform":
|
||||
"މި ރިމޯޓް ޕްލެޓްފޯމް ސަޕޯޓް ނުކުރެއެވެ. އޮޓޮމެޓިކް ސެޓަޕް މިވަގުތު ބޭނުންވަނީ Linux ނުވަތަ macOS x64 ނުވަތަ arm64 ގައެވެ.",
|
||||
"ssh.error.version": "ރިމޯޓް ސާވިސް ގުޅުމުގެ ކުރިން މި ޑެސްކްޓޮޕް ވަރޝަން އާއި އެއްގޮތްވާން ޖެހެއެވެ.",
|
||||
"ssh.error.install":
|
||||
"ރިމޯޓް ސަރވަރ އިންސްޓޯލް ނުކުރެވުނެވެ. ކަނެކްޓިވިޓީ، ޑިސްކް ސްޕޭސް، އަދި ޓާރ އިންސްޓޯލް ކޮށްފައި ހުރިތޯ ބަލާށެވެ.",
|
||||
"ssh.error.unpublished":
|
||||
"މި ޑެސްކްޓޮޕް ވަރޝަންގައި ޝާއިއުކޮށްފައިވާ ރިމޯޓް ސަރވަރެއް ނެތެވެ. ޑިވެލޮޕްމަންޓް ބިލްޑްތަކަށް، ހޯސްޓްގައި V2 އިންސްޓޯލްކޮށް ސްޓާޓްކޮށް، ދެން އަލުން މަސައްކަތް ކުރާށެވެ.",
|
||||
"ssh.error.service": "SSH ގުޅިފައިވީ ނަމަވެސް OpenCode ސަރވަރ ތައްޔާރު ނުވިއެވެ.",
|
||||
"ssh.error.host-key":
|
||||
"ހޯސްޓްގެ އައިޑެންޓިޓީ ޔަގީން ނުކުރެވުނެވެ. ތިބާއަށް އެނގޭ SSH ހޯސްޓްތައް އަޕްޑޭޓް ކުރުމުގެ ކުރިން އޭގެ އިނގިލީގެ ނިޝާން ޔަގީން ކުރައްވާށެވެ.",
|
||||
"ssh.error.ssh-missing":
|
||||
"OpenSSH ހޯދިފައެއް ނުވެއެވެ. OpenSSH ކްލައިންޓެއް އިންސްޓޯލްކޮށް، PATH ގައި ssh ލިބެން ހުރިކަން ޔަގީންކުރުން.",
|
||||
"command.browser.open": "ބްރައުޒާ ހުޅުވާލާށެވެ",
|
||||
"command.browser.reload": "ބްރައުޒާ ޕޭޖް އަލުން ލޯޑް ކުރާށެވެ",
|
||||
"command.session.summary.toggle": "ޓޮގްލް ޚުލާސާ",
|
||||
"common.color.orange": "އޮރެންޖު",
|
||||
"common.color.yellow": "ރީނދޫ",
|
||||
"common.color.cyan": "ސައިން އެވެ",
|
||||
"common.color.green": "ފެހި",
|
||||
"common.color.red": "ރަތް",
|
||||
"common.color.pink": "ފިޔާތޮށި",
|
||||
"common.color.blue": "ނޫ",
|
||||
"common.color.purple": "ޖަންބު",
|
||||
"common.color.gray": "އަޅިކުލަ",
|
||||
"mcp.auth.interactiveForm": "MCP ސަރވަރ \u2068{{name}}\u2069 އަށް ބޭނުންވަނީ އިންޓަރެކްޓިވް އޮތެންޓިކޭޝަން ފޯމެކެވެ",
|
||||
"server.connect.title": "ސަރވަރ އަކަށް ގުޅާށެވެ",
|
||||
"server.connect.description": "ފަށަން ސަރވަރ އެޑްރެހާއި ޕާސްވޯޑް ލިޔެލާށެވެ.",
|
||||
"server.connect.button": "ގުޅުވުން",
|
||||
"server.connect.address.invalid": "ސައްހަ HTTP ނުވަތަ HTTPS ސަރވަރ އެޑްރެހެއް ލިޔެލާށެވެ.",
|
||||
"server.connect.failed":
|
||||
"ގުޅެވޭ ގޮތެއް ނުވިއެވެ. ސަރވަރ އެޑްރެހާއި ޕާސްވޯޑް ޗެކްކޮށްލުމަށްފަހު އަލުން މަސައްކަތް ކުރާށެވެ.",
|
||||
"server.connect.pair.description": "ކަނެކްޝަންގެ ތަފްސީލު ހޯދުމަށްޓަކައި ކޮމްޕިއުޓަރުގައި މި ކޮމާންޑް ހިންގާށެވެ.",
|
||||
"server.connect.scan": "QR ކޯޑް ސްކޭން ކުރާށެވެ",
|
||||
"server.connect.scan.description": "އޮޕަންކޯޑް ޖޯޑުން ދައްކާ QR ކޯޑަށް ކެމެރާ އިޝާރާތް ކުރާށެވެ.",
|
||||
"server.connect.scan.invalid": "މިއީ OpenCode ޖޯޑު ކޯޑެއް ނޫނެވެ. އޮޕަންކޯޑް ޕެއާ އިން ދައްކާ ކޯޑް ސްކޭން ކުރާށެވެ.",
|
||||
"server.connect.camera": "ޕެއަރިންގ ކެމެރާ",
|
||||
"server.connect.camera.starting": "ކެމެރާ ހުޅުވަނީ...",
|
||||
"server.connect.mixedContent":
|
||||
"HTTPS ޕޭޖަކުން މި HTTP ސަރވަރ އާއި ގުޅޭ ގޮތެއް ނުވިއެވެ. އޭގެ ބަދަލުގައި HTTPS ސަރވަރ އެޑްރެހެއް ބޭނުން ކުރާށެވެ.",
|
||||
"server.connect.camera.insecure":
|
||||
"QR ސްކޭން ކުރުމަށް މި ޕޭޖް ހުޅުވަން ޖެހެނީ HTTPS ގެ މައްޗަށް ނުވަތަ ލޯކަލްހޯސްޓް އިންނެވެ.",
|
||||
"server.connect.camera.unavailable":
|
||||
"މި ބްރައުޒާއަށް އެއްވެސް ކެމެރާއެއް ނުލިބެއެވެ. ކަނެކްޝަންގެ ތަފްސީލުތައް އަމިއްލައަށް ލިޔެލާށެވެ.",
|
||||
"server.connect.camera.error":
|
||||
"ކެމެރާ ހުޅުވޭ ގޮތެއް ނުވިއެވެ. ކެމެރާއަށް ވަނުމަށް ހުއްދަ ދިނުން ނުވަތަ ކަނެކްޝަންގެ ތަފްސީލުތައް އަމިއްލައަށް ލިޔެލާށެވެ.",
|
||||
"dialog.server.menu.remove": "ރިމޫވް",
|
||||
"file.error.notFound": "ފައިލް ނުފެނޭ: \u2068{{name}}\u2069",
|
||||
"toast.migration.progress.migratingSessions.current": "ސެޝަންތައް މައިގްރޭޓްކުރުން \u2068{{current}}\u2069",
|
||||
"toast.migration.progress.migratingSessions.progress":
|
||||
"ސެޝަންތައް މައިގްރޭޓްކުރުން \u2068{{current}}\u2069/\u2068{{total}}\u2069",
|
||||
"toast.migration.progress.working": "ޑޭޓާ މައިގްރޭޓްކުރުން",
|
||||
"toast.migration.progress.working.current": "ޑޭޓާ މައިގްރޭޓްކުރުން \u2068{{current}}\u2069",
|
||||
"toast.migration.progress.working.progress": "ޑޭޓާ މައިގްރޭޓްކުރުން \u2068{{current}}\u2069/\u2068{{total}}\u2069",
|
||||
"home.workspaceTip": "ބަދަލުތައް އެކަހެރިކޮށް ބެހެއްޓުމަށްޓަކައި އާ ވޯކްސްޕޭސްއެއްގައި ދެން އޮންނަ ސެޝަން ފެށުން",
|
||||
"session.tab.browser": "ބްރައުޒާ އެވެ",
|
||||
"session.tab.add": "ޓެބް އިތުރުކުރުން",
|
||||
"session.queue.attachments.one": "ޕްލަސް \u2068{{count}}\u2069 އެޓޭޗްމަންޓް",
|
||||
"session.queue.attachments.other": "ޕްލަސް \u2068{{count}}\u2069 އެޓޭޗްމަންޓްސް",
|
||||
"session.browser.address": "ބްރައުޒާ އެޑްރެސް އެވެ",
|
||||
"session.browser.replaced": "ބްރައުޒާ ކޮންޓްރޯލް އެހެން ޑެސްކްޓޮޕް ވިންޑޯއަކަށް ބަދަލުވިއެވެ.",
|
||||
"session.browser.unsupported": "މި ޑެސްކްޓޮޕް އެޕް އިން ބްރައުޒާ ޕޭން އަށް ސަޕޯޓް ނުކުރެއެވެ.",
|
||||
"session.browser.suspended": "ބްރައުޒާ ސަސްޕެންޑް ކޮށްފިއެވެ. އަލުން ގުޅެން މި ސެޝަނާ މުއާމަލާތް ކުރުން.",
|
||||
"session.browser.address.placeholder": "URL އަށް ވަދެވޭނެއެވެ.",
|
||||
"settings.backToSettings": "އެނބުރި ސެޓިންގްސް އަށް",
|
||||
"settings.backToProjects": "އަނބުރާ ޕްރޮޖެކްޓްތަކަށް",
|
||||
"settings.search.placeholder": "ހޯދުން",
|
||||
"settings.search.results": "ސެޓިންގްސް ނަތީޖާ",
|
||||
"settings.search.group.pages": "ޞަފްޙާތަކެވެ",
|
||||
"settings.search.group.settings": "ސެޓިންގސް",
|
||||
"settings.search.group.projects": "މަޝްރޫއުތައް",
|
||||
"settings.search.group.servers": "ސަރވަރސް",
|
||||
"settings.search.result": "\u2068{{title}}\u2069، \u2068{{scope}}\u2069، \u2068{{page}}\u2069",
|
||||
"settings.search.page": "\u2068{{title}}\u2069، \u2068{{scope}}\u2069",
|
||||
"settings.search.result.unscoped": "\u2068{{title}}\u2069، \u2068{{page}}\u2069",
|
||||
"settings.search.empty": "\u2068{{query}}\u2069 އަށް އެއްވެސް ނަތީޖާއެއް ނުލިބެއެވެ.",
|
||||
"settings.search.empty.query": '"\u2068{{query}}\u2069" އެވެ.',
|
||||
"settings.search.refine": "އިތުރު ވަކި ނަތީޖާތަކެއް ފެނުމަށްޓަކައި ހޯދުން ހަނިކޮށްލާށެވެ.",
|
||||
"settings.server.description": "މި ސަރވަރުގެ ކަނެކްޝަން އަދި ޕްރެފެރެންސް މެނޭޖްކުރުން",
|
||||
"settings.server.section.connection": "ގުޅުން",
|
||||
"settings.server.preferences.websearch.title": "ތިންވަނަ ފަރާތެއްގެ ހޯދުން",
|
||||
"settings.server.preferences.websearch.description":
|
||||
"ވެބް ސަރޗް ކުރުމަށް އޭޖެންޓުން ބޭނުންކުރާ ސަރޗް ޕްރޮވައިޑަރ ހޮވާށެވެ",
|
||||
"settings.projects.search.placeholder": "ޕްރޮޖެކްޓްތައް ހޯދުން",
|
||||
"project.settings.name.title": "ޕްރޮޖެކްޓްގެ ނަން",
|
||||
"project.settings.name.description": "މުޅި OpenCode ގައި މި މަޝްރޫޢަށް ދައްކާފައިވާ ނަން.",
|
||||
"project.settings.icon.description":
|
||||
"ލަފާދެނީ: 128×128px. ތަސްވީރެއް އަޕްލޯޑް ކުރުމަށް ކްލިކް ނުވަތަ ޑްރެގް ކުރާށެވެ.",
|
||||
"project.settings.color.description": "ކަސްޓަމް އިމޭޖެއް ސެޓް ނުކުރާއިރު ޕްރޮޖެކްޓް އައިކޮންއަށް ބޭނުންކުރެއެވެ",
|
||||
"project.settings.worktree.startup.description": "އާ ވޯކްޓްރީއެއް އުފެއްދުމަށްފަހު އެއްފަހަރު ހިނގައެވެ",
|
||||
"project.settings.worktree.startup.hint.base": "ބޭސް ވޯކްޓްރީއަށް $OPENCODE_WORKTREE_BASE ބޭނުން ކުރާށެވެ.",
|
||||
"project.settings.worktree.startup.hint.new": "އާ ވޯކްޓްރީއަށް $OPENCODE_WORKTREE_PATH ބޭނުން ކުރާށެވެ.",
|
||||
"project.settings.extensions.empty.mcps.title": "އަދި އެމްސީޕީއެއް ނެތެވެ",
|
||||
"project.settings.extensions.empty.mcps.description": "OpenCode އަށް ލިބޭ އެމްސީޕީތައް މިތަނުން ފެންނާނެއެވެ",
|
||||
"project.settings.extensions.empty.plugins.title": "އަދި ޕްލަގިންސްއެއް ނެތެވެ",
|
||||
"project.settings.extensions.empty.plugins.description": "OpenCode އަށް ލިބޭ ޕްލަގިންތައް މިތަނުން ފެންނާނެއެވެ",
|
||||
"project.settings.extensions.empty.skills.title": "އަދި ހުނަރެއް ނެތެވެ",
|
||||
"project.settings.extensions.empty.skills.description": "OpenCode އަށް ލިބިފައިވާ ހުނަރުތައް މިތަނުން ފެންނާނެއެވެ",
|
||||
"project.settings.extensions.lsp.configured": "ކޮންފިގްރޭޓް ކުރެވިފައިވާ ބަހުގެ ސަރވަރސް",
|
||||
"project.settings.extensions.lsp.status.enabled": "ކޮންފިގްގައި އެނެބަލް ކުރެވިފައިވެއެވެ",
|
||||
"project.settings.extensions.lsp.status.disabled": "ކޮންފިގްގައި ޑިސެބިލްކޮށްފައިވެއެވެ",
|
||||
"project.settings.extensions.lsp.empty.title": "އެއްވެސް ބަހުގެ ސަރވަރ ކޮންފިގްރޭޓް ކުރެވިފައެއް ނުވެއެވެ",
|
||||
"project.settings.extensions.lsp.empty.description":
|
||||
"މި މަޝްރޫޢަށް ކޮންފިގްރޭޓް ކުރެވިފައިވާ ބަހުގެ ސަރވަރތައް މިތަނުން ފެންނާނެއެވެ",
|
||||
"project.settings.extensions.lsp.disabled.title": "ބަހުގެ ސަރވަރތައް ނުކުޅެދުންތެރިވެއްޖެއެވެ",
|
||||
"project.settings.extensions.lsp.disabled.description":
|
||||
"މި ޕްރޮޖެކްޓްގެ ކޮންފިގްރޭޝަންގައި LSP ޑިސެބިލް ކުރެވިފައިވެއެވެ",
|
||||
"project.settings.extensions.lsp.loadFailed": "ލޭންގުއޭޖް ސަރވަރ ކޮންފިގްރޭޝަން ލޯޑް ނުކުރެވުނެވެ",
|
||||
"project.settings.extensions.lsp.retry": "އަލުން މަސައްކަތް ކުރާށެވެ",
|
||||
"settings.timeline.summary": "\u2068{{preset}}\u2069:",
|
||||
"settings.timeline.group": "ގްރޫޕް",
|
||||
"settings.timeline.collapse": "ހޭނެތިގެން ވެއްޓުން",
|
||||
"settings.timeline.visibility.show": "ދެއްކުން",
|
||||
"settings.timeline.visibility.hide": "ފޮރުވުން",
|
||||
"settings.timeline.visibility.label": "\u2068{{activity}}\u2069 ފެންނަން ހުރުމެވެ",
|
||||
"settings.timeline.grouped.label": "\u2068{{activity}}\u2069 ގްރޫޕްކޮށްފައި ހުރެއެވެ",
|
||||
"settings.timeline.collapsed.label": "\u2068{{activity}}\u2069 ވެއްޓިއްޖެއެވެ",
|
||||
"session.new.workspace.search.empty": "އެއްގޮތް ވޯކްޓްރީއެއް ނެތެވެ",
|
||||
"settings.workspaces.description": "ވޯކްޓްރީތައް ރިވިއުކޮށް ޑިސްކް ބޭނުންކުރުން މެނޭޖްކުރުން",
|
||||
"settings.workspaces.empty.description": "OpenCode ގައި އުފެއްދި ވޯކްޓްރީތައް މިތަނުން ފެންނާނެއެވެ",
|
||||
"settings.workspaces.sessions.filtered.one": "\u2068{{count}}\u2069 ސެޝަން",
|
||||
"settings.workspaces.sessions.filtered.other": "\u2068{{count}}\u2069 ސެޝަންތަކެވެ",
|
||||
"settings.workspaces.deleteAll.confirm.one":
|
||||
"މިއީ \u2068{{count}}\u2069 ހޮވާފައިވާ ވޯކްޓްރީ ދާއިމީކޮށް ޑިލީޓް ކުރާނެ ކަމެކެވެ.",
|
||||
"settings.workspaces.deleteAll.confirm.other":
|
||||
"މިއީ \u2068{{count}}\u2069 ހޮވާފައިވާ ވޯކްޓްރީތައް ދާއިމީކޮށް ޑިލީޓް ކުރާނެ ކަމެކެވެ.",
|
||||
"settings.workspaces.deleteWithoutSessions": "ސެޝަންތަކެއް ނެތި ވޯކްޓްރީތައް ޑިލީޓްކުރުން",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"މިއީ ލިންކްޑް ސެޝަންތަކެއް ނެތި \u2068{{count}}\u2069 ވޯކްޓްރީ ދާއިމީކޮށް ޑިލީޓް ކުރާނެ ކަމެކެވެ.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"މިއީ ލިންކްޑް ސެޝަންތަކެއް ނެތް \u2068{{count}}\u2069 ވޯކްޓްރީތައް ދާއިމީކޮށް ޑިލީޓް ކުރާނެ ކަމެކެވެ.",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"އެއް ނުކުރެވި ހުރި ބަދަލުތަކެއް ނުވަތަ އެކްޓިވް ލޮކޭޝަންތަކެއް ހުރި ވޯކްޓްރީތައް ބެހެއްޓޭނެއެވެ.",
|
||||
"settings.workspaces.delete.button": "ވޯކްޓްރީތައް ޑިލީޓްކުރުން",
|
||||
"workspace.lifecycle.deleting": "ޑިލީޓް ކުރަމުން...",
|
||||
"session.summary.tooltip": "ޚުލާސާ",
|
||||
"session.summary.server": "އިތުރުކުރުން",
|
||||
"session.summary.chooseProject": "ޕްރޮޖެކްޓެއް ހޮވާށެވެ",
|
||||
"session.summary.mcp.onCreation": "ވޯކްޓްރީ އުފެއްދުމުން އަމަލުކުރެއެވެ",
|
||||
"session.summary.mcp.prepareFailed": "MCP ސަރވަރތައް ތައްޔާރު ނުކުރެވުނެވެ",
|
||||
"session.summary.mcp.unavailable": "MCP ސަރވަރ \u2068{{name}}\u2069 މި ވޯކްޓްރީގައި ނުލިބެއެވެ.",
|
||||
"session.summary.mcp.signInBeforeSend":
|
||||
"ޕްރޮމްޕްޓް ފޮނުވުމުގެ ކުރިން \u2068{{name}}\u2069 އަށް ސައިން އިން ވާނެއެވެ.",
|
||||
"session.summary.mcp.notReady":
|
||||
"MCP ސަރވަރ \u2068{{name}}\u2069 ތައްޔާރު ނުވެއެވެ. ޕްރޮމްޕް ފޮނުވުމުގެ ކުރިން އޭގެ ކަނެކްޝަން ހައްލުކުރުން.",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "ކޮންފިގްރޭޓް ކުރެވިފައިވާ MCP ސަރވަރސް",
|
||||
"session.summary.plugins": "ޕްލަގިންސް އެވެ",
|
||||
"session.summary.plugins.configured": "ކޮންފިގްރޭޓް ކުރެވިފައިވާ ޕްލަގިންސް",
|
||||
"session.summary.skills": "ހުނަރުތައް",
|
||||
"session.summary.skills.configured": "ކޮންފިގްރޭޓް ކުރެވިފައިވާ ހުނަރުތައް",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "ފެއިލްވުން",
|
||||
"session.summary.retry": "އަލުން މަސައްކަތް ކުރާށެވެ",
|
||||
"session.summary.connecting": "ގުޅުވައިގެން...",
|
||||
"session.summary.needsAuth": "ސައިން އިން ކުރަން ޖެހެއެވެ",
|
||||
"session.summary.configure": "ކޮންފިގްރޭޝަން ފައިލް",
|
||||
"session.summary.copyConfigPath": "ކޮންފިގްރޭޝަން ފައިލް މަގު ކޮޕީކުރުން",
|
||||
"session.summary.configFileMissing": "ކޮންފިގްރޭޝަން ފައިލެއް ނުފެނެއެވެ",
|
||||
"session.summary.mcp.empty": "MCP ސަރވަރ ކޮންފިގްރޭޓް ކުރެވިފައެއް ނުވެއެވެ",
|
||||
"session.summary.mcp.add": "opencode.json ގައި ސަރވަރތައް އިތުރުކުރުން.",
|
||||
"session.summary.plugins.manage": "opencode.json ގައި ޕްލަގިންސް މެނޭޖްކުރުން.",
|
||||
"session.summary.plugins.empty": "ޕްލަގިންސް ކޮންފިގްރޭޓް ކުރެވިފައެއް ނުވެއެވެ",
|
||||
"session.summary.plugins.add": "opencode.json ގައި ޕްލަގިންސް އިތުރުކުރުން.",
|
||||
"session.summary.skills.manage": "opencode.json ގައި ހުނަރުތައް މެނޭޖްކުރުން.",
|
||||
"session.summary.skills.empty": "އެއްވެސް ހުނަރެއް ކޮންފިގްރޭޓް ކުރެވިފައެއް ނުވެއެވެ",
|
||||
"session.summary.skills.add": "opencode.json ގައި ހުނަރުތައް އިތުރުކުރުން.",
|
||||
"session.summary.lsp.configured": "ކޮންފިގްރޭޓް ކުރެވިފައިވާ އެލްއެސްޕީތަކެވެ",
|
||||
"session.summary.lsp.empty": "LSP ސަރވަރ ކޮންފިގްރޭޓް ކުރެވިފައެއް ނުވެއެވެ",
|
||||
"session.summary.lsp.manage": "opencode.json ގައި LSP މެނޭޖްކުރުން.",
|
||||
"workspace.delete.location": "ސަރަހައްދު",
|
||||
|
||||
"command.debugBar.toggle": "ޑީބަގް ބާ ޓޮގަލް ކުރަން",
|
||||
"command.session.location.cycle": "ސެޝަން ލޮކޭޝަން މަތިން ބަދަލު ކުރަން",
|
||||
"dialog.provider.anthropic.note": "API ކީއަކުން Claude މޮޑެލްތަކަށް ސީދާ އެކްސެސް",
|
||||
"prompt.toast.uploading.percent": "\u2068{{percent}}\u2069%",
|
||||
"prompt.toast.uploading.cancelFile": "\u2068{{filename}}\u2069 ގެ އަޕްލޯޑް ކެންސަލް ކުރަން",
|
||||
"prompt.toast.uploading.cancel": "އަޕްލޯޑް ކެންސަލް ކުރަން",
|
||||
"prompt.toast.uploadFailed.title": "އަޕްލޯޑް ފޭލްވެއްޖެ",
|
||||
"session.browser.empty.title": "URL ލިޔުއްވާ",
|
||||
"session.browser.empty.description": "ނުވަތަ ”އެޕް ބްރައުޒަރުގައި ހުޅުވާ“ އޭ ޕްރޮމްޕްޓް ކުރަން",
|
||||
"session.browser.failed.title": "URL އަށް ނުފޯރާ",
|
||||
"session.browser.failed.description": "URL އާއި ތިޔަ ކަނެކްޝަން ޗެކްކޮށް، އަލުން މަސައްކަތް ކުރައްވާ۔",
|
||||
"debugBar.providerAriaLabel": "ޕްރޮވައިޑަރ ޕަފޯމަންސް ޑައިއަގްނޮސްޓިކްސް",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttft.tip": "ޕްރޮވައިޑަރ ރިކުއެސްޓް ފޮނުވުނު ގަޑީން ފުރަތަމަ މޮޑެލް އައުޓްޕުޓް ލިބެންދެން ދާ ވަގުތު۔",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.ttfa.tip": "ޕްރޮވައިޑަރ ރިކުއެސްޓް ފޮނުވުނު ގަޑީން ޖަވާބުގެ ފުރަތަމަ ލިޔުން ލިބެންދެން ދާ ވަގުތު।",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.tps.tip": "ފުރަތަމަ މޮޑެލް އައުޓްޕުޓަށްފަހު ސިކުންތަކަށް އައުޓްޕުޓް ޓޯކަންތައް۔",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
"debugBar.e2e.tip": "ޕްރޮވައިޑަރ ރިކުއެސްޓް ފޮނުވުނު ގަޑީން ޖަވާބުގެ ސްޓްރީމް ނިމެންދެން ދާ ވަގުތު۔",
|
||||
"settings.updates.action.download": "OpenCode ޑައުންލޯޑް ކުރަން",
|
||||
"settings.updates.migration.title": "ބީޓާއިން ސްޓޭބަލްއަށް ބަދަލުވާ",
|
||||
"settings.updates.migration.description":
|
||||
"މިހާރު OpenCode Beta، OpenCode Stable އަށް ބަދަލުވަމުން ދެއެވެ۔ \u2068{{version}}\u2069 ވަރޝަން ޑައުންލޯޑްކޮށް، އަޕްޑޭޓް ލިބެމުން ގެންދިއުމަށް ޑިސްކް އިމޭޖުން OpenCode އިންސްޓޯލް ކުރައްވާ۔",
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ export const dict: Record<string, string> = {
|
||||
"desktop.menu.window": "སྒོང༌སྒྲིག",
|
||||
"desktop.menu.help": "ཆ་རོགས་འབད་ནི",
|
||||
"desktop.menu.checkForUpdates": "དུས་མཐུན་ཚུ་གི་དོན་ལུ་ཞིབ་དཔྱད་འབད།",
|
||||
"desktop.menu.installCli": "CLI གཞི་བཙུགས་འབད།...",
|
||||
"desktop.menu.settings": "སྒྲིག་སྟངས་ཚུ།",
|
||||
"desktop.menu.reloadWebview": "ཡང་བསྐྱར་མངོན་གསལ་ Webview།",
|
||||
"desktop.menu.restart": "ལོག་འགོ་བཙུགས།",
|
||||
@@ -52,6 +53,11 @@ export const dict: Record<string, string> = {
|
||||
"desktop.updater.dialog.ready.title": "དུས་མཐུན་བཟོ་ནི་གྲ་སྒྲིག།",
|
||||
"desktop.updater.dialog.restart": "ལོག་འགོ་བཙུགས།",
|
||||
"desktop.updater.dialog.later": "ཤུལ་ལས",
|
||||
"desktop.cli.installed.title": "CLI གཞི་བཙུགས་འབད་ཡོདཔ།",
|
||||
"desktop.cli.installed.message":
|
||||
"CLI འདི་ {{path}} ལུ་གཞི་བཙུགས་འབད་ཡི།\n\n'opencode2' བརྡ་བཀོད་ལག་ལེན་འཐབ་ནིའི་དོན་ལུ་ ཊར་མི་ནཱལ་ལོག་འགོ་བཙུགས།",
|
||||
"desktop.cli.failed.title": "གཞི་བཙུགས་འཐུས་ཤོར་བྱུང་ཡོདཔ།",
|
||||
"desktop.cli.failed.message": "CLI གཞི་བཙུགས་འབད་མ་ཚུགས།: {{error}}",
|
||||
"desktop.recovery.action.relaunch": "བསྐྱར་འགོ་བཙུགས།",
|
||||
"desktop.recovery.action.exportLogs": "ཕྱིར་འདྲེན་དྲན་དེབ་ཚུ།",
|
||||
"desktop.recovery.action.keepWaiting": "བསྒུག་སྡོད།",
|
||||
@@ -1109,5 +1115,467 @@ export const dict: Record<string, string> = {
|
||||
"workspace.reset.archived.one": "ལཱ་ཡུན་ ༡ གཏན་མཛོད་ནང་བཞག་འོང་།",
|
||||
"workspace.reset.archived.many": "{{count}} ལཱ་ཡུན་ཚུ་ཡིག་མཛོད་ནང་བཞག་འོང་།",
|
||||
"workspace.reset.note": "འདི་གིས་ སྔོན་སྒྲིག་ཡན་ལག་མཐུན་སྒྲིག་འབད་ནི་ལུ་ ལཱ་གི་ས་སྒོ་འདི་སླར་སྒྲིག་འབད་འོང་།",
|
||||
"toast.migration.failed.title": "གནས་སྡུད་གནས་སྤོ་འཐུས་ཤོར་བྱུང་ཡོདཔ།",
|
||||
"command.project.copyID": "ལས་གཞིའི་ཨའི་ཌི་འདྲ་བཤུས་འབད།",
|
||||
"command.session.copyID": "ལཱ་ཡུན་གྱི་ཨའི་ཌི་འདྲ་བཤུས་འབད།",
|
||||
"server.row.incompatible":
|
||||
"སར་བར་འདི་གིས་ གློག་རིམ་འདི་དང་མཐུན་འགྱུར་མེད་པའི་ OpenCode {{version}} གཡོག་བཀོལ་དོ། འཕྲོ་མཐུད་ཀྱི་དོན་ལུ་ OpenCode V2 ལུ་ཡར་སེང་འབད།",
|
||||
"toast.session.copyID.failed.title": "ལཱ་ཡུན་གྱི་ཨའི་ཌི་འདྲ་བཤུས་འབད་མ་ཚུགས།",
|
||||
"toast.session.copyID.failed.description": "ལཱ་ཡུན་གྱི་ཨའི་ཌི་འདྲ་བཤུས་འབདཝ་ད་ འཛོལ་བ་ཅིག་བྱུང་ནུག།",
|
||||
"toast.project.copyID.failed.title": "ལས་གཞིའི་ཨའི་ཌི་འདྲ་བཤུས་འབད་མ་ཚུགས།",
|
||||
"toast.project.copyID.failed.description": "ལས་གཞིའི་ཨའི་ཌི་འདྲ་བཤུས་འབདཝ་ད་ འཛོལ་བ་ཅིག་བྱུང་ནུག།",
|
||||
"error.page.title.status": "སར་བར་ཞུ་བ་འཐུས་ཤོར་བྱུང་ཡོདཔ།",
|
||||
"error.page.description.status": "སར་བར་གྱིས་ HTTP {{status}} ལན་ཅིག་སྤྲོད་ནུག།",
|
||||
"error.page.action.reload": "ཡང་བསྐྱར་མངོན་གསལ།",
|
||||
"session.error.incompatible": "སར་བར་ཐོན་རིམ་འདི་ལུ་རྒྱབ་སྐྱོར་མེད།",
|
||||
"session.error.incompatible.description":
|
||||
"{{server}} གིས་ གློག་རིམ་འདི་དང་མཐུན་འགྱུར་མེད་པའི་ OpenCode {{version}} གཡོག་བཀོལ་དོ། འཕྲོ་མཐུད་ཀྱི་དོན་ལུ་ སར་བར་འདི་ OpenCode V2 ལུ་ཡར་སེང་འབད།",
|
||||
"session.background.moveInline": "གཡོག་བཀོལ་དོ་ཡོད་པའི་ལཱ་འདི་རྒྱབ་ཁར་སྤོ་ནིའི་དོན་ལུ་ {{keybind}} ཨེབ།",
|
||||
"session.background.running": "ལཱ་འདི་རྒྱབ་ཁར་གཡོག་བཀོལ་དོ།",
|
||||
"session.background.runningCount.one": "རྒྱབ་ཁར་རྣམ་གྲངས་ {{count}} གཡོག་བཀོལ་དོ།",
|
||||
"session.background.runningCount.other": "རྒྱབ་ཁར་རྣམ་གྲངས་ {{count}} གཡོག་བཀོལ་དོ།",
|
||||
"settings.general.row.terminalPlacement.title": "ཊར་མི་ནཱལ་བཞག་ས།",
|
||||
"settings.general.row.terminalPlacement.description": "ལཱ་ཡུན་ཚུ་ནང་ ཊར་མི་ནཱལ་ག་ཏེ་ཁ་ཕྱེ་ནི་ཨིན་ན་གདམ་ཁ་རྐྱབས།",
|
||||
"settings.general.row.terminalPlacement.side": "ཟུར་ཁ།",
|
||||
"settings.general.row.terminalPlacement.bottom": "མཇུག་ལུ།",
|
||||
"command.session.background": "རྒྱབ་ཁར་སྤོ།",
|
||||
"session.timeline.notice.finished": "{{actor}} མཇུག་བསྡུ་ཡོདཔ།",
|
||||
"session.timeline.notice.failed": "{{actor}} འཐུས་ཤོར་བྱུང་ཡོདཔ།",
|
||||
"session.timeline.notice.cancelled": "{{actor}} ཆ་མེད་བཏང་ཡོདཔ།",
|
||||
"settings.tab.preferences": "དགའ་གདམ་ཚུ།",
|
||||
"settings.tab.notifications": "བརྡ་བསྐུལ་ཚུ།",
|
||||
"settings.tab.projects": "ལས་གཞི་ཚུ།",
|
||||
"settings.tab.extensions": "རྒྱ་བསྐྱེད་ཚུ།",
|
||||
"settings.preferences.description": "དགའ་གདམ་དང་ བརྗོད་དོན་ དེ་ལས་ སྔོན་སྒྲིག་སྤྱོད་ལམ་སྲོལ་སྒྲིག་འབད།",
|
||||
"settings.appearance.description": "བརྗོད་དོན་དང་ཡིག་གཟུགས་ཚུ་སྲོལ་སྒྲིག་འབད།",
|
||||
"settings.notifications.description": "བརྡ་བསྐུལ་ནམ་ཐོབ་ནི་དང་ སྒྲ་ནམ་གོ་ནི་ཨིན་ན་གདམ་ཁ་རྐྱབས།",
|
||||
"settings.shortcuts.description": "སྤྱིར་བཏང་བྱ་བ་ཚུ་གི་མགྱོགས་ཐབས་སྲོལ་སྒྲིག་འབད།",
|
||||
"settings.servers.description": "སར་བར་མཐུད་ལམ་ཚུ་འཛིན་སྐྱོང་འཐབ།",
|
||||
"settings.projects.title": "ལས་གཞི་ཚུ།",
|
||||
"settings.projects.description": "སར་བར་འདི་གུ་ལས་གཞིའི་སྒྲིག་སྟངས་ཚུ་འཛིན་སྐྱོང་འཐབ།",
|
||||
"settings.projects.empty": "ལས་གཞི་འཚོལ་མ་ཐོབ།",
|
||||
"settings.projects.server.all": "སར་བར་ཆ་མཉམ།",
|
||||
"settings.mcps.description": "Model Context Protocol (MCP) སར་བར་དང་ལག་ཆས་ཚུ་འཛིན་སྐྱོང་འཐབ།",
|
||||
"settings.extensions.description": "སར་བར་འདི་གུ་འཐོབ་ཚུགས་པའི་རྒྱ་བསྐྱེད་ཚུ་འཛིན་སྐྱོང་འཐབ།",
|
||||
"settings.extensions.tab.mcps": "MCPs",
|
||||
"settings.extensions.tab.skills": "རིག་རྩལ་ཚུ།",
|
||||
"settings.extensions.availableAll": "ལས་གཞི་ཆ་མཉམ་ལུ་འཐོབ་ཚུགས།",
|
||||
"settings.extensions.manageConfig": "opencode.json ནང་འཛིན་སྐྱོང་འཐབ།",
|
||||
"settings.extensions.addSkills": "རིག་རྩལ་ཚུ་ག་དེ་སྦེ་ཁ་སྐོང་རྐྱབ་ནི་ཨིན་ན།",
|
||||
"dialog.server.authenticate.title": "བདེན་བཤད་འབད།",
|
||||
"project.settings.general.description": "ལས་གཞིའི་མིང་དང་བཟོ་དབྱིབས་འཛིན་སྐྱོང་འཐབ།",
|
||||
"project.settings.scripts": "ཡིག་ཚུགས་ཚུ།",
|
||||
"project.settings.scripts.description": "ལས་གཞི་འདི་གི་ཡིག་ཚུགས་ཚུ་རིམ་སྒྲིག་འབད།",
|
||||
"project.settings.extensions.description": "ལས་གཞི་འདི་ལུ་འཐོབ་ཚུགས་པའི་རྒྱ་བསྐྱེད་ཚུ་བལྟ།",
|
||||
"project.settings.extensions.tab.lsps": "LSPs",
|
||||
"project.settings.extensions.added": "ལས་གཞི་འདི་ལུ་ཁ་སྐོང་བརྐྱབ་ཡོདཔ།",
|
||||
"project.settings.extensions.shared": "ལས་གཞི་ཆ་མཉམ་དང་གཅིག་ཁར་རུབ་སྤྱོད་འབད་ཡོདཔ།",
|
||||
"project.settings.extensions.lsp.detected": "སྐྱོན་འཛིན་འབད་ཡོད་པའི་སྐད་ཡིག་སར་བར་ཚུ།",
|
||||
"project.settings.extensions.lsp.description": "ཡིག་སྣོད་དབྱེ་བ་ལས་རང་བཞིན་གྱིས་སྐྱོན་འཛིན་འབད་ཡོདཔ།",
|
||||
"project.settings.extensions.setupRequired": "གཞི་སྒྲིག་དགོཔ་ཨིན།",
|
||||
"settings.general.section.general": "སྤྱིར་བཏང་།",
|
||||
"common.viewAll": "ཆ་མཉམ་བལྟ།",
|
||||
"session.new.workspace.local.tooltip": "ད་ལྟོའི་ checkout ལག་ལེན་འཐབ།",
|
||||
"session.new.workspace.new.tooltip": "checkout སོ་སོ་ཅིག་གསར་བསྐྲུན་འབད།",
|
||||
"session.new.workspace.fromBranch": "{{branch}} ལས།",
|
||||
"session.new.workspace.trigger.tooltip": "ལཱ་ཡུན་ག་ཏེ་གཡོག་བཀོལ་ནི་ཨིན་ན་སེལ་འཐུ་འབད།",
|
||||
"session.new.workspace.search.placeholder": "ལཱ་གི་ས་སྒོ་ཚུ་འཚོལ་ཞིབ་འབད།",
|
||||
"settings.tab.workspaces": "ལཱ་གི་ས་སྒོ་ཚུ།",
|
||||
"settings.workspaces.filter.all": "ལས་གཞི་ཆ་མཉམ།",
|
||||
"settings.workspaces.empty": "ལཱ་གི་ས་སྒོ་མེད།",
|
||||
"settings.workspaces.count.one": "{{count}} ལཱ་གི་ས་སྒོ།",
|
||||
"settings.workspaces.count.other": "{{count}} ལཱ་གི་ས་སྒོ།",
|
||||
"settings.workspaces.sessions.one": "{{project}} ནང་ {{count}} ལཱ་ཡུན།",
|
||||
"settings.workspaces.sessions.other": "{{project}} ནང་ {{count}} ལཱ་ཡུན།",
|
||||
"settings.workspaces.lastActiveSession": "མཇུག་གི་ཤུགས་ལྡན་ལཱ་ཡུན།",
|
||||
"settings.workspaces.deleteAll": "ལཱ་གི་ས་སྒོ་ཆ་མཉམ་བཏོན་གཏང་།",
|
||||
"settings.workspaces.delete.warning":
|
||||
"འོག་ལུ་སྟོན་ཡོད་པའི་མཉམ་བསྡོམས་མ་འབད་བའི་བསྒྱུར་བཅོས་ཚུ་རྩིས་ཏེ་ ལཱ་གི་ས་སྒོའི་སྣོད་ཐོ་དང་ཡན་ལག་གཏན་འཇགས་སྦེ་རྩ་བསྐྲད་གཏང་འོང་།",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"མཉམ་བསྡོམས་མ་འབད་བའི་བསྒྱུར་བཅོས་ཚུ་དང་ འབྲེལ་མཐུད་འབད་ཡོད་པའི་ལཱ་ཡུན་ཚུ་ ཡང་ན་ ཤུགས་ལྡན་གནས་ཁོངས་ཚུ་ཡོད་པའི་ ལཱ་གི་ཤིང་ཚུ་བཞག་འོང་།",
|
||||
"settings.workspaces.delete.blocked.active": "ཤུགས་ལྡན་ལཱ་གི་ས་སྒོ་འདི་བཏོན་གཏང་མི་ཚུགས།",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"འབྲེལ་མཐུད་ལཱ་ཡུན་ཚུ་བཞག་འོང་ དེ་འབདཝ་ད་ དེ་ཚུ་གི་ལཱ་འབད་སའི་སྣོད་ཐོ་གཏན་འཇགས་སྦེ་རྩ་བསྐྲད་གཏང་འོང་།",
|
||||
"settings.workspaces.default.title": "སྔོན་སྒྲིག་མཐའ་འཁོར།",
|
||||
"settings.workspaces.default.description": "ལཱ་ཡུན་གསརཔ་ཚུ་ག་ཏེ་འགོ་བཙུགས་ནི་ཨིན་ན་གདམ་ཁ་རྐྱབས།",
|
||||
"settings.workspaces.default.lastUsed": "ལས་གཞི་རེ་ལུ་མཇུག་ལག་ལེན་འཐབ་མི།",
|
||||
"settings.workspaces.default.local": "ས་གནས་ཀྱི་སྣོད་ཐོ།",
|
||||
"settings.workspaces.default.new": "ལཱ་གི་ས་སྒོ་གསརཔ།",
|
||||
"workspace.move.title": "ལཱ་གི་ས་སྒོ་ལུ་སྤོ།",
|
||||
"workspace.move.menu.title": "ལཱ་ཡུན་སྤོ་ས།",
|
||||
"workspace.move.failed": "ལཱ་ཡུན་སྤོ་མ་ཚུགས།",
|
||||
"workspace.lifecycle.creating": "ལཱ་གི་ས་སྒོ་གསར་བསྐྲུན་འབད་དོ།",
|
||||
"workspace.lifecycle.created": "ལཱ་གི་ས་སྒོ་གསར་བསྐྲུན་འབད་ཡོདཔ།",
|
||||
"workspace.lifecycle.starting": "ལཱ་ཡུན་འགོ་བཙུགས་དོ།",
|
||||
"workspace.onboarding.title": "ལཱ་ཡུན་ཚུ་ལཱ་གི་ས་སྒོ་དང་གཅིག་ཁར་སོ་སོར་བཞག།",
|
||||
"workspace.onboarding.description":
|
||||
"རེ་རེ་ལུ་ checkout སོ་སོ་ཡོདཔ་ལས་ ཁྱོད་ཀྱི་ས་གནས་ཀྱི་མཛོད་ཁང་ལུ་ག་ནི་ཡང་བར་ཆད་མི་འབྱུང་།",
|
||||
"workspace.lifecycle.moving": "ལཱ་གི་ས་སྒོ་ལུ་སྤོ་དོ།",
|
||||
"workspace.lifecycle.set": "ལཱ་གི་ས་སྒོ་གཞི་སྒྲིག་འབད་ཡོདཔ།",
|
||||
"session.summary.title": "ལཱ་ཡུན་ཁ་གསལ།",
|
||||
"session.summary.noBranch": "ཡན་ལག་མེད།",
|
||||
"session.summary.basedOn": "{{branch}} གུ་གཞི་བཞག་ཡོདཔ།",
|
||||
"provider.disconnect.toast.noCredentials.description": "{{provider}} གི་བཏོན་གཏང་བཏུབ་པའི་ངོ་རྟགས་འཚོལ་མ་ཐོབ།",
|
||||
"provider.disconnect.toast.failed.description": "{{provider}} མཐུད་ལམ་བཏོག་མ་ཚུགས།",
|
||||
"dialog.usageExceeded.dontShowAgain": "ལོག་སྟེ་མ་སྟོན།",
|
||||
"session.location.unavailable": "ལཱ་ཡུན་གྱི་ས་གནས་འདི་མི་ཐོབ་པས།",
|
||||
"session.location.description": "ལཱ་ཡུན་འདི་འཕྲོ་མཐུད་ནི་ལུ་ སྣོད་ཐོ་གཞན་ཅིག་གདམ་ཁ་རྐྱབས།",
|
||||
"session.location.choose": "སྣོད་ཐོ་གདམ་ཁ་རྐྱབས།",
|
||||
"session.location.worktree": "Git worktree གདམ་ཁ་རྐྱབས།",
|
||||
"session.location.worktreesFailed": "Git worktree ཚུ་མངོན་གསལ་འབད་མ་ཚུགས།",
|
||||
"session.location.moving": "ལཱ་ཡུན་སྤོ་བཤུད་འབད་དོ…",
|
||||
"dialog.server.menu.hide": "ལས་འགུལ་ཐོ་ཡིག་ནང་ལས་སྦ་བཞག།",
|
||||
"dialog.server.menu.show": "ལས་འགུལ་ཐོ་ཡིག་ནང་སྟོན།",
|
||||
"session.queue.count.one": "{{count}} བསྒུག་ཐོ་ནང་།",
|
||||
"session.queue.count.other": "{{count}} བསྒུག་ཐོ་ནང་།",
|
||||
"session.queue.steer": "ཁ་སྒྱུར།",
|
||||
"session.queue.send": "གཏང་།",
|
||||
"session.queue.steerTooltip": "བར་ཆད་མ་བཏོན་པར་གཏང་།",
|
||||
"session.queue.remove": "རྩ་བསྐྲད་གཏང་།",
|
||||
"session.queue.reorder": "བསྒུག་ཐོ་ནང་གི་བརྡ་སྟོན་གོ་རིམ་སྒྲིག།",
|
||||
"session.new.worktree.creating": "Git worktree གསར་བསྐྲུན་འབད་དོ།",
|
||||
"settings.backToApp": "གློག་རིམ་ལུ་ལོག།",
|
||||
"settings.appearance.section.experimental": "ཚོད་བརྟག།",
|
||||
"settings.appearance.row.tabs.title": "མཆོང་ལྡེ་ཚུ།",
|
||||
"settings.appearance.row.tabs.description": "ལཱ་ཡུན་མཆོང་ལྡེ་ཚུ་ག་དེ་སྦེ་བཀོད་ནི་ཨིན་ན་གདམ་ཁ་རྐྱབས།",
|
||||
"settings.appearance.row.tabs.horizontal": "ཐད་སྙོམས།",
|
||||
"settings.appearance.row.tabs.vertical": "ཀེར་ཕྲང་།",
|
||||
"settings.general.row.followUpBehavior.title": "འཕྲོ་མཐུད་འཕྲིན་དོན་གྱི་སྤྱོད་ལམ།",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"འཕྲོ་མཐུད་འཕྲིན་དོན་ཚུ་བསྒུག་ཐོ་ནང་བཙུགས་ནི་ཡང་ན་ ད་ལྟོའི་ལཱ་ཐེངས་ཁ་སྒྱུར་ནི་གདམ་ཁ་རྐྱབས། སོར་ནི་ལུ་ {{keybind}} ལག་ལེན་འཐབ།",
|
||||
"settings.general.row.followUpBehavior.queue": "བསྒུག་ཐོ་ནང་བཙུགས།",
|
||||
"settings.general.row.followUpBehavior.steer": "ཁ་སྒྱུར།",
|
||||
"settings.general.row.reasoningMode.title": "དཔེ་ཚད་ཀྱི་རྒྱུ་མཚན།",
|
||||
"settings.general.row.reasoningMode.description":
|
||||
"དཔེ་ཚད་ཀྱི་རྒྱུ་མཚན་འདི་དུས་ཐིག་ནང་ག་དེ་སྦེ་སྟོན་ནི་ཨིན་ན་གདམ་ཁ་རྐྱབས།",
|
||||
"settings.general.row.reasoningMode.hidden": "སྦ་བཞག་ཡོདཔ།",
|
||||
"settings.general.row.reasoningMode.compact": "བསྡུས་པ།",
|
||||
"settings.general.row.reasoningMode.full": "ཆ་ཚང་།",
|
||||
"session.new.workspace.createFrom": "ཡན་ལག་ལས་གསར་བསྐྲུན་འབད།",
|
||||
"session.new.workspace.branch.search.placeholder": "ཡན་ལག་ཚུ་འཚོལ།",
|
||||
"toast.migration.progress.clearingOldEvents": "ཧེ་མའི་བྱུང་ལས་ཚུ་བསལ་དོ།",
|
||||
"toast.migration.progress.migratingSessions": "ལཱ་ཡུན་ཚུ་གནས་སྤོ་འབད་དོ།",
|
||||
"session.new.workspace.existingLabel": "Git worktree",
|
||||
"desktop.onboarding.defaultProject": "སྔོན་སྒྲིག་ལས་འགུལ",
|
||||
"home.projects.all": "ལས་གཞི་ཚང་མ།",
|
||||
"session.tab.files": "ཡིག་སྣོད་ཚུ།",
|
||||
"session.files.openTabs": "ཡིག་སྣོད་ཚུ་ཁ་ཕྱེ།",
|
||||
"session.tab.usage": "བེད་སྤྱོད།",
|
||||
"session.view.select": "ལཱ་ཡུན་མཐོང་སྣང་།",
|
||||
"session.background.moveTasks": "{{tasks}} རྒྱབ་གཞི་ལུ་སྤོ་བཤུད་འབད།",
|
||||
"session.background.moveRunning": "རྒྱབ་གཞི་ལུ་སྤོ་བཤུད་འབད།",
|
||||
"session.background.inBackground": "རྒྱབ་གཞི་ནང་ {{tasks}} གཡོག་བཀོལ་དོ།",
|
||||
"session.background.tasksRunning.one": "{{count}} རྒྱབ་གཞིའི་ལས་འགན་གཡོག་བཀོལ་དོ།",
|
||||
"session.background.tasksRunning.other": "{{count}} རྒྱབ་གཞིའི་ལས་འགན་ཚུ་གཡོག་བཀོལ་དོ།",
|
||||
"session.background.combine": "{{first}}དང་{{second}}།",
|
||||
"session.background.shell.one": "{{count}} Shell",
|
||||
"session.background.shell.other": "{{count}} Shell",
|
||||
"session.background.subagent.one": "{{count}} ཡན་ལག་ལས་ཚབ།",
|
||||
"session.background.subagent.other": "{{count}} ཡན་ལག་ལས་ཚབ་ཚུ།",
|
||||
"session.timeline.working": "ལཱ་འབད་དོ།",
|
||||
"session.review.wrapLines": "གྲལ་ཐིག་ཚུ་བསྡམས།",
|
||||
"session.websearch.title": "ཕྱོགས་གསུམ་པའི་དྲ་རྒྱའི་འཚོལ་ཞིབ།",
|
||||
"session.websearch.description": "ཝེབ་འཚོལ་ཞིབ་འབད་ནི་ལུ་ལག་ལེན་འཐབ་མི་ འཚོལ་ཞིབ་བྱིན་མི་ལས་ཚབ་ཚུ་སེལ་འཐུ་འབད།",
|
||||
"session.websearch.provider": "འཚོལ་ཞིབ་བྱིན་མི།",
|
||||
"session.websearch.any": "གང་རུང་།",
|
||||
"session.websearch.disable": "འཚོལ་ཞིབ་ལག་ལེན་མ་འཐབ།",
|
||||
"session.websearch.enable": "ལྕོགས་ཅན་བཟོ།",
|
||||
"session.websearch.loadFailed": "འཚོལ་ཞིབ་བྱིན་མི་ཚུ་ མངོན་གསལ་འབད་མ་ཚུགས།",
|
||||
"session.websearch.empty": "འཚོལ་ཞིབ་བྱིན་མི་ཚུ་འཐོབ་མི་ཚུགས།",
|
||||
"session.websearch.failed": "ཁྱོད་རའི་གདམ་ཁ་སྲུང་མ་ཚུགས། ལོག་སྟེ་འབད་རྩོལ་བསྐྱེད་གནང་།",
|
||||
"session.websearch.retry": "ཡང་བསྐྱར་འབད་རྩོལ་བསྐྱེད།",
|
||||
"session.new.worktree.draftPlaceholder": "ལས་ཀའི་ཤིང་འདི་གྲ་སྒྲིག་འབད་བའི་སྐབས་ལུ་ རྗེས་འཇུག་ཅིག་ཟིན་བྲིས་བཏབ།",
|
||||
"session.search.placeholder": "འཚོལ།",
|
||||
"session.search.noResults": "མཐུན་སྒྲིག་མེད།",
|
||||
"titlebar.tabs": "མཆོང་ལྡེ་ཚུ།",
|
||||
"titlebar.channel.local": "ས་གནས།",
|
||||
"titlebar.channel.dev": "Dev",
|
||||
"titlebar.channel.beta": "Beta",
|
||||
"titlebar.toggleDebugTools": "རྐྱེན་སེལ་ལག་ཆས་ཚུ་སོར་སྟོན་འབད།",
|
||||
"settings.tab.experimental": "བརྟག་དཔྱད་འབད་མི།",
|
||||
"settings.experimental.description": "བརྟག་ཞིབ་ཁྱད་རྣམ་ཚུ་འབད་རྩོལ་བསྐྱེད།",
|
||||
"settings.tab.about": "སྐོར།",
|
||||
"settings.about.version": "ཐོན་རིམ་ {{version}} .",
|
||||
"settings.about.devVersion": "གོང་འཕེལ།",
|
||||
"settings.about.license": "ཨེམ་ཨའི་ཊི་ཆོག་ཐམ་གྱི་འོག་ལུ་བཏོན་ཡོདཔ།",
|
||||
"settings.about.writtenBy": "བྲིས།",
|
||||
"settings.about.illustratedBy": "པར་རིས་བཀོད་མཁན།",
|
||||
"settings.about.and": "དང་ །",
|
||||
"settings.about.otherContributor.one": "{{count}} གཞན།",
|
||||
"settings.about.otherContributor.other": "{{count}} གཞན།",
|
||||
"settings.about.firstPublished": "འགོ་དང་པ་ ཡུ་ཨེས་ཨེ་གི་ མི་སོ་རི་ལུ་ དཔར་བསྐྲུན་འབད་ཡོདཔ།",
|
||||
"settings.about.firstIllustrated": "འགོ་དང་པ་ ཨིང་ལེནཌ་གི་ ལོན་ཌོན་ལུ་ པར་རིས་བཀོད་ཡོདཔ།",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode, ཁ་ཕྱེ་ཡོད་པའི་ཐོན་ཁུངས་གསང་ཡིག་ལས་ཚབ་པ།",
|
||||
"settings.about.trademark": "OpenCode འདི་ Anomaly Innovations, Inc གི་ཐོ་བཀོད་ཚོང་རྟགས་ཅིག་ཨིན།",
|
||||
"settings.about.typeset": "ཨིན་ཊར་དང་ཨའི་བི་ཨེམ་པེལེགསི་མོ་ནོ་ནང་ཡིག་དཔར་གཞི་སྒྲིག།",
|
||||
"settings.about.tagline": "ཁྱོད་མེད་པར་ AI གིས་མཉེན་ཆས་ལེགས་ཤོམ་བཟོ་མི་ཐུབ།",
|
||||
"settings.about.copyright": "© Anomaly གསར་གཏོད།",
|
||||
"project.settings.title": "ཞུན་དག་ལས་གཞི།",
|
||||
"settings.timeline.title": "དུས་ཚོད།",
|
||||
"settings.timeline.detail": "དུས་ཚོད་ཐིག་རྒྱས་པ།",
|
||||
"settings.timeline.description":
|
||||
"དུས་ཚོད་གྲལ་ཐིག་ནང་ ལས་སྣ་ག་དེམ་ཅིག་འབྱུངམ་ཨིན་ན་ གདམ་ཁ་རྐྱབས། འཕྲིན་དོན་ཚུ་མཐོང་ཚུགསཔ་སྦེ་སྡོདཔ་ཨིན།",
|
||||
"settings.timeline.preset.everything": "ག་ར།",
|
||||
"settings.timeline.preset.detailed": "ཁ་གསལ།",
|
||||
"settings.timeline.preset.compact": "བསྡུ་སྒྲིག།",
|
||||
"settings.timeline.preset.quiet": "ཁུ་སིམ་སིམ།",
|
||||
"settings.timeline.preset.text-only": "ཚིག་ཡིག་རྐྱངམ་གཅིག།",
|
||||
"settings.timeline.description.everything":
|
||||
"ལས་རིམ་ཆ་མཉམ་སོ་སོ་སྦེ་སྟོན། ཤེལ་གྱི་ཨའུཊི་པུཊི་དང་ཞུན་དག་ དེ་ལས་བསམ་བློ་གཏང་ནི་ཚུ་རྒྱ་བསྐྱེད་འབད།",
|
||||
"settings.timeline.description.detailed":
|
||||
"ཤལ་ཨའུཊི་པུཊི་དང་ཞུན་དག་ཚུ་རྒྱ་བསྐྱེད་འབད། ཡན་ལག་ལས་ཚབ་ཚུ་སོ་སོ་སྦེ་སྟོན་ཞིནམ་ལས་ ལག་ལེན་འཐབ་ཡོད་པའི་ནང་ལུ་ ལས་སྣ་གཞན་མི་ཚུ་སྡེ་ཚན་བཟོ།",
|
||||
"settings.timeline.description.compact":
|
||||
"ཁ་གསལ་ཚུ་བསྡམ་བཞག་ཡོད་མི་དང་གཅིག་ཁར་ལག་ལེན་འཐབ་ཡོད་པའི་ནང་ལུ་ ལས་སྣ་ཆ་མཉམ་སྡེ་ཚན་བཟོ།",
|
||||
"settings.timeline.description.quiet":
|
||||
"ལག་ལེན་འཐབ་ཡོད་པའི་ནང་ སྡེ་ཚན་ཞུན་དག་ཚུ་དང་ ཡན་ལག་ལས་ཚབ་ཚུ། ལས་སྣ་གཞན་སྦ་བཞག།",
|
||||
"settings.timeline.description.text-only": "ལས་རིམ་ཆ་མཉམ་སྦ་བཞག། འཕྲིན་དོན་ཚུ་རྐྱངམ་ཅིག་སྟོན།",
|
||||
"settings.timeline.description.custom":
|
||||
"ལས་རིམ་དབྱེ་རིམ་རེ་རེ་གི་དོན་ལུ་ ཁྱོད་ཀྱིས་སེལ་འཐུ་འབད་ཡོད་པའི་གནས་ས་དང་ཁ་གསལ་ཚུ་ལག་ལེན་འཐབ།",
|
||||
"settings.timeline.custom": "སྲོལ་སྒྲིག།",
|
||||
"settings.timeline.advanced": "ཡར་རྒྱས།",
|
||||
"settings.timeline.advanced.description": "ལས་རིམ་དབྱེ་རིམ་རེ་རེ་གི་དོན་ལུ་ ས་གནས་དང་ཁ་གསལ་ཚུ་གཞི་སྒྲིག་འབད།",
|
||||
"settings.timeline.category.shell": "Shell",
|
||||
"settings.timeline.category.edit": "ཞུན་དག་ཚུ།",
|
||||
"settings.timeline.category.thinking": "བསམ་ཤེས།",
|
||||
"settings.timeline.category.subagents": "ཡན་ལག་ལས་ཚབ་ཚུ།",
|
||||
"settings.timeline.category.notices": "གསལ་བསྒྲགས།",
|
||||
"settings.timeline.category.tools": "ལག་ཆ་གཞན།",
|
||||
"settings.general.row.mobileDiffWrap.description":
|
||||
"འཕྲེད་ལ་བཤུད་སྒྲིལ་འབད་ནིའི་ཚབ་ལུ་ འགྲུལ་འཕྲིན་ཁྱད་པར་ཚུ་ནང་གྲལ་ཐིག་རིངམོ་ཚུ་བསྡམས།",
|
||||
"provider.connect.error.unsupportedFields": "བདེན་བཤད་འབྲི་ཤོག་འདི་ནང་ རྒྱབ་སྐྱོར་མེད་པའི་ས་སྒོ་ཚུ་ཡོདཔ་ཨིན།",
|
||||
"session.review.filesChangedCount.one": "{{count}} ཡིག་སྣོད་བསྒྱུར་བཅོས་འབད་ཡོདཔ།",
|
||||
"session.review.filesChangedCount.other": "{{count}} ཡིག་སྣོད་ཚུ་བསྒྱུར་བཅོས་འབད་ཡོདཔ།",
|
||||
"settings.about.writtenByNames": "{{names}}གིས་བྲིས།",
|
||||
"settings.about.illustratedByNames": "{{names}} གིས་པར་རིས་བཀོད་ཡོད།",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline":
|
||||
"{{host}} ལུ་མཐུད་མེད། ཁྱོད་ཀྱི་ཟིན་བྲིས་འདི་ཉར་ཚགས་འབད་ཡོདཔ་ཨིན། ཐག་རིང་གི་ལཱ་འདི་ད་ལྟོ་ཡང་གཡོག་བཀོལ་དོ་འོང་།",
|
||||
"ssh.placeholder": "ssh ལག་ལེན་པ@དཔེ།com",
|
||||
"ssh.add": "SSH སར་བར་ཁ་སྐོང་འབད།",
|
||||
"ssh.server.menu.label": "SSH སར་བར་",
|
||||
"ssh.target": "ཧོསིཊི་ཡང་ན་ SSH བརྡ་བཀོད་",
|
||||
"ssh.connect": "མཐུད།",
|
||||
"ssh.connectTo": "{{host}} ལུ་མཐུད།",
|
||||
"ssh.authenticate": "SSH བདེན་བཤད་",
|
||||
"ssh.action.authenticate": "བདེན་བཤད་འབད།",
|
||||
"ssh.session.disconnected": "SSH མཐུད་ལམ་ཤུགས་མེད་",
|
||||
"ssh.session.connecting": "SSH སར་བར་ལུ་མཐུད་དོ",
|
||||
"ssh.session.reconnectDescription":
|
||||
"ལཱ་ཡུན་འདི་བལྟ་ནི་དང་ལཱ་འཕྲོ་མཐུད་འབད་ནི་ལུ་ ལོག་སྟེ་མཐུད། ཁྱོད་ཀྱི་ཐག་རིང་ལཱ་ཡུན་འདི་ཉམས་སྲུང་འབད་དེ་ཡོད།",
|
||||
"ssh.session.reconnect": "ལོག་མཐུད།",
|
||||
"ssh.authenticationRequired": "{{host}} གི་དོན་ལུ་བདེན་བཤད་དགོཔ་ཨིན།",
|
||||
"ssh.trust": "བློ་གཏད་དང་འབྲེལ་མཐུད།",
|
||||
"ssh.continue": "འཕྲོ་མཐུད།",
|
||||
"ssh.retry": "བསྐྱར་དུ་ཚོད་ལྟ་",
|
||||
"ssh.update": "དུས་མཐུན་བཟོ་སྟེ་ ལོག་སྟེ་མཐུད།",
|
||||
"ssh.openProject": "ལས་གཞི་ཁ་ཕྱེ།",
|
||||
"ssh.project": "{{host}} གུ་ལས་འགུལ་ཁ་ཕྱེ།",
|
||||
"ssh.disconnect": "མཐུད་ལམ་བཏོག",
|
||||
"ssh.forget": "མཐུད་ལམ་བརྗེད།",
|
||||
"ssh.stage.disconnected": "མཐུད་ལམ་བཏོག་ཡོདཔ། ཐག་རིང་གི་སར་བར་འདི་གཡོག་བཀོལ་བའི་བསྒང་རང་བཞགཔ་ཨིན།",
|
||||
"ssh.stage.connecting": "SSH བརྒྱུད་དེ་མཐུད་དོ...",
|
||||
"ssh.stage.checking": "OpenCode བརྟག་དཔྱད་འབད་དོ།...",
|
||||
"ssh.stage.downloading": "སར་བར་ཕབ་ལེན་འབད་དོ།...",
|
||||
"ssh.stage.uploading": "སར་བར་སྐྱེལ་བཙུགས་འབད་དོ།...",
|
||||
"ssh.stage.starting": "OpenCode ལུ་མཐུད་དོ...",
|
||||
"ssh.stage.ready": "འབྲེལ་མཐུད་འབད་ཡོདཔ།",
|
||||
"ssh.stage.authentication": "བདེན་བཤད་འབད་དགོ",
|
||||
"ssh.stage.incompatible": "སར་བར་དུས་མཐུན་བཟོ་དགོ",
|
||||
"ssh.stage.failed": "མཐུད་ལམ་འཐུས་ཤོར་བྱུང་ཡོདཔ།",
|
||||
"ssh.error.input":
|
||||
"ཧོསིཊི་ཡང་ན་ SSH མཐུད་ལམ་བརྡ་བཀོད་ཅིག་བཙུགས། ཐག་རིང་བརྡ་བཀོད་དང་རྒྱབ་སྐྱོར་མ་འབད་བའི་ SSH གདམ་ཁ་ཚུ་ འབད་མི་ཆོག།",
|
||||
"ssh.error.connection": "SSH མཐུད་ལམ་གཞི་བཙུགས་འབད་མ་ཚུགས། ཁྱོད་རའི་ཡོངས་འབྲེལ་དང་ SSH རིམ་སྒྲིག་ཞིབ་དཔྱད་འབད།",
|
||||
"ssh.error.platform":
|
||||
"ཐག་རིང་སྟེགས་རིས་འདི་ལུ་རྒྱབ་སྐྱོར་མི་འབད། རང་བཞིན་གཞི་སྒྲིག་ལུ་ད་ལྟོ་ x64 ཡང་ན་ arm64 གུ་ Linux ཡང་ན་ macOS དགོཔ་ཨིན།",
|
||||
"ssh.error.version": "ཐག་རིང་ཞབས་ཏོག་འདི་ མཐུད་མ་འབད་བའི་ཧེ་མ་ ཌེཀསི་ཊོཔ་ཐོན་རིམ་འདི་དང་ མཐུན་སྒྲིག་འབད་དགོ།",
|
||||
"ssh.error.install":
|
||||
"ཐག་རིང་སར་བར་ གཞི་བཙུགས་འབད་མ་ཚུགས། མཐུད་ལམ་དང་ ཌིཀསི་གི་ས་སྟོང་ དེ་ལས་ tar དེ་གཞི་བཙུགས་འབད་ཡོདཔ་ཨིན་ན་ ཞིབ་དཔྱད་འབད།",
|
||||
"ssh.error.unpublished":
|
||||
"ཌེཀསི་ཊོཔ་ཐོན་རིམ་འདི་ལུ་ དཔར་བསྐྲུན་འབད་ཡོད་པའི་ཐག་རིང་སར་བར་མེད། གོང་འཕེལ་བཟོ་བསྐྲུན་ཚུ་གི་དོན་ལུ་ ཧོསིཊི་གུ་ V2 གཞི་བཙུགས་འབད་དེ་འགོ་བཙུགས་ཞིནམ་ལས་ ལོག་སྟེ་འབད་རྩོལ་བསྐྱེད།",
|
||||
"ssh.error.service": "SSH མཐུད་ཡོད་རུང་ OpenCode སར་བར་འདི་གྲ་སྒྲིག་མ་འགྱོ་བས།",
|
||||
"ssh.error.host-key":
|
||||
"ཧོསིཊི་གི་ངོ་རྟགས་འདི་བདེན་དཔྱད་འབད་མ་ཚུགས། ཁྱོད་ཀྱི་ SSH ཤེས་རྟོགས་ཡོད་པའི་ཧོསིཊི་ཚུ་དུས་མཐུན་མ་བཟོ་བའི་ཧེ་མ་ དེ་གི་མཛུབ་མོའི་པར་བཤུས་བདེན་དཔྱད་འབད།",
|
||||
"ssh.error.ssh-missing":
|
||||
"OpenSSH མ་ཐོབ། OpenSSH མཁོ་སྤྲོད་པ་ཅིག་གཞི་བཙུགས་འབད་ཞིནམ་ལས་ ssh འདི་ PATH གུ་འཐོབ་ཚུགསཔ་ངེས་གཏན་བཟོ།",
|
||||
"command.browser.open": "བརའུ་ཟར་ཁ་ཕྱེ།",
|
||||
"command.browser.reload": "བརའུ་ཟར་ཤོག་ལེབ་ལོག་བཙུགས་",
|
||||
"command.session.summary.toggle": "བཅུད་དོན་སོར་བསྒྱུར་",
|
||||
"mcp.auth.interactiveForm": "MCP སར་བར་ {{name}} ལུ་ འབྲེལ་མཐུན་བདེན་བཤད་འབྲི་ཤོག་ཅིག་དགོཔ་ཨིན།",
|
||||
"server.connect.title": "སར་བར་ཅིག་ལུ་མཐུད།",
|
||||
"server.connect.description": "འགོ་བཙུགས་ནིའི་དོན་ལུ་ ཁྱོད་རའི་སར་བར་ཁ་བྱང་དང་ཆོག་ཡིག་བཙུགས།",
|
||||
"server.connect.button": "མཐུད།",
|
||||
"server.connect.address.invalid": "ནུས་ཅན་ HTTP ཡང་ན་ HTTPS སར་བར་ཁ་བྱང་ཅིག་བཙུགས།",
|
||||
"server.connect.failed": "མཐུད་མ་ཚུགས། སར་བར་ཁ་བྱང་དང་ཆོག་ཡིག་ཞིབ་དཔྱད་འབད་ཞིནམ་ལས་ ལོག་སྟེ་འབད་རྩོལ་བསྐྱེད།",
|
||||
"server.connect.pair.description":
|
||||
"ཁྱོད་རའི་མཐུད་ལམ་རྒྱས་བཤད་ཚུ་ཐོབ་ནིའི་དོན་ལུ་ ཁྱོད་རའི་གློག་རིག་གུ་བརྡ་བཀོད་འདི་གཡོག་བཀོལ།",
|
||||
"server.connect.scan": "QR གསང་གྲངས་པར་བཤུས་",
|
||||
"server.connect.scan.description": "ཁྱོད་རའི་པར་ཆས་འདི་ opencode pair གིས་སྟོན་མི་ QR གསང་ཡིག་ལུ་སྟོན་དགོ།",
|
||||
"server.connect.scan.invalid":
|
||||
"འདི་ OpenCode ཆ་སྒྲིག་ཨང་རྟགས་ཅིག་མེན། opencode pair གིས་སྟོན་ཡོད་པའི་ཨང་རྟགས་འདི་པར་བཤུས་འབད།",
|
||||
"server.connect.camera": "པར་ཆས་ཆ་སྒྲིག་འབད་དོ།",
|
||||
"server.connect.camera.starting": "པར་ཆས་ཁ་ཕྱེ་དོ...",
|
||||
"server.connect.mixedContent":
|
||||
"HTTPS ཤོག་ལེབ་ཅིག་ལས་ HTTP སར་བར་འདི་ལུ་མཐུད་མ་ཚུགས། དེ་གི་ཚབ་ལུ་ HTTPS སར་བར་ཁ་བྱང་ཅིག་ལག་ལེན་འཐབ།",
|
||||
"server.connect.camera.insecure": "QR པར་ལེན་འབད་ནི་ལུ་ ཤོག་ལེབ་འདི་ HTTPS ཡང་ན་ localhost གུ་ཁ་ཕྱེ་དགོཔ་ཨིན།",
|
||||
"server.connect.camera.unavailable": "བརྡ་འཚོལ་འདི་ལུ་པར་ཆས་མེད། ཁྱོད་རའི་མཐུད་ལམ་རྒྱས་བཤད་ཚུ་ལག་ཐོག་ལས་བཙུགས།",
|
||||
"server.connect.camera.error":
|
||||
"པར་ཆས་ཁ་ཕྱེ་མ་ཚུགས། པར་ཆས་འཛུལ་སྤྱོད་འབད་བཅུགཔ་ ཡང་ན་ ཁྱོད་རའི་མཐུད་ལམ་རྒྱས་བཤད་ཚུ་ལག་ཐོག་ལས་བཙུགས།",
|
||||
"dialog.server.menu.remove": "བཏོན་བཏང་",
|
||||
"file.error.notFound": "ཡིག་སྣོད་འཚོལ་མ་ཐོབ།: {{name}}",
|
||||
"home.workspaceTip": "བསྒྱུར་བཅོས་ཚུ་སོ་སོ་སྦེ་བཞག་ནི་ལུ་ ལཱ་གི་ས་སྒོ་གསརཔ་ཅིག་ནང་ ཤུལ་མམ་གྱི་ལཱ་ཡུན་འགོ་བཙུགས།",
|
||||
"session.tab.browser": "བརའུ་ཟར་",
|
||||
"session.tab.add": "མཆོང་ལྡེ་ཁ་སྐོང་",
|
||||
"session.queue.attachments.one": "པ་ལཱསི་ {{count}} མཐུད་སྣེ།",
|
||||
"session.queue.attachments.other": "དེ་ལས་ {{count}} མཐུད་སྣེ་ཚུ་",
|
||||
"session.browser.address": "བརྡ་འཚོལ་ཁ་བྱང་",
|
||||
"session.browser.replaced": "བརའུ་ཟར་ཚད་འཛིན་འདི་ ཌེཀསི་ཊོཔ་སྒོ་སྒྲིག་གཞན་མི་ཅིག་ནང་ སྤོ་བཤུད་འབད་ཡི།",
|
||||
"session.browser.suspended": "བརའུ་ཟར་བཀག་བཞག་ཡོདཔ། ལོག་སྟེ་མཐུད་ནིའི་དོན་ལུ་ ལཱ་ཡུན་འདི་དང་གཅིག་ཁར་ འབྲེལ་བ་འཐབ།",
|
||||
"session.browser.address.placeholder": "ཡུ་ཨར་ཨེལ་བཙུགས།",
|
||||
"settings.backToSettings": "གཞི་སྒྲིག་ལུ་ལོག་འགྱོ།",
|
||||
"settings.backToProjects": "ལས་འགུལ་ཚུ་ལུ་ལོག་འགྱོ།",
|
||||
"settings.search.placeholder": "འཚོལ་ཞིབ་",
|
||||
"settings.search.results": "སྒྲིག་སྟངས་གྲུབ་འབྲས།",
|
||||
"settings.search.group.pages": "ཤོག་ངོས་",
|
||||
"settings.search.group.settings": "སྒྲིག་སྟངས་",
|
||||
"settings.search.group.projects": "ལས་གཞི།",
|
||||
"settings.search.group.servers": "སར་བར",
|
||||
"settings.search.result": "{{title}}, {{scope}}, {{page}}",
|
||||
"settings.search.page": "{{title}}, {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}, {{page}}",
|
||||
"settings.search.empty": "{{query}} གི་དོན་ལུ་གྲུབ་འབྲས་མེད།",
|
||||
"settings.search.empty.query": '"{{query}}"',
|
||||
"settings.search.refine": "དམིགས་བསལ་གྱི་གྲུབ་འབྲས་མངམ་བལྟ་ནི་ལུ་ ཁྱོད་རའི་འཚོལ་ཞིབ་འདི་ཕྲང་ཕྲངམ་བཟོ།",
|
||||
"settings.server.description": "སར་བར་འདི་གི་མཐུད་ལམ་དང་དགའ་གདམ་ཚུ་འཛིན་སྐྱོང་འཐབ།",
|
||||
"settings.server.section.connection": "མཐུད་ལམ་",
|
||||
"settings.server.preferences.websearch.title": "ཕྱོགས་གསུམ་པའི་འཚོལ་ཞིབ།",
|
||||
"settings.server.preferences.websearch.description":
|
||||
"ཝེབ་འཚོལ་ཞིབ་འབད་ནི་ལུ་ལག་ལེན་འཐབ་མི་ འཚོལ་ཞིབ་བྱིན་མི་ལས་ཚབ་ཚུ་སེལ་འཐུ་འབད།",
|
||||
"settings.projects.search.placeholder": "ལས་གཞི་འཚོལ་ཞིབ་",
|
||||
"project.settings.name.title": "ལས་འགུལ་གྱི་མིང་",
|
||||
"project.settings.name.description": "ལས་འགུལ་འདི་གི་དོན་ལུ་ OpenCode ཡོངས་རྫོགས་ནང་སྟོན་ཡོད་པའི་མིང་།",
|
||||
"project.settings.icon.description": "གྲོས་འཆར་: ༡༢༨×༡༢༨px. གཟུགས་བརྙན་ཅིག་སྐྱེལ་བཙུགས་འབད་ནི་ལུ་ཨེབ་གཏང་ཡང་ན་འདྲུད།",
|
||||
"project.settings.color.description":
|
||||
"སྲོལ་སྒྲིག་གཟུགས་བརྙན་གཞི་སྒྲིག་མ་འབད་བའི་སྐབས་ལས་འགུལ་ངོས་དཔར་གྱི་དོན་ལུ་ལག་ལེན་འཐབ་ཡོདཔ་ཨིན།",
|
||||
"project.settings.worktree.startup.description": "ལཱ་གི་ཤིང་གསརཔ་གསར་བསྐྲུན་འབད་བའི་ཤུལ་ལས་ཚར་གཅིག་གཡོག་བཀོལཝ་ཨིན།",
|
||||
"project.settings.worktree.startup.hint.base": "གཞི་རྟེན་ལཱ་ཤིང་གི་དོན་ལུ་ $OPENCODE_WORKTREE_BASE ལག་ལེན་འཐབ།",
|
||||
"project.settings.worktree.startup.hint.new": "ལཱ་གི་ཤིང་གསརཔ་གི་དོན་ལུ་ $OPENCODE_WORKTREE_PATH ལག་ལེན་འཐབ།",
|
||||
"project.settings.extensions.empty.mcps.title": "ད་ལྟོ་ MCPs མེད།",
|
||||
"project.settings.extensions.empty.mcps.description": "MCPs ལུ་ཐོབ་ཚུགས་པའི་ OpenCode འདི་ན་འབྱུངམ་ཨིན།",
|
||||
"project.settings.extensions.empty.plugins.title": "ད་ལྟོ་པ་ལག་ཨིནསི་མེད།",
|
||||
"project.settings.extensions.empty.plugins.description": "OpenCode ལུ་ཡོད་པའི་པ་ལག་ཨིན་ཚུ་ ནཱ་ལུ་འབྱུངམ་ཨིན།",
|
||||
"project.settings.extensions.empty.skills.title": "ད་ལྟོ་རིག་རྩལ་མེད།",
|
||||
"project.settings.extensions.empty.skills.description": "OpenCode ལུ་ཡོད་པའི་རིག་རྩལ་ཚུ་ ནཱ་ལུ་འབྱུང་འོང་།",
|
||||
"project.settings.extensions.lsp.configured": "རིམ་སྒྲིག་འབད་ཡོད་པའི་སྐད་ཡིག་སར་བར་ཚུ།",
|
||||
"project.settings.extensions.lsp.status.enabled": "རིམ་སྒྲིག་ནང་ལུ་ལྕོགས་ཅན་བཟོ་ཡོདཔ།",
|
||||
"project.settings.extensions.lsp.status.disabled": "རིམ་སྒྲིག་ནང་ལུ་ལྕོགས་མིན་བཟོ་ཡོདཔ།",
|
||||
"project.settings.extensions.lsp.empty.title": "སྐད་ཡིག་སར་བར་ཚུ་རིམ་སྒྲིག་མ་འབད་བས།",
|
||||
"project.settings.extensions.lsp.empty.description":
|
||||
"ལས་འགུལ་འདི་གི་དོན་ལུ་རིམ་སྒྲིག་འབད་ཡོད་པའི་སྐད་ཡིག་སར་བར་ཚུ་ནཱ་ལུ་འབྱུངམ་ཨིན།",
|
||||
"project.settings.extensions.lsp.disabled.title": "སྐད་ཡིག་སར་བར་ཚུ་ལྕོགས་མིན་བཟོ་ཡོདཔ།",
|
||||
"project.settings.extensions.lsp.disabled.description":
|
||||
"LSP འདི་ལས་འགུལ་འདི་གི་རིམ་སྒྲིག་ནང་ལུ་ལྕོགས་མིན་བཟོ་ཡོདཔ་ཨིན།",
|
||||
"project.settings.extensions.lsp.loadFailed": "སྐད་ཡིག་སར་བར་རིམ་སྒྲིག་མངོན་གསལ་འབད་མ་ཚུགས།",
|
||||
"project.settings.extensions.lsp.retry": "བསྐྱར་དུ་ཚོད་ལྟ་",
|
||||
"settings.timeline.summary": "{{preset}}:",
|
||||
"settings.timeline.group": "སྡེ་ཚན་",
|
||||
"settings.timeline.collapse": "བརྡིབས་",
|
||||
"settings.timeline.visibility.show": "སྟོན།",
|
||||
"settings.timeline.visibility.hide": "སྦ་བཞག",
|
||||
"settings.timeline.visibility.label": "{{activity}} མཐོང་ཚུལ།",
|
||||
"settings.timeline.grouped.label": "{{activity}} སྡེ་ཚན་བཟོ་ཡོདཔ།",
|
||||
"settings.timeline.collapsed.label": "{{activity}} རྡིབ་སོང་",
|
||||
"session.new.workspace.search.empty": "མཐུན་སྒྲིག་ལཱ་ཤིང་མེད།",
|
||||
"settings.workspaces.description": "ལཱ་གི་ཤིང་ཚུ་བསྐྱར་ཞིབ་འབད་དེ་ ཌིཀསི་ལག་ལེན་འཛིན་སྐྱོང་འཐབ།",
|
||||
"settings.workspaces.empty.description": "OpenCode ནང་གསར་བསྐྲུན་འབད་ཡོད་པའི་ལཱ་ཤིང་ཚུ་ ནཱ་ལུ་འབྱུངམ་ཨིན།",
|
||||
"settings.workspaces.sessions.filtered.one": "{{count}} ལཱ་ཡུན་",
|
||||
"settings.workspaces.sessions.filtered.other": "{{count}} ལཱ་ཡུན་ཚུ་",
|
||||
"settings.workspaces.deleteAll.confirm.one":
|
||||
"འདི་གིས་ {{count}} སེལ་འཐུ་འབད་ཡོད་པའི་ལཱ་གི་ཤིང་འདི་ རྟག་བརྟན་སྦེ་བཏོན་གཏང་འོང་།",
|
||||
"settings.workspaces.deleteAll.confirm.other":
|
||||
"འདི་གིས་ {{count}} སེལ་འཐུ་འབད་ཡོད་པའི་ལཱ་གི་ཤིང་ཚུ་ རྟག་བརྟན་སྦེ་བཏོན་གཏང་འོང་།",
|
||||
"settings.workspaces.deleteWithoutSessions": "ལཱ་ཡུན་མེད་པའི་ལཱ་ཤིང་ཚུ་བཏོན་གཏང་།",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"འདི་གིས་ འབྲེལ་མཐུད་ཡོད་པའི་ལཱ་ཡུན་ཚུ་མེད་པར་ {{count}} ལཱ་ཤིང་འདི་རྟག་བརྟན་སྦེ་བཏོན་གཏང་འོང་།",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"འདི་གིས་ འབྲེལ་མཐུད་ཡོད་པའི་ལཱ་ཡུན་ཚུ་མེད་པའི་ {{count}} ལཱ་ཤིང་ཚུ་ རྟག་བརྟན་སྦེ་བཏོན་གཏང་འོང་།",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"མཉམ་བསྡོམས་མ་འབད་བའི་བསྒྱུར་བཅོས་ཚུ་ཡང་ན་ ཤུགས་ལྡན་གནས་ཁོངས་ཚུ་ཡོད་པའི་ལཱ་གི་ཤིང་ཚུ་བཞག་འོང་།",
|
||||
"settings.workspaces.delete.button": "ལཱ་གི་ཤིང་ཚུ་བཏོན་གཏང་།",
|
||||
"workspace.lifecycle.deleting": "བཏོན་གཏང་དོ...",
|
||||
"session.summary.tooltip": "བཅུད་བསྡུས།",
|
||||
"session.summary.server": "རྒྱ་བསྐྱེད་",
|
||||
"session.summary.chooseProject": "ལས་འགུལ་གདམ་ཁ་རྐྱབས།",
|
||||
"session.summary.mcp.onCreation": "ལཱ་གི་ཤིང་འདི་གསར་བསྐྲུན་འབད་བའི་སྐབས་འཇུག་སྤྱོད་འབདཝ་ཨིན།",
|
||||
"session.summary.mcp.prepareFailed": "MCP སར་བར་ཚུ་གྲ་སྒྲིག་འབད་མ་ཚུགས།",
|
||||
"session.summary.mcp.unavailable": "MCP སར་བར་ {{name}} འདི་ལཱ་ཤིང་འདི་ནང་འཐོབ་མི་ཚུགས།",
|
||||
"session.summary.mcp.signInBeforeSend": "བརྡ་སྟོན་མ་གཏང་པའི་ཧེ་མ་ {{name}} ལུ་ནང་བསྐྱོད་འབད།",
|
||||
"session.summary.mcp.notReady":
|
||||
"MCP སར་བར་ {{name}} འདི་གྲ་སྒྲིག་མེདཔ་ཨིན། བརྡ་སྟོན་མ་གཏང་པའི་ཧེ་མ་ དེ་གི་མཐུད་ལམ་འདི་སེལ་འཐུ་འབད།",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "རིམ་སྒྲིག་འབད་ཡོད་པའི་ MCP སར་བར་ཚུ་",
|
||||
"session.summary.plugins": "པ་ལག་ཨིན་",
|
||||
"session.summary.plugins.configured": "རིམ་སྒྲིག་འབད་ཡོད་པའི་པ་ལག་ཨིན་ཚུ་",
|
||||
"session.summary.skills": "རིག་རྩལ།",
|
||||
"session.summary.skills.configured": "རིམ་སྒྲིག་འབད་ཡོད་པའི་རིག་རྩལ།",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "འཐུས་ཤོར་བྱུང་ཡོདཔ།",
|
||||
"session.summary.retry": "བསྐྱར་དུ་ཚོད་ལྟ་",
|
||||
"session.summary.connecting": "མཐུད་པའི་...",
|
||||
"session.summary.needsAuth": "ནང་བསྐྱོད་འབད་དགོ",
|
||||
"session.summary.configure": "རིམ་སྒྲིག་ཡིག་སྣོད་",
|
||||
"session.summary.copyConfigPath": "རིམ་སྒྲིག་ཡིག་སྣོད་འགྲུལ་ལམ་འདྲ་བཤུས་རྐྱབས།",
|
||||
"session.summary.configFileMissing": "རིམ་སྒྲིག་ཡིག་སྣོད་འཚོལ་མ་ཐོབ།",
|
||||
"session.summary.mcp.empty": "MCP སར་བར་ཚུ་རིམ་སྒྲིག་མ་འབད་བས།",
|
||||
"session.summary.mcp.add": "opencode.json ནང་ལུ་སར་བར་ཚུ་ཁ་སྐོང་འབད།",
|
||||
"session.summary.plugins.manage": "opencode.json ནང་ལུ་ པ་ལག་ཨིན་ཚུ་འཛིན་སྐྱོང་འཐབ།",
|
||||
"session.summary.plugins.empty": "པ་ལག་ཨིན་ཚུ་རིམ་སྒྲིག་མ་འབད་བས།",
|
||||
"session.summary.plugins.add": "opencode.json ནང་ལུ་ པ་ལག་ཨིན་ཚུ་ཁ་སྐོང་འབད།",
|
||||
"session.summary.skills.manage": "opencode.json ནང་རིག་རྩལ་འཛིན་སྐྱོང་འཐབ།",
|
||||
"session.summary.skills.empty": "རིག་རྩལ་རིམ་སྒྲིག་མ་འབད་བས།",
|
||||
"session.summary.skills.add": "opencode.json ནང་ལུ་རིག་རྩལ་ཁ་སྐོང་འབད།",
|
||||
"session.summary.lsp.configured": "རིམ་སྒྲིག་འབད་ཡོད་པའི་ LSPs",
|
||||
"session.summary.lsp.empty": "LSP སར་བར་ཚུ་རིམ་སྒྲིག་མ་འབད་བས།",
|
||||
"session.summary.lsp.manage": "opencode.json ནང་ལུ་ LSP འཛིན་སྐྱོང་འཐབ།",
|
||||
"workspace.delete.location": "ས་གནས་",
|
||||
"common.color.orange": "ལི་ཝང་",
|
||||
"common.color.yellow": "སེར་པོ་",
|
||||
"common.color.cyan": "སྔོ་ལྗང་",
|
||||
"common.color.green": "ལྗང་ཁུ",
|
||||
"common.color.red": "དམརཔོ་",
|
||||
"common.color.pink": "ཤ་ཁ་",
|
||||
"common.color.blue": "སྔོན་པོ་",
|
||||
"common.color.purple": "མུ་མེན་",
|
||||
"common.color.gray": "སྐྱ་ཐལ་",
|
||||
"toast.migration.progress.migratingSessions.current": "ལཱ་ཡུན་ཚུ་གནས་སྤོ་འབད་དོ་ {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "ལཱ་ཡུན་ཚུ་གནས་སོར་འབད་དོ་ {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "གནད་སྡུད་གནས་སྤོ་འབད་དོ་",
|
||||
"toast.migration.progress.working.current": "གནད་སྡུད་གནས་སྤོ་འབད་དོ་ {{current}}",
|
||||
"toast.migration.progress.working.progress": "གནད་སྡུད་གནས་སྤོ་འབད་དོ་ {{current}}/{{total}}",
|
||||
"session.browser.unsupported": "ཌེཀསི་ཊོཔ་གློག་རིམ་འདི་གིས་ བརའུ་ཟར་པེན་ལུ་རྒྱབ་སྐྱོར་མི་འབད།",
|
||||
"command.debugBar.toggle": "རྐྱེན་སེལ་ཕྲ་རིང་སྟོན་ནི་ཡང་ན་སྦ་ནི།",
|
||||
"command.session.location.cycle": "ལཱ་ཡུན་གྱི་ས་གནས་སོར།",
|
||||
"dialog.provider.anthropic.note": "API ལྡེ་མིག་བརྒྱུད་དེ་ Claude དཔེ་ཚད་ཚུ་ལུ་ཐད་ཀར་འཛུལ་སྤྱོད།",
|
||||
"provider.connect.title.anthropicProMax": "Anthropic ཐོག་ལས་ནང་བསྐྱོད།",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"prompt.toast.uploading.cancel": "སྐྱེལ་བཙུགས་ཆ་མེད་བཏང་།",
|
||||
"prompt.toast.uploading.cancelFile": "{{filename}} སྐྱེལ་བཙུགས་འབད་ནི་ཆ་མེད་བཏང་།",
|
||||
"prompt.toast.uploadFailed.title": "སྐྱེལ་བཙུགས་འཐུས་ཤོར།",
|
||||
"session.browser.empty.title": "URL བཙུགས།",
|
||||
"session.browser.empty.description": "ཡང་ན་ “གློག་རིམ་བརའུ་ཟར་ནང་ཁ་ཕྱེ” ཟེར་བའི་ནུས་སྤེལ་བྱིན།",
|
||||
"session.browser.failed.title": "URL ལུ་ལྷོད་མི་ཚུགས།",
|
||||
"session.browser.failed.description": "URL དང་ཁྱོད་ཀྱི་མཐུད་ལམ་ཞིབ་དཔྱད་འབད་དེ་ལོག་སྟེ་འབད།",
|
||||
"debugBar.providerAriaLabel": "བྱིན་མིའི་ལཱ་ཤུགས་བརྟག་དཔྱད།",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttft.tip": "བྱིན་མི་ལུ་ཞུ་བ་བཏང་བ་ལས་དཔེ་ཚད་ཀྱི་ཐོན་འབྲས་དང་པ་ཚུན་གྱི་དུས་ཚོད།",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.ttfa.tip": "བྱིན་མི་ལུ་ཞུ་བ་བཏང་བ་ལས་ལན་གྱི་ཚིག་ཡིག་དང་པ་ཚུན་གྱི་དུས་ཚོད།",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.tps.tip": "དཔེ་ཚད་ཀྱི་ཐོན་འབྲས་དང་པའི་ཤུལ་ལས་སྐར་ཆ་རེར་ཐོན་འབྲས་ཊོ་ཀེན།",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
"debugBar.e2e.tip": "བྱིན་མི་ལུ་ཞུ་བ་བཏང་བ་ལས་ལན་གྱི་རྒྱུན་ལམ་མཇུག་བསྡུ་ཚུན་གྱི་དུས་ཚོད།",
|
||||
"settings.updates.action.download": "OpenCode ཕབ་ལེན་འབད།",
|
||||
"settings.updates.migration.title": "Beta ལས་ Stable ལུ་སྤོ།",
|
||||
"settings.updates.migration.description":
|
||||
"ད་ལྟོའི་རིང་ལུ་ OpenCode Beta འདི་ OpenCode Stable ལུ་སྤོ་དོ། དུས་མཐུན་ཚུ་འཕྲོ་མཐུད་དེ་ཐོབ་ནི་ལུ་ ཐོན་རིམ་ {{version}} ཕབ་ལེན་འབད་དེ་ ཌིཀསི་གཟུགས་བརྙན་ལས་ OpenCode གཞི་བཙུགས་འབད།",
|
||||
}
|
||||
|
||||
@@ -1080,6 +1080,47 @@ export const dict = {
|
||||
"session.delete.confirm": 'Διαγραφή συνεδρίας "{{name}}";',
|
||||
"session.delete.button": "Διαγραφή συνεδρίας",
|
||||
"workspace.new": "Νέος χώρος εργασίας",
|
||||
"common.viewAll": "Προβολή όλων",
|
||||
"session.new.workspace.local.tooltip": "Χρήση του τρέχοντος checkout",
|
||||
"session.new.workspace.new.tooltip": "Δημιουργία απομονωμένου checkout",
|
||||
"session.new.workspace.fromBranch": "από {{branch}}",
|
||||
"session.new.workspace.trigger.tooltip": "Επιλέξτε πού θα εκτελεστεί η συνεδρία",
|
||||
"session.new.workspace.search.placeholder": "Αναζήτηση χώρων εργασίας",
|
||||
"settings.tab.workspaces": "Χώροι εργασίας",
|
||||
"settings.workspaces.filter.all": "Όλα τα έργα",
|
||||
"settings.workspaces.empty": "Δεν υπάρχουν χώροι εργασίας",
|
||||
"settings.workspaces.count.one": "{{count}} χώρος εργασίας",
|
||||
"settings.workspaces.count.other": "{{count}} χώροι εργασίας",
|
||||
"settings.workspaces.sessions.one": "{{count}} συνεδρία στο {{project}}",
|
||||
"settings.workspaces.sessions.other": "{{count}} συνεδρίες στο {{project}}",
|
||||
"settings.workspaces.lastActiveSession": "Τελευταία ενεργή συνεδρία",
|
||||
"settings.workspaces.deleteAll": "Διαγραφή όλων των χώρων εργασίας",
|
||||
"settings.workspaces.delete.warning":
|
||||
"Ο κατάλογος και ο κλάδος του χώρου εργασίας θα διαγραφούν οριστικά, μαζί με τυχόν μη συγχωνευμένες αλλαγές που εμφανίζονται παρακάτω.",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"Τα δέντρα εργασίας με μη συγχωνευμένες αλλαγές, συνδεδεμένες περιόδους σύνδεσης ή ενεργές τοποθεσίες θα διατηρηθούν.",
|
||||
"settings.workspaces.delete.blocked.active": "Ο ενεργός χώρος εργασίας δεν μπορεί να διαγραφεί.",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"Οι συνδεδεμένες συνεδρίες θα διατηρηθούν, αλλά ο κατάλογος εργασίας τους θα διαγραφεί οριστικά.",
|
||||
"settings.workspaces.default.title": "Προεπιλεγμένο περιβάλλον",
|
||||
"settings.workspaces.default.description": "Επιλέξτε πού θα ξεκινούν οι νέες συνεδρίες",
|
||||
"settings.workspaces.default.lastUsed": "Τελευταίο χρησιμοποιημένο ανά έργο",
|
||||
"settings.workspaces.default.local": "Τοπικός κατάλογος",
|
||||
"settings.workspaces.default.new": "Νέος χώρος εργασίας",
|
||||
"workspace.move.title": "Μετακίνηση σε χώρο εργασίας",
|
||||
"workspace.move.menu.title": "Μετακίνηση συνεδρίας σε",
|
||||
"workspace.move.failed": "Αποτυχία μετακίνησης συνεδρίας",
|
||||
"workspace.lifecycle.creating": "Δημιουργία χώρου εργασίας",
|
||||
"workspace.lifecycle.created": "Ο χώρος εργασίας δημιουργήθηκε",
|
||||
"workspace.lifecycle.starting": "Έναρξη συνεδρίας",
|
||||
"workspace.onboarding.title": "Απομονώστε συνεδρίες με χώρους εργασίας",
|
||||
"workspace.onboarding.description":
|
||||
"Κάθε συνεδρία έχει το δικό της checkout, ώστε να μην επηρεάζεται το τοπικό αποθετήριο",
|
||||
"workspace.lifecycle.moving": "Μετακίνηση σε χώρο εργασίας",
|
||||
"workspace.lifecycle.set": "Ο χώρος εργασίας ορίστηκε",
|
||||
"session.summary.title": "Λεπτομέρειες συνεδρίας",
|
||||
"session.summary.noBranch": "Χωρίς κλάδο",
|
||||
"session.summary.basedOn": "Βασίζεται στον κλάδο {{branch}}",
|
||||
"workspace.type.local": "τοπικό",
|
||||
"workspace.type.sandbox": "απομονωμένο περιβάλλον",
|
||||
"workspace.create.failed.title": "Αποτυχία δημιουργίας χώρου εργασίας",
|
||||
@@ -1105,4 +1146,444 @@ export const dict = {
|
||||
"workspace.reset.archived.many": "{{count}} θα αρχειοθετηθούν οι περίοδοι σύνδεσης.",
|
||||
"workspace.reset.note": "Αυτό θα επαναφέρει τον χώρο εργασίας ώστε να ταιριάζει με τον προεπιλεγμένο κλάδο.",
|
||||
"dialog.usageExceeded.dontShowAgain": "Να μην εμφανιστεί ξανά",
|
||||
"provider.disconnect.toast.noCredentials.description":
|
||||
"Δεν βρέθηκαν διαπιστευτήρια που μπορούν να αφαιρεθούν για τον πάροχο {{provider}}.",
|
||||
"provider.disconnect.toast.failed.description": "Αποτυχία αποσύνδεσης του παρόχου {{provider}}.",
|
||||
"toast.migration.failed.title": "Η μετεγκατάσταση δεδομένων απέτυχε",
|
||||
"command.session.background": "Μετακίνηση στο παρασκήνιο",
|
||||
"session.timeline.notice.finished": "Ο χρήστης {{actor}} ολοκλήρωσε",
|
||||
"session.timeline.notice.failed": "Ο χρήστης {{actor}} απέτυχε",
|
||||
"session.timeline.notice.cancelled": "Ο χρήστης {{actor}} ακυρώθηκε",
|
||||
"settings.tab.preferences": "Προτιμήσεις",
|
||||
"settings.tab.notifications": "Ειδοποιήσεις",
|
||||
"settings.tab.projects": "Έργα",
|
||||
"settings.tab.extensions": "Επεκτάσεις",
|
||||
"settings.preferences.description": "Προσαρμογή προτιμήσεων, θέματος και προεπιλεγμένης συμπεριφοράς",
|
||||
"settings.appearance.description": "Προσαρμογή θέματος και γραμματοσειρών",
|
||||
"settings.notifications.description": "Επιλέξτε πότε θα λαμβάνετε ειδοποιήσεις και θα ακούτε ήχους",
|
||||
"settings.shortcuts.description": "Προσαρμογή συντομεύσεων για συνηθισμένες ενέργειες",
|
||||
"settings.servers.description": "Διαχείριση συνδέσεων διακομιστή",
|
||||
"settings.projects.title": "Έργα",
|
||||
"settings.projects.description": "Διαχείριση ρυθμίσεων έργων σε αυτόν τον διακομιστή",
|
||||
"settings.projects.empty": "Δεν βρέθηκαν έργα",
|
||||
"settings.projects.server.all": "Όλοι οι διακομιστές",
|
||||
"settings.mcps.description": "Διαχείριση διακομιστών και εργαλείων Model Context Protocol (MCP)",
|
||||
"settings.extensions.description": "Διαχείριση επεκτάσεων που είναι διαθέσιμες σε αυτόν τον διακομιστή",
|
||||
"settings.extensions.tab.mcps": "MCP",
|
||||
"settings.extensions.tab.skills": "Δεξιότητες",
|
||||
"settings.extensions.availableAll": "Διαθέσιμο σε όλα τα έργα",
|
||||
"settings.extensions.manageConfig": "Διαχείριση στο opencode.json",
|
||||
"settings.extensions.addSkills": "Πώς να προσθέσετε δεξιότητες",
|
||||
"dialog.server.authenticate.title": "Έλεγχος ταυτότητας",
|
||||
"project.settings.general.description": "Διαχείριση ονόματος και εμφάνισης έργου",
|
||||
"project.settings.scripts": "Σενάρια",
|
||||
"project.settings.scripts.description": "Διαμόρφωση σεναρίων για αυτό το έργο",
|
||||
"project.settings.extensions.description": "Προβολή επεκτάσεων που είναι διαθέσιμες σε αυτό το έργο",
|
||||
"project.settings.extensions.tab.lsps": "LSP",
|
||||
"project.settings.extensions.added": "Προστέθηκε σε αυτό το έργο",
|
||||
"project.settings.extensions.shared": "Κοινόχρηστο με όλα τα έργα",
|
||||
"project.settings.extensions.lsp.detected": "Εντοπισμένοι διακομιστές γλώσσας",
|
||||
"project.settings.extensions.lsp.description": "Αυτόματος εντοπισμός από τους τύπους αρχείων",
|
||||
"project.settings.extensions.setupRequired": "Απαιτείται ρύθμιση",
|
||||
"settings.general.section.general": "Γενικά",
|
||||
"desktop.menu.installCli": "Εγκατάσταση CLI...",
|
||||
"desktop.cli.installed.title": "Το CLI εγκαταστάθηκε",
|
||||
"desktop.cli.installed.message":
|
||||
"Το CLI εγκαταστάθηκε στη διαδρομή {{path}}\n\nΕπανεκκινήστε το τερματικό για να χρησιμοποιήσετε την εντολή 'opencode2'.",
|
||||
"desktop.cli.failed.title": "Η εγκατάσταση απέτυχε",
|
||||
"desktop.cli.failed.message": "Αποτυχία εγκατάστασης του CLI: {{error}}",
|
||||
"command.project.copyID": "Αντιγραφή ID έργου",
|
||||
"command.session.copyID": "Αντιγραφή ID συνεδρίας",
|
||||
"server.row.incompatible":
|
||||
"Αυτός ο διακομιστής εκτελεί το OpenCode {{version}}, το οποίο δεν είναι συμβατό με αυτήν την εφαρμογή. Αναβαθμίστε τον σε OpenCode V2 για να συνεχίσετε.",
|
||||
"toast.session.copyID.failed.title": "Αποτυχία αντιγραφής του ID συνεδρίας",
|
||||
"toast.session.copyID.failed.description": "Παρουσιάστηκε σφάλμα κατά την αντιγραφή του ID συνεδρίας",
|
||||
"toast.project.copyID.failed.title": "Αποτυχία αντιγραφής του ID έργου",
|
||||
"toast.project.copyID.failed.description": "Παρουσιάστηκε σφάλμα κατά την αντιγραφή του ID έργου",
|
||||
"error.page.title.status": "Το αίτημα προς τον διακομιστή απέτυχε",
|
||||
"error.page.description.status": "Ο διακομιστής επέστρεψε απόκριση HTTP {{status}}.",
|
||||
"error.page.action.reload": "Επαναφόρτωση",
|
||||
"session.error.incompatible": "Αυτή η έκδοση διακομιστή δεν υποστηρίζεται",
|
||||
"session.error.incompatible.description":
|
||||
"Ο διακομιστής {{server}} εκτελεί το OpenCode {{version}}, το οποίο δεν είναι συμβατό με αυτήν την εφαρμογή. Αναβαθμίστε τον διακομιστή σε OpenCode V2 για να συνεχίσετε.",
|
||||
"session.background.moveInline": "Πατήστε {{keybind}} για να μετακινήσετε την εργασία που εκτελείται στο παρασκήνιο",
|
||||
"session.background.running": "Εκτελείται εργασία στο παρασκήνιο",
|
||||
"session.background.runningCount.one": "{{count}} στοιχείο εκτελείται στο παρασκήνιο",
|
||||
"session.background.runningCount.other": "{{count}} στοιχεία εκτελούνται στο παρασκήνιο",
|
||||
"settings.general.row.terminalPlacement.title": "Τοποθέτηση τερματικού",
|
||||
"settings.general.row.terminalPlacement.description": "Επιλέξτε πού ανοίγει το τερματικό στις συνεδρίες",
|
||||
"settings.general.row.terminalPlacement.side": "Στο πλάι",
|
||||
"settings.general.row.terminalPlacement.bottom": "Κάτω",
|
||||
"session.location.unavailable": "Η τοποθεσία της συνεδρίας δεν είναι διαθέσιμη",
|
||||
"session.location.description": "Επιλέξτε άλλον κατάλογο για να συνεχίσετε αυτή τη συνεδρία.",
|
||||
"session.location.choose": "Επιλογή καταλόγου",
|
||||
"session.location.worktree": "Επιλογή δέντρου εργασίας",
|
||||
"session.location.worktreesFailed": "Αποτυχία φόρτωσης των δέντρων εργασίας",
|
||||
"session.location.moving": "Μετακίνηση συνεδρίας…",
|
||||
"dialog.server.menu.hide": "Απόκρυψη από τη λίστα έργων",
|
||||
"dialog.server.menu.show": "Εμφάνιση στη λίστα έργων",
|
||||
"session.queue.count.one": "{{count}} στην ουρά",
|
||||
"session.queue.count.other": "{{count}} στην ουρά",
|
||||
"session.queue.steer": "Καθοδήγηση",
|
||||
"session.queue.send": "Αποστολή",
|
||||
"session.queue.steerTooltip": "Αποστολή χωρίς διακοπή",
|
||||
"session.queue.remove": "Αφαίρεση",
|
||||
"session.queue.reorder": "Αναδιάταξη προτροπής στην ουρά",
|
||||
"session.new.worktree.creating": "Δημιουργία δέντρου εργασίας",
|
||||
"settings.backToApp": "Επιστροφή στην εφαρμογή",
|
||||
"settings.appearance.section.experimental": "Πειραματικά",
|
||||
"settings.appearance.row.tabs.title": "Καρτέλες",
|
||||
"settings.appearance.row.tabs.description": "Επιλέξτε πώς διατάσσονται οι καρτέλες συνεδριών",
|
||||
"settings.appearance.row.tabs.horizontal": "Οριζόντια",
|
||||
"settings.appearance.row.tabs.vertical": "Κατακόρυφα",
|
||||
"settings.general.row.followUpBehavior.title": "Συμπεριφορά επόμενων μηνυμάτων",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"Επιλέξτε αν τα επόμενα μηνύματα θα μπαίνουν στην ουρά ή θα καθοδηγούν τον τρέχοντα γύρο. Χρησιμοποιήστε {{keybind}} για εναλλαγή.",
|
||||
"settings.general.row.followUpBehavior.queue": "Ουρά",
|
||||
"settings.general.row.followUpBehavior.steer": "Καθοδήγηση",
|
||||
"settings.general.row.reasoningMode.title": "Συλλογισμός μοντέλου",
|
||||
"settings.general.row.reasoningMode.description":
|
||||
"Επιλέξτε πώς εμφανίζεται ο συλλογισμός του μοντέλου στη λωρίδα χρόνου",
|
||||
"settings.general.row.reasoningMode.hidden": "Κρυφό",
|
||||
"settings.general.row.reasoningMode.compact": "Συμπτυγμένο",
|
||||
"settings.general.row.reasoningMode.full": "Πλήρες",
|
||||
"session.new.workspace.createFrom": "Δημιουργία από κλάδο",
|
||||
"session.new.workspace.branch.search.placeholder": "Αναζήτηση κλάδων",
|
||||
"toast.migration.progress.clearingOldEvents": "Εκκαθάριση παλιών συμβάντων",
|
||||
"toast.migration.progress.migratingSessions": "Μετεγκατάσταση συνεδριών",
|
||||
"session.new.workspace.existingLabel": "Δέντρο εργασίας",
|
||||
"desktop.onboarding.defaultProject": "Προεπιλεγμένο έργο",
|
||||
"home.projects.all": "Όλα τα έργα",
|
||||
"session.tab.files": "Αρχεία",
|
||||
"session.files.openTabs": "Άνοιγμα αρχείων",
|
||||
"session.tab.usage": "Χρήση",
|
||||
"session.view.select": "Προβολή συνεδρίας",
|
||||
"session.background.moveTasks": "Μετακινήστε το {{tasks}} στο παρασκήνιο",
|
||||
"session.background.moveRunning": "Μετακίνηση στο παρασκήνιο",
|
||||
"session.background.inBackground": "Εκτέλεση {{tasks}} στο παρασκήνιο",
|
||||
"session.background.tasksRunning.one": "Εκτέλεση εργασίας παρασκηνίου {{count}}",
|
||||
"session.background.tasksRunning.other": "Εκτελούνται εργασίες παρασκηνίου {{count}}",
|
||||
"session.background.combine": "{{first}} και {{second}}",
|
||||
"session.background.shell.one": "{{count}} Shell",
|
||||
"session.background.shell.other": "{{count}} Shell",
|
||||
"session.background.subagent.one": "{{count}} υποπράκτορας",
|
||||
"session.background.subagent.other": "{{count}} υποπράκτορες",
|
||||
"session.timeline.working": "Εργασία",
|
||||
"session.review.wrapLines": "Αναδίπλωση γραμμών",
|
||||
"session.websearch.title": "Αναζήτηση ιστού τρίτων",
|
||||
"session.websearch.description":
|
||||
"Επιλέξτε τους πράκτορες παρόχου αναζήτησης που χρησιμοποιούν για την αναζήτηση στον ιστό",
|
||||
"session.websearch.provider": "Αναζήτηση παρόχου",
|
||||
"session.websearch.any": "Οποιαδήποτε",
|
||||
"session.websearch.disable": "Μην χρησιμοποιείτε την αναζήτηση",
|
||||
"session.websearch.enable": "Ενεργοποίηση",
|
||||
"session.websearch.loadFailed": "Δεν ήταν δυνατή η φόρτωση παρόχων αναζήτησης.",
|
||||
"session.websearch.empty": "Δεν υπάρχουν διαθέσιμοι πάροχοι αναζήτησης.",
|
||||
"session.websearch.failed": "Δεν ήταν δυνατή η αποθήκευση της επιλογής σας. Δοκιμάστε ξανά.",
|
||||
"session.websearch.retry": "Επανάληψη",
|
||||
"session.new.worktree.draftPlaceholder": "Σχεδιάστε μια συνέχεια ενώ προετοιμάζεται το δέντρο εργασίας…",
|
||||
"session.search.placeholder": "Βρείτε…",
|
||||
"session.search.noResults": "Δεν βρέθηκαν αντιστοιχίες",
|
||||
"titlebar.tabs": "Καρτέλες",
|
||||
"titlebar.channel.local": "Τοπικό",
|
||||
"titlebar.channel.dev": "Dev",
|
||||
"titlebar.channel.beta": "Beta",
|
||||
"titlebar.toggleDebugTools": "Εναλλαγή εργαλείων εντοπισμού σφαλμάτων",
|
||||
"settings.tab.experimental": "Πειραματικό",
|
||||
"settings.experimental.description": "Δοκιμάστε πειραματικές λειτουργίες",
|
||||
"settings.tab.about": "Πληροφορίες",
|
||||
"settings.about.version": "Έκδοση {{version}}",
|
||||
"settings.about.devVersion": "ανάπτυξη",
|
||||
"settings.about.license": "Κυκλοφόρησε υπό την άδεια MIT",
|
||||
"settings.about.writtenBy": "Γράφτηκε από",
|
||||
"settings.about.illustratedBy": "Εικονογράφηση από",
|
||||
"settings.about.and": "και",
|
||||
"settings.about.otherContributor.one": "{{count}} άλλο",
|
||||
"settings.about.otherContributor.other": "{{count}} άλλοι",
|
||||
"settings.about.firstPublished": "Πρωτοδημοσιεύτηκε στο Μιζούρι των Η.Π.Α",
|
||||
"settings.about.firstIllustrated": "Εικονογραφήθηκε για πρώτη φορά στο Λονδίνο της Αγγλίας",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode, ο παράγοντας κωδικοποίησης ανοιχτού κώδικα",
|
||||
"settings.about.trademark": "Το OpenCode είναι σήμα κατατεθέν της Anomaly Innovations, Inc.",
|
||||
"settings.about.typeset": "Δακτυλογράφηση σε Inter και IBM Plex Mono",
|
||||
"settings.about.tagline": "Το AI δεν μπορεί να δημιουργήσει εξαιρετικό λογισμικό, χωρίς εσάς",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "Επεξεργασία έργου",
|
||||
"settings.timeline.title": "Χρονολόγιο",
|
||||
"settings.timeline.detail": "Λεπτομέρειες χρονολογίου",
|
||||
"settings.timeline.description":
|
||||
"Επιλέξτε πόση δραστηριότητα θα εμφανίζεται στη γραμμή χρόνου. Τα μηνύματα παραμένουν ορατά.",
|
||||
"settings.timeline.preset.everything": "Τα πάντα",
|
||||
"settings.timeline.preset.detailed": "Αναλυτικά",
|
||||
"settings.timeline.preset.compact": "Συμπαγές",
|
||||
"settings.timeline.preset.quiet": "Ήσυχο",
|
||||
"settings.timeline.preset.text-only": "Μόνο κείμενο",
|
||||
"settings.timeline.description.everything":
|
||||
"Εμφάνιση όλων των δραστηριοτήτων ξεχωριστά. Επεκτείνετε την παραγωγή φλοιού, τις επεξεργασίες και τη σκέψη.",
|
||||
"settings.timeline.description.detailed":
|
||||
"Αναπτύξτε την έξοδο φλοιού και τις επεξεργασίες. Εμφάνιση υποπαραγόντων ξεχωριστά και ομαδοποίηση άλλης δραστηριότητας στο Χρησιμοποιήθηκαν.",
|
||||
"settings.timeline.description.compact":
|
||||
"Ομαδοποιήστε όλη τη δραστηριότητα στο Χρησιμοποιήθηκαν με τις λεπτομέρειες σε σύμπτυξη.",
|
||||
"settings.timeline.description.quiet":
|
||||
"Ομαδοποιήστε επεξεργασίες και υποπράκτορες στο Χρησιμοποιήθηκαν. Απόκρυψη άλλης δραστηριότητας.",
|
||||
"settings.timeline.description.text-only": "Απόκρυψη όλης της δραστηριότητας. Εμφάνιση μόνο μηνυμάτων.",
|
||||
"settings.timeline.description.custom":
|
||||
"Χρησιμοποιήστε την επιλεγμένη τοποθέτηση και τις λεπτομέρειες για κάθε κατηγορία δραστηριότητας.",
|
||||
"settings.timeline.custom": "Προσαρμοσμένο",
|
||||
"settings.timeline.advanced": "Προχωρημένο",
|
||||
"settings.timeline.advanced.description":
|
||||
"Ορίστε την τοποθέτηση και τις λεπτομέρειες για κάθε κατηγορία δραστηριότητας.",
|
||||
"settings.timeline.category.shell": "Shell",
|
||||
"settings.timeline.category.edit": "Επεξεργασίες",
|
||||
"settings.timeline.category.thinking": "Σκέψη",
|
||||
"settings.timeline.category.subagents": "Υποπράκτορες",
|
||||
"settings.timeline.category.notices": "Ειδοποιήσεις",
|
||||
"settings.timeline.category.tools": "Άλλα εργαλεία",
|
||||
"settings.general.row.mobileDiffWrap.description":
|
||||
"Τυλίξτε τις μακριές γραμμές σε κινητές διαφορές αντί να κάνετε κύλιση οριζόντια",
|
||||
"provider.connect.error.unsupportedFields": "Αυτή η φόρμα ελέγχου ταυτότητας περιέχει μη υποστηριζόμενα πεδία",
|
||||
"session.review.filesChangedCount.one": "{{count}} αρχείο άλλαξε",
|
||||
"session.review.filesChangedCount.other": "{{count}} αρχεία άλλαξαν",
|
||||
"settings.about.writtenByNames": "Γράφτηκε από {{names}}",
|
||||
"settings.about.illustratedByNames": "Εικονογράφηση από {{names}}",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline":
|
||||
"Δεν είναι συνδεδεμένο στο {{host}}. Το πρόχειρό σας διατηρείται. η απομακρυσμένη εργασία μπορεί να εξακολουθεί να εκτελείται.",
|
||||
"ssh.placeholder": "ssh user@example.com",
|
||||
"ssh.add": "Προσθήκη διακομιστή SSH",
|
||||
"ssh.server.menu.label": "Διακομιστής SSH",
|
||||
"ssh.target": "Εντολή Host ή SSH",
|
||||
"ssh.connect": "Σύνδεση",
|
||||
"ssh.connectTo": "Σύνδεση στο {{host}}",
|
||||
"ssh.authenticate": "Έλεγχος ταυτότητας SSH",
|
||||
"ssh.action.authenticate": "Έλεγχος ταυτότητας",
|
||||
"ssh.session.disconnected": "Η σύνδεση SSH είναι ανενεργή",
|
||||
"ssh.session.connecting": "Σύνδεση με διακομιστή SSH",
|
||||
"ssh.session.reconnectDescription":
|
||||
"Επανασυνδεθείτε για να δείτε αυτήν την περίοδο λειτουργίας και να συνεχίσετε να εργάζεστε. Η απομακρυσμένη συνεδρία σας διατηρείται.",
|
||||
"ssh.session.reconnect": "Επανασύνδεση",
|
||||
"ssh.authenticationRequired": "Απαιτείται έλεγχος ταυτότητας για το {{host}}",
|
||||
"ssh.trust": "Εμπιστευτείτε και συνδεθείτε",
|
||||
"ssh.continue": "Συνέχεια",
|
||||
"ssh.retry": "Επανάληψη",
|
||||
"ssh.update": "Ενημέρωση και επανασύνδεση",
|
||||
"ssh.openProject": "Ανοιχτό έργο",
|
||||
"ssh.project": "Άνοιγμα έργου στο {{host}}",
|
||||
"ssh.disconnect": "Αποσύνδεση",
|
||||
"ssh.forget": "Ξεχάστε τη σύνδεση",
|
||||
"ssh.stage.disconnected": "Ασύνδετος. Ο απομακρυσμένος διακομιστής παραμένει σε λειτουργία.",
|
||||
"ssh.stage.connecting": "Σύνδεση μέσω SSH…",
|
||||
"ssh.stage.checking": "Έλεγχος OpenCode…",
|
||||
"ssh.stage.downloading": "Λήψη διακομιστή…",
|
||||
"ssh.stage.uploading": "Διακομιστής μεταφόρτωσης…",
|
||||
"ssh.stage.starting": "Σύνδεση στο OpenCode…",
|
||||
"ssh.stage.ready": "Συνδεδεμένος",
|
||||
"ssh.stage.authentication": "Απαιτείται έλεγχος ταυτότητας",
|
||||
"ssh.stage.incompatible": "Απαιτείται ενημέρωση διακομιστή",
|
||||
"ssh.stage.failed": "Η σύνδεση απέτυχε",
|
||||
"ssh.error.input":
|
||||
"Εισαγάγετε έναν κεντρικό υπολογιστή ή μια εντολή σύνδεσης SSH. Δεν επιτρέπονται οι απομακρυσμένες εντολές και οι μη υποστηριζόμενες επιλογές SSH.",
|
||||
"ssh.error.connection":
|
||||
"Δεν ήταν δυνατή η δημιουργία της σύνδεσης SSH. Ελέγξτε τη διαμόρφωση του δικτύου σας και του SSH.",
|
||||
"ssh.error.platform":
|
||||
"Αυτή η απομακρυσμένη πλατφόρμα δεν υποστηρίζεται. Η αυτόματη ρύθμιση απαιτεί επί του παρόντος Linux ή macOS σε x64 ή arm64.",
|
||||
"ssh.error.version":
|
||||
"Η απομακρυσμένη υπηρεσία πρέπει να ταιριάζει με αυτήν την έκδοση επιφάνειας εργασίας πριν από τη σύνδεση.",
|
||||
"ssh.error.install":
|
||||
"Δεν ήταν δυνατή η εγκατάσταση του απομακρυσμένου διακομιστή. Ελέγξτε τη συνδεσιμότητα, το χώρο στο δίσκο και ότι είναι εγκατεστημένο το tar.",
|
||||
"ssh.error.unpublished":
|
||||
"Αυτή η έκδοση για επιφάνεια εργασίας δεν έχει δημοσιευμένο απομακρυσμένο διακομιστή. Για εκδόσεις ανάπτυξης, εγκαταστήστε και ξεκινήστε το V2 στον κεντρικό υπολογιστή και, στη συνέχεια, δοκιμάστε ξανά.",
|
||||
"ssh.error.service": "Ο SSH συνδέθηκε, αλλά ο διακομιστής OpenCode δεν ήταν έτοιμος.",
|
||||
"ssh.error.host-key":
|
||||
"Δεν ήταν δυνατή η επαλήθευση της ταυτότητας του οικοδεσπότη. Επαληθεύστε το δακτυλικό του αποτύπωμα πριν ενημερώσετε τους γνωστούς κεντρικούς υπολογιστές SSH.",
|
||||
"ssh.error.ssh-missing":
|
||||
"Το OpenSSH δεν βρέθηκε. Εγκαταστήστε έναν πελάτη OpenSSH και βεβαιωθείτε ότι το ssh είναι διαθέσιμο στο PATH.",
|
||||
"command.browser.open": "Άνοιγμα προγράμματος περιήγησης",
|
||||
"command.browser.reload": "Επαναφόρτωση σελίδας προγράμματος περιήγησης",
|
||||
"command.session.summary.toggle": "Εναλλαγή περίληψης",
|
||||
"mcp.auth.interactiveForm": "Ο διακομιστής MCP Ο {{name}} απαιτεί μια διαδραστική φόρμα ελέγχου ταυτότητας",
|
||||
"server.connect.title": "Σύνδεση σε διακομιστή",
|
||||
"server.connect.description": "Εισαγάγετε τη διεύθυνση του διακομιστή και τον κωδικό πρόσβασης για να ξεκινήσετε.",
|
||||
"server.connect.button": "Σύνδεση",
|
||||
"server.connect.address.invalid": "Εισαγάγετε μια έγκυρη διεύθυνση διακομιστή HTTP ή HTTPS.",
|
||||
"server.connect.failed":
|
||||
"Δεν ήταν δυνατή η σύνδεση. Ελέγξτε τη διεύθυνση του διακομιστή και τον κωδικό πρόσβασης και, στη συνέχεια, δοκιμάστε ξανά.",
|
||||
"server.connect.pair.description":
|
||||
"Εκτελέστε αυτήν την εντολή στον υπολογιστή σας για να λάβετε τα στοιχεία της σύνδεσής σας.",
|
||||
"server.connect.scan": "Σάρωση κωδικού QR",
|
||||
"server.connect.scan.description": "Στρέψτε την κάμερά σας στον κωδικό QR που εμφανίζεται από το opencode pair.",
|
||||
"server.connect.scan.invalid":
|
||||
"Αυτός δεν είναι κωδικός σύζευξης OpenCode. Σαρώστε τον κωδικό που εμφανίζεται από το opencode pair.",
|
||||
"server.connect.camera": "Κάμερα ζευγοποίησης",
|
||||
"server.connect.camera.starting": "Άνοιγμα κάμερας…",
|
||||
"server.connect.mixedContent":
|
||||
"Δεν ήταν δυνατή η σύνδεση σε αυτόν τον διακομιστή HTTP από μια σελίδα HTTPS. Χρησιμοποιήστε μια διεύθυνση διακομιστή HTTPS.",
|
||||
"server.connect.camera.insecure": "Η σάρωση QR απαιτεί άνοιγμα αυτής της σελίδας μέσω HTTPS ή localhost.",
|
||||
"server.connect.camera.unavailable":
|
||||
"Δεν υπάρχει κάμερα διαθέσιμη σε αυτό το πρόγραμμα περιήγησης. Εισαγάγετε τα στοιχεία της σύνδεσής σας με μη αυτόματο τρόπο.",
|
||||
"server.connect.camera.error":
|
||||
"Δεν ήταν δυνατό το άνοιγμα της κάμερας. Επιτρέψτε την πρόσβαση στην κάμερα ή εισαγάγετε τα στοιχεία της σύνδεσής σας με μη αυτόματο τρόπο.",
|
||||
"dialog.server.menu.remove": "Αφαίρεση",
|
||||
"file.error.notFound": "Το αρχείο δεν βρέθηκε: {{name}}",
|
||||
"home.workspaceTip":
|
||||
"Ξεκινήστε την επόμενη συνεδρία σε νέο χώρο εργασίας για να διατηρήσετε τις αλλαγές απομονωμένες",
|
||||
"session.tab.browser": "Πρόγραμμα περιήγησης",
|
||||
"session.tab.add": "Προσθήκη καρτέλας",
|
||||
"session.queue.attachments.one": "Συν {{count}} συνημμένο",
|
||||
"session.queue.attachments.other": "Συν {{count}} συνημμένα",
|
||||
"session.browser.address": "Διεύθυνση προγράμματος περιήγησης",
|
||||
"session.browser.replaced":
|
||||
"Ο έλεγχος του προγράμματος περιήγησης μετακινήθηκε σε άλλο παράθυρο επιφάνειας εργασίας.",
|
||||
"session.browser.suspended":
|
||||
"Το πρόγραμμα περιήγησης σε αναστολή. Αλληλεπιδράστε με αυτήν την περίοδο σύνδεσης για επανασύνδεση.",
|
||||
"session.browser.address.placeholder": "Εισαγάγετε τη διεύθυνση URL",
|
||||
"settings.backToSettings": "Επιστροφή στις ρυθμίσεις",
|
||||
"settings.backToProjects": "Επιστροφή στα έργα",
|
||||
"settings.search.placeholder": "Αναζήτηση",
|
||||
"settings.search.results": "Αποτελέσματα ρυθμίσεων",
|
||||
"settings.search.group.pages": "Σελίδες",
|
||||
"settings.search.group.settings": "Ρυθμίσεις",
|
||||
"settings.search.group.projects": "Έργα",
|
||||
"settings.search.group.servers": "Διακομιστές",
|
||||
"settings.search.result": "{{title}}, {{scope}}, {{page}}",
|
||||
"settings.search.page": "{{title}}, {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}, {{page}}",
|
||||
"settings.search.empty": "Δεν υπάρχουν αποτελέσματα για {{query}}",
|
||||
"settings.search.empty.query": '"{{query}}"',
|
||||
"settings.search.refine": "Περιορίστε την αναζήτησή σας για να δείτε πιο συγκεκριμένα αποτελέσματα.",
|
||||
"settings.server.description": "Διαχειριστείτε τη σύνδεση και τις προτιμήσεις αυτού του διακομιστή",
|
||||
"settings.server.section.connection": "Σύνδεση",
|
||||
"settings.server.preferences.websearch.title": "Αναζήτηση τρίτων",
|
||||
"settings.server.preferences.websearch.description":
|
||||
"Επιλέξτε τους πράκτορες παροχής αναζήτησης που χρησιμοποιούν για την αναζήτηση στον ιστό",
|
||||
"settings.projects.search.placeholder": "Αναζήτηση έργων",
|
||||
"project.settings.name.title": "Όνομα έργου",
|
||||
"project.settings.name.description": "Το όνομα που εμφανίζεται για αυτό το έργο σε όλο το OpenCode",
|
||||
"project.settings.icon.description": "Προτείνεται: 128×128 px. Κάντε κλικ ή σύρετε για να ανεβάσετε μια εικόνα.",
|
||||
"project.settings.color.description":
|
||||
"Χρησιμοποιείται για το εικονίδιο του έργου όταν δεν έχει οριστεί προσαρμοσμένη εικόνα",
|
||||
"project.settings.worktree.startup.description": "Εκτελείται μία φορά μετά τη δημιουργία ενός νέου δέντρου εργασίας",
|
||||
"project.settings.worktree.startup.hint.base":
|
||||
"Χρησιμοποιήστε το $OPENCODE_WORKTREE_BASE για το βασικό δέντρο εργασίας.",
|
||||
"project.settings.worktree.startup.hint.new": "Χρησιμοποιήστε το $OPENCODE_WORKTREE_PATH για το νέο δέντρο εργασίας.",
|
||||
"project.settings.extensions.empty.mcps.title": "Όχι MCPs ακόμα",
|
||||
"project.settings.extensions.empty.mcps.description": "Το MCPs διαθέσιμο στο OpenCode θα εμφανιστεί εδώ",
|
||||
"project.settings.extensions.empty.plugins.title": "Δεν υπάρχουν πρόσθετα ακόμα",
|
||||
"project.settings.extensions.empty.plugins.description":
|
||||
"Τα πρόσθετα που είναι διαθέσιμα στο OpenCode θα εμφανιστούν εδώ",
|
||||
"project.settings.extensions.empty.skills.title": "Δεν υπάρχουν ακόμη δεξιότητες",
|
||||
"project.settings.extensions.empty.skills.description":
|
||||
"Οι δεξιότητες που είναι διαθέσιμες στο OpenCode θα εμφανιστούν εδώ",
|
||||
"project.settings.extensions.lsp.configured": "Διακομιστές γλώσσας που έχουν διαμορφωθεί",
|
||||
"project.settings.extensions.lsp.status.enabled": "Ενεργοποιήθηκε στο config",
|
||||
"project.settings.extensions.lsp.status.disabled": "Απενεργοποιήθηκε στη διαμόρφωση",
|
||||
"project.settings.extensions.lsp.empty.title": "Δεν έχουν ρυθμιστεί διακομιστές γλώσσας",
|
||||
"project.settings.extensions.lsp.empty.description":
|
||||
"Οι διακομιστές γλωσσών που έχουν ρυθμιστεί για αυτό το έργο θα εμφανιστούν εδώ",
|
||||
"project.settings.extensions.lsp.disabled.title": "Οι διακομιστές γλώσσας απενεργοποιήθηκαν",
|
||||
"project.settings.extensions.lsp.disabled.description":
|
||||
"Το LSP είναι απενεργοποιημένο στη διαμόρφωση αυτού του έργου",
|
||||
"project.settings.extensions.lsp.loadFailed": "Δεν ήταν δυνατή η φόρτωση της διαμόρφωσης διακομιστή γλώσσας",
|
||||
"project.settings.extensions.lsp.retry": "Επανάληψη",
|
||||
"settings.timeline.summary": "{{preset}}:",
|
||||
"settings.timeline.group": "Ομάδα",
|
||||
"settings.timeline.collapse": "Κατάρρευση",
|
||||
"settings.timeline.visibility.show": "Εμφάνιση",
|
||||
"settings.timeline.visibility.hide": "Απόκρυψη",
|
||||
"settings.timeline.visibility.label": "{{activity}} ορατότητα",
|
||||
"settings.timeline.grouped.label": "{{activity}} ομαδοποιημένα",
|
||||
"settings.timeline.collapsed.label": "Το {{activity}} κατέρρευσε",
|
||||
"session.new.workspace.search.empty": "Δεν υπάρχουν δέντρα εργασίας που να ταιριάζουν",
|
||||
"settings.workspaces.description": "Ελέγξτε τα δέντρα εργασίας και διαχειριστείτε τη χρήση του δίσκου",
|
||||
"settings.workspaces.empty.description": "Τα δέντρα εργασίας που δημιουργήθηκαν στο OpenCode θα εμφανιστούν εδώ",
|
||||
"settings.workspaces.sessions.filtered.one": "Συνεδρία {{count}}",
|
||||
"settings.workspaces.sessions.filtered.other": "Συνεδρίες {{count}}",
|
||||
"settings.workspaces.deleteAll.confirm.one": "Αυτό θα διαγράψει οριστικά το επιλεγμένο δέντρο εργασίας {{count}}.",
|
||||
"settings.workspaces.deleteAll.confirm.other": "Αυτό θα διαγράψει οριστικά τα επιλεγμένα δέντρα εργασίας {{count}}.",
|
||||
"settings.workspaces.deleteWithoutSessions": "Διαγραφή δέντρων εργασίας χωρίς περιόδους λειτουργίας",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"Αυτό θα διαγράψει οριστικά το δέντρο εργασίας {{count}} χωρίς συνδεδεμένες περιόδους σύνδεσης.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"Αυτό θα διαγράψει οριστικά τα δέντρα εργασίας {{count}} χωρίς συνδεδεμένες περιόδους σύνδεσης.",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"Τα δέντρα εργασίας με μη συγχωνευμένες αλλαγές ή ενεργές τοποθεσίες θα διατηρηθούν.",
|
||||
"settings.workspaces.delete.button": "Διαγραφή δέντρων εργασίας",
|
||||
"workspace.lifecycle.deleting": "Διαγραφή…",
|
||||
"session.summary.tooltip": "Περίληψη",
|
||||
"session.summary.server": "Επεκτάσεις",
|
||||
"session.summary.chooseProject": "Επιλέξτε ένα έργο",
|
||||
"session.summary.mcp.onCreation": "Εφαρμόζεται όταν δημιουργείται το δέντρο εργασίας",
|
||||
"session.summary.mcp.prepareFailed": "Δεν ήταν δυνατή η προετοιμασία διακομιστών MCP",
|
||||
"session.summary.mcp.unavailable":
|
||||
"Ο διακομιστής MCP Ο διακομιστής {{name}} δεν είναι διαθέσιμος σε αυτό το δέντρο εργασίας.",
|
||||
"session.summary.mcp.signInBeforeSend": "Συνδεθείτε στο {{name}} πριν στείλετε το μήνυμα προτροπής.",
|
||||
"session.summary.mcp.notReady":
|
||||
"Ο διακομιστής MCP Ο διακομιστής {{name}} δεν είναι έτοιμος. Επιλύστε τη σύνδεσή του πριν στείλετε το μήνυμα.",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "Διαμορφωμένοι διακομιστές MCP",
|
||||
"session.summary.plugins": "Πρόσθετα",
|
||||
"session.summary.plugins.configured": "Ρυθμισμένες προσθήκες",
|
||||
"session.summary.skills": "Δεξιότητες",
|
||||
"session.summary.skills.configured": "Διαμορφωμένες δεξιότητες",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "Απέτυχε",
|
||||
"session.summary.retry": "Επανάληψη",
|
||||
"session.summary.connecting": "Σύνδεση…",
|
||||
"session.summary.needsAuth": "Απαιτείται είσοδος",
|
||||
"session.summary.configure": "Αρχείο διαμόρφωσης",
|
||||
"session.summary.copyConfigPath": "Αντιγραφή διαδρομής αρχείου διαμόρφωσης",
|
||||
"session.summary.configFileMissing": "Δεν βρέθηκε αρχείο διαμόρφωσης",
|
||||
"session.summary.mcp.empty": "Δεν έχουν διαμορφωθεί διακομιστές MCP",
|
||||
"session.summary.mcp.add": "Προσθήκη διακομιστών στο opencode.json",
|
||||
"session.summary.plugins.manage": "Διαχείριση προσθηκών στο opencode.json",
|
||||
"session.summary.plugins.empty": "Δεν έχουν ρυθμιστεί πρόσθετα",
|
||||
"session.summary.plugins.add": "Προσθήκη προσθηκών στο opencode.json",
|
||||
"session.summary.skills.manage": "Διαχείριση δεξιοτήτων στο opencode.json",
|
||||
"session.summary.skills.empty": "Δεν έχουν διαμορφωθεί δεξιότητες",
|
||||
"session.summary.skills.add": "Προσθέστε δεξιότητες στο opencode.json",
|
||||
"session.summary.lsp.configured": "Διαμόρφωσε το LSPs",
|
||||
"session.summary.lsp.empty": "Δεν έχουν διαμορφωθεί διακομιστές LSP",
|
||||
"session.summary.lsp.manage": "Διαχειριστείτε το LSP στο opencode.json",
|
||||
"workspace.delete.location": "Τοποθεσία",
|
||||
"common.color.orange": "πορτοκαλί",
|
||||
"common.color.yellow": "κίτρινο",
|
||||
"common.color.cyan": "κυανό",
|
||||
"common.color.green": "πράσινο",
|
||||
"common.color.red": "κόκκινο",
|
||||
"common.color.pink": "ροζ",
|
||||
"common.color.blue": "μπλε",
|
||||
"common.color.purple": "μωβ",
|
||||
"common.color.gray": "γκρι",
|
||||
"toast.migration.progress.migratingSessions.current": "Μετεγκατάσταση συνεδριών {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "Μετεγκατάσταση συνεδριών {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "Μετανάστευση δεδομένων",
|
||||
"toast.migration.progress.working.current": "Μεταφορά δεδομένων {{current}}",
|
||||
"toast.migration.progress.working.progress": "Μεταφορά δεδομένων {{current}}/{{total}}",
|
||||
"session.browser.unsupported":
|
||||
"Αυτή η εφαρμογή επιφάνειας εργασίας δεν υποστηρίζει το παράθυρο του προγράμματος περιήγησης.",
|
||||
"command.debugBar.toggle": "Εναλλαγή γραμμής εντοπισμού σφαλμάτων",
|
||||
"command.session.location.cycle": "Εναλλαγή τοποθεσίας συνεδρίας",
|
||||
"dialog.provider.anthropic.note": "Άμεση πρόσβαση στα μοντέλα Claude μέσω κλειδιού API",
|
||||
"provider.connect.title.anthropicProMax": "Σύνδεση με το Anthropic",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"prompt.toast.uploading.cancel": "Ακύρωση μεταφόρτωσης",
|
||||
"prompt.toast.uploading.cancelFile": "Ακύρωση μεταφόρτωσης του {{filename}}",
|
||||
"prompt.toast.uploadFailed.title": "Η μεταφόρτωση απέτυχε",
|
||||
"session.browser.empty.title": "Εισαγάγετε URL",
|
||||
"session.browser.empty.description": "Ή ζητήστε «Άνοιγμα στο πρόγραμμα περιήγησης της εφαρμογής»",
|
||||
"session.browser.failed.title": "Δεν είναι δυνατή η πρόσβαση στο URL",
|
||||
"session.browser.failed.description": "Ελέγξτε το URL και τη σύνδεσή σας και δοκιμάστε ξανά.",
|
||||
"debugBar.providerAriaLabel": "Διαγνωστικά απόδοσης παρόχου",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttft.tip": "Χρόνος από την αποστολή του αιτήματος στον πάροχο έως την πρώτη έξοδο του μοντέλου.",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.ttfa.tip": "Χρόνος από την αποστολή του αιτήματος στον πάροχο έως το πρώτο κείμενο απάντησης.",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.tps.tip": "Διακριτικά εξόδου ανά δευτερόλεπτο μετά την πρώτη έξοδο του μοντέλου.",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
"debugBar.e2e.tip": "Χρόνος από την αποστολή του αιτήματος στον πάροχο έως τη λήξη της ροής απάντησης.",
|
||||
"settings.updates.action.download": "Λήψη του OpenCode",
|
||||
"settings.updates.migration.title": "Μετάβαση από Beta σε Σταθερή",
|
||||
"settings.updates.migration.description":
|
||||
"Προς το παρόν, το OpenCode Beta μεταφέρεται στο OpenCode Stable. Κάντε λήψη της έκδοσης {{version}} και, στη συνέχεια, εγκαταστήστε το OpenCode από το είδωλο δίσκου για να συνεχίσετε να λαμβάνετε ενημερώσεις.",
|
||||
}
|
||||
|
||||
@@ -195,6 +195,43 @@ export const dict = {
|
||||
"dialog.provider.viewAll": "Show more providers",
|
||||
|
||||
"provider.connect.title": "Connect {{provider}}",
|
||||
"provider.connect.opencode.name": "OpenCode Console",
|
||||
"provider.connect.opencode.freeName": "OpenCode Free",
|
||||
"provider.connect.console.title": "Connecting to OpenCode Console",
|
||||
"provider.connect.console.instructions":
|
||||
"Continue in your browser. Confirm the code shown there matches the one below.",
|
||||
"provider.connect.console.deviceCode": "Device code",
|
||||
"provider.connect.console.deviceCode.label": "Device code: {{code}}",
|
||||
"provider.connect.console.waiting": "Waiting for confirmation…",
|
||||
"provider.connect.console.browserHint": "Browser didn't open?",
|
||||
"provider.connect.console.copyLink": "Copy sign-in link",
|
||||
"provider.connect.console.linkCopied": "Sign-in link copied",
|
||||
"provider.connect.console.copyFailed": "Couldn't copy the sign-in link. Open Console again to continue.",
|
||||
"provider.connect.console.openAgain": "Open Console again",
|
||||
"provider.connect.console.browserFailed":
|
||||
"We couldn't open your browser. Try again or copy the sign-in link to continue.",
|
||||
"provider.connect.console.expired": "This sign-in request has expired. Start again to get a new device code.",
|
||||
"provider.connect.console.denied": "Access was denied in Console. Try again when you're ready to connect.",
|
||||
"provider.connect.console.statusFailed": "Couldn't check authorization. Check your server connection and try again.",
|
||||
"provider.connect.console.startFailed": "Couldn't start sign-in. Check your server connection and try again.",
|
||||
"provider.connect.models.title": "Connected to {{provider}}",
|
||||
"provider.connect.models.description": "Choose a model to start with. You can switch models anytime.",
|
||||
"provider.connect.models.available": "Available models",
|
||||
"provider.connect.models.list": "Models available from {{provider}}",
|
||||
"provider.connect.console.refreshFailed":
|
||||
"Your account is connected, but we couldn't load your models. Try again to refresh them.",
|
||||
"provider.connect.console.connected": "OpenCode connected",
|
||||
"provider.connect.console.noModels":
|
||||
"Your account is connected, but this Console workspace has no available models. Check its setup in Console, then refresh.",
|
||||
"provider.connect.console.modelsLoading": "Your models are still loading. Refresh to check again.",
|
||||
"provider.connect.console.refresh": "Refresh models",
|
||||
"provider.connect.console.openingBrowser": "Opening browser…",
|
||||
"provider.connect.console.serviceAccount": "Service account?",
|
||||
"provider.connect.console.useApiKey": "Use API key",
|
||||
"provider.connect.remote.title": "Connecting on “{{server}}”",
|
||||
"provider.connect.remote.description":
|
||||
"Your OpenCode credentials will be stored on this server. Models will be available through this server.",
|
||||
"provider.connect.form.unsupported": "This authentication form contains unsupported fields",
|
||||
"provider.connect.title.anthropicProMax": "Login with Anthropic",
|
||||
"provider.connect.selectMethod": "Select login method for {{provider}}.",
|
||||
"provider.connect.method.apiKey": "API key",
|
||||
@@ -203,6 +240,7 @@ export const dict = {
|
||||
"provider.connect.status.inProgress": "Authorization in progress…",
|
||||
"provider.connect.status.waiting": "Waiting for authorization…",
|
||||
"provider.connect.status.failed": "Authorization failed: {{error}}",
|
||||
"provider.connect.error.unsupportedFields": "This authentication form contains unsupported fields",
|
||||
"provider.connect.apiKey.description":
|
||||
"Enter your {{provider}} API key to connect your account and use {{provider}} models in OpenCode.",
|
||||
"provider.connect.apiKey.label": "{{provider}} API key",
|
||||
@@ -236,11 +274,6 @@ export const dict = {
|
||||
"Your browser opens so you can sign in to {{provider}}. Paste the authorization code it gives you below.",
|
||||
"provider.connect.oauth.openBrowser": "Open browser",
|
||||
"provider.connect.oauth.expired": "Authorization expired",
|
||||
"provider.connect.console.description":
|
||||
"Sign in with your OpenCode Console account. Your browser opens to the Console, where you pick a workspace and select Authorize.",
|
||||
"provider.connect.console.opening": "Opening your browser…",
|
||||
"provider.connect.console.code.placeholder": "Requesting a code…",
|
||||
"provider.connect.console.apiKey.switch": "Connect with an API key or service account instead",
|
||||
"provider.connect.console.apiKey.description":
|
||||
"Paste an API key for a service account. You create service accounts in the OpenCode Console under Keys.",
|
||||
"provider.connect.console.apiKey.link": "Open the Console",
|
||||
@@ -287,6 +320,8 @@ export const dict = {
|
||||
|
||||
"provider.disconnect.toast.disconnected.title": "{{provider}} disconnected",
|
||||
"provider.disconnect.toast.disconnected.description": "{{provider}} models are no longer available.",
|
||||
"provider.disconnect.toast.noCredentials.description": "No removable credentials found for {{provider}}",
|
||||
"provider.disconnect.toast.failed.description": "Failed to disconnect {{provider}}.",
|
||||
|
||||
"model.tag.free": "Free",
|
||||
"model.tag.latest": "Latest",
|
||||
@@ -317,6 +352,15 @@ export const dict = {
|
||||
"common.loading.ellipsis": "…",
|
||||
"common.cancel": "Cancel",
|
||||
"common.clear": "Clear",
|
||||
"common.color.orange": "orange",
|
||||
"common.color.yellow": "yellow",
|
||||
"common.color.cyan": "cyan",
|
||||
"common.color.green": "green",
|
||||
"common.color.red": "red",
|
||||
"common.color.pink": "pink",
|
||||
"common.color.blue": "blue",
|
||||
"common.color.purple": "purple",
|
||||
"common.color.gray": "gray",
|
||||
"common.open": "Open",
|
||||
"common.connect": "Connect",
|
||||
"common.disconnect": "Disconnect",
|
||||
@@ -389,6 +433,7 @@ export const dict = {
|
||||
"prompt.toast.attachmentDuplicate.title": "This file has already been uploaded",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"prompt.toast.uploading.cancel": "Cancel upload",
|
||||
"prompt.toast.uploading.cancelFile": "Cancel upload of {{filename}}",
|
||||
"prompt.toast.uploadFailed.title": "Upload failed",
|
||||
"prompt.toast.modelAgentRequired.title": "Select an agent and model",
|
||||
"prompt.toast.modelAgentRequired.description": "Choose an agent and model before sending a prompt.",
|
||||
@@ -689,6 +734,13 @@ export const dict = {
|
||||
"toast.session.listFailed.title": "Failed to load sessions for {{project}}",
|
||||
"toast.project.reloadFailed.title": "Failed to reload {{project}}",
|
||||
"toast.migration.failed.title": "Data migration failed",
|
||||
"toast.migration.progress.clearingOldEvents": "Clearing old events",
|
||||
"toast.migration.progress.migratingSessions": "Migrating sessions",
|
||||
"toast.migration.progress.migratingSessions.current": "Migrating sessions {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "Migrating sessions {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "Migrating data",
|
||||
"toast.migration.progress.working.current": "Migrating data {{current}}",
|
||||
"toast.migration.progress.working.progress": "Migrating data {{current}}/{{total}}",
|
||||
|
||||
"toast.update.title": "Update available",
|
||||
"toast.update.description": "A new version of OpenCode ({{version}}) is now available to install.",
|
||||
@@ -765,6 +817,8 @@ export const dict = {
|
||||
"home.projects": "Projects",
|
||||
"home.projects.all": "All projects",
|
||||
"home.project.add": "Add project",
|
||||
"home.project.missing.title": "Project folder not found",
|
||||
"home.project.missing.description": "The folder for {{name}} no longer exists.",
|
||||
"home.recentlyClosed": "Recently closed",
|
||||
"home.server.collapse": "Collapse server projects",
|
||||
"home.server.expand": "Expand server projects",
|
||||
@@ -828,6 +882,8 @@ export const dict = {
|
||||
"session.timeline.notice.cancelled": "{{actor}} cancelled",
|
||||
"session.error.serverConnection": "Can't connect to this server",
|
||||
"session.review.filesChanged": "Files Changed {{count}}",
|
||||
"session.review.filesChangedCount.one": "Files Changed {{count}}",
|
||||
"session.review.filesChangedCount.other": "Files Changed {{count}}",
|
||||
"session.review.change.one": "Change",
|
||||
"session.review.change.other": "Changes",
|
||||
"session.review.loadingChanges": "Loading changes…",
|
||||
@@ -888,6 +944,7 @@ export const dict = {
|
||||
"session.new.workspace.triggerLocal": "Local",
|
||||
"session.new.workspace.local": "Local repository",
|
||||
"session.new.workspace.existing": "Worktree…",
|
||||
"session.new.workspace.existingLabel": "Worktree",
|
||||
"session.new.git.none": "No Git",
|
||||
"session.new.lastModified": "Last modified",
|
||||
|
||||
@@ -948,6 +1005,7 @@ export const dict = {
|
||||
|
||||
"session.browser.address": "Browser address",
|
||||
"session.browser.replaced": "Browser control moved to another desktop window.",
|
||||
"session.browser.unsupported": "This desktop app does not support the browser pane.",
|
||||
"session.browser.suspended": "Browser suspended. Interact with this session to reconnect.",
|
||||
"session.browser.address.placeholder": "Enter URL",
|
||||
"session.browser.empty.title": "Enter URL",
|
||||
@@ -1093,6 +1151,8 @@ export const dict = {
|
||||
"settings.about.writtenBy": "Written by",
|
||||
"settings.about.illustratedBy": "Illustrated by",
|
||||
"settings.about.and": "and",
|
||||
"settings.about.writtenByNames": "Written by {{names}}",
|
||||
"settings.about.illustratedByNames": "Illustrated by {{names}}",
|
||||
"settings.about.otherContributor.one": "{{count}} other",
|
||||
"settings.about.otherContributor.other": "{{count}} others",
|
||||
"settings.about.firstPublished": "First published in Missouri, USA",
|
||||
@@ -1110,8 +1170,6 @@ export const dict = {
|
||||
"settings.appearance.row.tabs.description": "Choose how session tabs are arranged",
|
||||
"settings.appearance.row.tabs.horizontal": "Horizontal",
|
||||
"settings.appearance.row.tabs.vertical": "Vertical",
|
||||
"settings.appearance.row.projectName.title": "Show project names",
|
||||
"settings.appearance.row.projectName.description": "Show project names in vertical tabs and the mobile tab drawer",
|
||||
"settings.notifications.description": "Choose when to receive notifications and hear sounds",
|
||||
"settings.shortcuts.description": "Customize shortcuts for common actions",
|
||||
"settings.servers.description": "Manage server connections",
|
||||
@@ -1120,8 +1178,10 @@ export const dict = {
|
||||
"settings.server.preferences.websearch.title": "Third-party search",
|
||||
"settings.server.preferences.websearch.description": "Select the search provider agents use to search the web",
|
||||
"settings.projects.title": "Projects",
|
||||
"settings.projects.description": "Manage project settings on this server",
|
||||
"settings.projects.description": "Manage projects and their settings",
|
||||
"settings.projects.empty": "No projects found",
|
||||
"settings.projects.empty.title": "No projects yet",
|
||||
"settings.projects.empty.description": "Add a project to get started",
|
||||
"settings.projects.search.placeholder": "Search projects",
|
||||
"settings.projects.server.all": "All servers",
|
||||
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
|
||||
@@ -1235,8 +1295,6 @@ export const dict = {
|
||||
"settings.general.row.uiFont.description": "Customise the font used throughout the interface",
|
||||
"settings.general.row.showFileTree.title": "File tree",
|
||||
"settings.general.row.showFileTree.description": "Show the file tree panel in sessions",
|
||||
"settings.general.row.browserPane.title": "Browser",
|
||||
"settings.general.row.browserPane.description": "Allow agents to open and control an in-app development browser.",
|
||||
"settings.general.row.showNavigation.title": "Navigation controls",
|
||||
"settings.general.row.showNavigation.description": "Show the back and forward buttons in the desktop title bar",
|
||||
"settings.general.row.showSearch.title": "Command palette",
|
||||
@@ -1245,8 +1303,6 @@ export const dict = {
|
||||
"settings.general.row.showTerminal.description": "Show the terminal button in the desktop title bar",
|
||||
"settings.general.row.showStatus.title": "Server status",
|
||||
"settings.general.row.showStatus.description": "Show the server status button in the title bar",
|
||||
"settings.general.row.showProjectIcon.title": "Show project icon",
|
||||
"settings.general.row.showProjectIcon.description": "Show project icon in session header",
|
||||
"settings.general.row.mobileTitlebarBottom.title": "Bottom navigation",
|
||||
"settings.general.row.mobileTitlebarBottom.description": "Place the title bar at the bottom of the screen on mobile",
|
||||
"settings.general.row.mobileDiffWrap.description":
|
||||
@@ -1382,6 +1438,8 @@ export const dict = {
|
||||
"settings.providers.section.connected": "Connected providers",
|
||||
"settings.providers.connected.empty": "No connected providers",
|
||||
"settings.providers.connected.environmentDescription": "Connected from your environment variables",
|
||||
"settings.providers.console.available.one": "{{count}} provider available",
|
||||
"settings.providers.console.available.other": "{{count}} providers available",
|
||||
"settings.providers.section.popular": "Popular providers",
|
||||
"settings.providers.custom.description": "Add an OpenAI-compatible provider by base URL.",
|
||||
"settings.providers.tag.environment": "Environment",
|
||||
@@ -1391,6 +1449,8 @@ export const dict = {
|
||||
"settings.providers.tag.other": "Other",
|
||||
"settings.models.title": "Models",
|
||||
"settings.models.description": "Choose which models appear in model picker",
|
||||
"settings.models.enableAll": "Enable all models",
|
||||
"settings.models.disableAll": "Disable all models",
|
||||
"settings.agents.title": "Agents",
|
||||
"settings.agents.description": "Agent settings will be configurable here.",
|
||||
"settings.commands.title": "Commands",
|
||||
|
||||
@@ -1,4 +1,352 @@
|
||||
export const dict = {
|
||||
"common.color.orange": "naranja",
|
||||
"common.color.yellow": "amarillo",
|
||||
"common.color.cyan": "cian",
|
||||
"common.color.green": "verde",
|
||||
"common.color.red": "rojo",
|
||||
"common.color.pink": "rosa",
|
||||
"common.color.blue": "azul",
|
||||
"common.color.purple": "morado",
|
||||
"common.color.gray": "gris",
|
||||
"toast.migration.progress.migratingSessions.current": "Migrando sesiones: {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "Migrando sesiones: {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "Migrando datos",
|
||||
"toast.migration.progress.working.current": "Migrando datos: {{current}}",
|
||||
"toast.migration.progress.working.progress": "Migrando datos: {{current}}/{{total}}",
|
||||
"session.browser.unsupported": "Esta aplicación de escritorio no admite el panel del navegador.",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline":
|
||||
"No conectado a {{host}}. Su borrador se conserva; Es posible que el trabajo remoto aún esté funcionando.",
|
||||
"ssh.placeholder": "ssh user@example.com",
|
||||
"ssh.add": "Agregar servidor SSH",
|
||||
"ssh.server.menu.label": "Servidor SSH",
|
||||
"ssh.target": "Comando host o SSH",
|
||||
"ssh.connect": "Conectar",
|
||||
"ssh.connectTo": "Conéctese a {{host}}",
|
||||
"ssh.authenticate": "Autenticación SSH",
|
||||
"ssh.action.authenticate": "autenticar",
|
||||
"ssh.session.disconnected": "Conexión SSH inactiva",
|
||||
"ssh.session.connecting": "Conexión al servidor SSH",
|
||||
"ssh.session.reconnectDescription":
|
||||
"Vuelva a conectarse para ver esta sesión y continuar trabajando. Su sesión remota se conserva.",
|
||||
"ssh.session.reconnect": "Reconectar",
|
||||
"ssh.authenticationRequired": "Se requiere autenticación para {{host}}",
|
||||
"ssh.trust": "Confía y conecta",
|
||||
"ssh.continue": "Continuar",
|
||||
"ssh.retry": "Reintentar",
|
||||
"ssh.update": "Actualizar y volver a conectar",
|
||||
"ssh.openProject": "Abrir proyecto",
|
||||
"ssh.project": "Abrir proyecto en {{host}}",
|
||||
"ssh.disconnect": "Desconectar",
|
||||
"ssh.forget": "olvidar la conexión",
|
||||
"ssh.stage.disconnected": "Desconectado. El servidor remoto se deja en ejecución.",
|
||||
"ssh.stage.connecting": "Conectando a través de SSH…",
|
||||
"ssh.stage.checking": "Comprobando OpenCode…",
|
||||
"ssh.stage.downloading": "Descargando servidor…",
|
||||
"ssh.stage.uploading": "Subiendo servidor…",
|
||||
"ssh.stage.starting": "Conectándose a OpenCode…",
|
||||
"ssh.stage.ready": "Conectado",
|
||||
"ssh.stage.authentication": "Se requiere autenticación",
|
||||
"ssh.stage.incompatible": "Se requiere actualización del servidor",
|
||||
"ssh.stage.failed": "La conexión falló",
|
||||
"ssh.error.input":
|
||||
"Ingrese un comando de conexión de host o SSH. No se permiten comandos remotos ni opciones de SSH no compatibles.",
|
||||
"ssh.error.connection": "No se pudo establecer la conexión SSH. Verifique su red y la configuración de SSH.",
|
||||
"ssh.error.platform":
|
||||
"Esta plataforma remota no es compatible. La configuración automática actualmente requiere Linux o macOS en x64 o arm64.",
|
||||
"ssh.error.version": "El servicio remoto debe coincidir con esta versión de escritorio antes de conectarse.",
|
||||
"ssh.error.install":
|
||||
"No se pudo instalar el servidor remoto. Verifique la conectividad, el espacio en disco y que tar esté instalado.",
|
||||
"ssh.error.unpublished":
|
||||
"Esta versión de escritorio no tiene ningún servidor remoto publicado. Para compilaciones de desarrollo, instale e inicie V2 en el host y luego vuelva a intentarlo.",
|
||||
"ssh.error.service": "SSH se conectó, pero el servidor OpenCode no estuvo listo.",
|
||||
"ssh.error.host-key":
|
||||
"No se pudo verificar la identidad del anfitrión. Verifique su huella digital antes de actualizar sus hosts conocidos SSH.",
|
||||
"ssh.error.ssh-missing":
|
||||
"No se encontró OpenSSH. Instale un cliente OpenSSH y asegúrese de que ssh esté disponible en PATH.",
|
||||
"command.browser.open": "Abrir navegador",
|
||||
"command.browser.reload": "Recargar la página del navegador",
|
||||
"command.session.summary.toggle": "Alternar resumen",
|
||||
"mcp.auth.interactiveForm": "El servidor MCP {{name}} requiere un formulario de autenticación interactivo",
|
||||
"server.connect.title": "Conectarse a un servidor",
|
||||
"server.connect.description": "Ingrese la dirección de su servidor y la contraseña para comenzar.",
|
||||
"server.connect.button": "Conectar",
|
||||
"server.connect.address.invalid": "Ingrese una dirección de servidor HTTP o HTTPS válida.",
|
||||
"server.connect.failed":
|
||||
"No se pudo conectar. Verifique la dirección y la contraseña del servidor y vuelva a intentarlo.",
|
||||
"server.connect.pair.description": "Ejecute este comando en su computadora para obtener los detalles de su conexión.",
|
||||
"server.connect.scan": "Escanea el código QR",
|
||||
"server.connect.scan.description": "Apunte su cámara al código QR mostrado por opencode pair.",
|
||||
"server.connect.scan.invalid":
|
||||
"Este no es un código de emparejamiento OpenCode. Escanea el código mostrado por opencode pair.",
|
||||
"server.connect.camera": "Emparejamiento de cámara",
|
||||
"server.connect.camera.starting": "Abriendo cámara...",
|
||||
"server.connect.mixedContent":
|
||||
"No se pudo conectar a este servidor HTTP desde una página HTTPS. Utilice una dirección de servidor HTTPS en su lugar.",
|
||||
"server.connect.camera.insecure": "El escaneo de QR requiere abrir esta página en HTTPS o en localhost.",
|
||||
"server.connect.camera.unavailable":
|
||||
"No hay ninguna cámara disponible para este navegador. Ingrese los detalles de su conexión manualmente.",
|
||||
"server.connect.camera.error":
|
||||
"No se pudo abrir la cámara. Permita el acceso a la cámara o ingrese los detalles de su conexión manualmente.",
|
||||
"dialog.server.menu.remove": "Quitar",
|
||||
"file.error.notFound": "Archivo no encontrado: {{name}}",
|
||||
"home.workspaceTip": "Inicie la próxima sesión en un nuevo espacio de trabajo para mantener los cambios aislados",
|
||||
"session.tab.browser": "Navegador",
|
||||
"session.tab.add": "Agregar pestaña",
|
||||
"session.queue.attachments.one": "Más accesorio {{count}}",
|
||||
"session.queue.attachments.other": "Más accesorios {{count}}",
|
||||
"session.browser.address": "dirección del navegador",
|
||||
"session.browser.replaced": "El control del navegador se movió a otra ventana del escritorio.",
|
||||
"session.browser.suspended": "Navegador suspendido. Interactúa con esta sesión para volver a conectarte.",
|
||||
"session.browser.address.placeholder": "Introduzca URL",
|
||||
"settings.backToSettings": "Volver a la configuración",
|
||||
"settings.backToProjects": "Volver a proyectos",
|
||||
"settings.search.placeholder": "Buscar",
|
||||
"settings.search.results": "Resultados de la configuración",
|
||||
"settings.search.group.pages": "paginas",
|
||||
"settings.search.group.settings": "Configuración",
|
||||
"settings.search.group.projects": "Proyectos",
|
||||
"settings.search.group.servers": "Servidores",
|
||||
"settings.search.result": "{{title}}, {{scope}}, {{page}}",
|
||||
"settings.search.page": "{{title}}, {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}, {{page}}",
|
||||
"settings.search.empty": "No hay resultados para {{query}}",
|
||||
"settings.search.empty.query": '"{{query}}"',
|
||||
"settings.search.refine": "Limite su búsqueda para ver resultados más específicos.",
|
||||
"settings.server.description": "Administrar la conexión y las preferencias de este servidor",
|
||||
"settings.server.section.connection": "Conexión",
|
||||
"settings.server.preferences.websearch.title": "Búsqueda de terceros",
|
||||
"settings.server.preferences.websearch.description":
|
||||
"Seleccione el proveedor de búsqueda que utilizan los agentes para buscar en la web",
|
||||
"settings.projects.search.placeholder": "Buscar proyectos",
|
||||
"project.settings.name.title": "Nombre del proyecto",
|
||||
"project.settings.name.description": "El nombre que se muestra para este proyecto en todo OpenCode.",
|
||||
"project.settings.icon.description": "Recomendado: 128×128px. Haga clic o arrastre para cargar una imagen.",
|
||||
"project.settings.color.description":
|
||||
"Se utiliza para el icono del proyecto cuando no se establece ninguna imagen personalizada.",
|
||||
"project.settings.worktree.startup.description": "Se ejecuta una vez después de crear un nuevo espacio de trabajo.",
|
||||
"project.settings.worktree.startup.hint.base": "Utilice $OPENCODE_WORKTREE_BASE para el espacio de trabajo base.",
|
||||
"project.settings.worktree.startup.hint.new": "Utilice $OPENCODE_WORKTREE_PATH para el nuevo espacio de trabajo.",
|
||||
"project.settings.extensions.empty.mcps.title": "Aún no hay MCPs",
|
||||
"project.settings.extensions.empty.mcps.description": "MCPs disponible para OpenCode aparecerá aquí",
|
||||
"project.settings.extensions.empty.plugins.title": "Aún no hay complementos",
|
||||
"project.settings.extensions.empty.plugins.description": "Los complementos disponibles para OpenCode aparecerán aquí",
|
||||
"project.settings.extensions.empty.skills.title": "Aún no hay habilidades",
|
||||
"project.settings.extensions.empty.skills.description": "Las habilidades disponibles para OpenCode aparecerán aquí",
|
||||
"project.settings.extensions.lsp.configured": "Servidores de idiomas configurados",
|
||||
"project.settings.extensions.lsp.status.enabled": "Habilitado en la configuración",
|
||||
"project.settings.extensions.lsp.status.disabled": "Deshabilitado en la configuración",
|
||||
"project.settings.extensions.lsp.empty.title": "No hay servidores de idiomas configurados",
|
||||
"project.settings.extensions.lsp.empty.description":
|
||||
"Los servidores de idiomas configurados para este proyecto aparecerán aquí",
|
||||
"project.settings.extensions.lsp.disabled.title": "Servidores de idiomas deshabilitados",
|
||||
"project.settings.extensions.lsp.disabled.description":
|
||||
"LSP está deshabilitado en la configuración de este proyecto.",
|
||||
"project.settings.extensions.lsp.loadFailed": "No se pudo cargar la configuración del servidor de idiomas",
|
||||
"project.settings.extensions.lsp.retry": "Reintentar",
|
||||
"settings.timeline.summary": "{{preset}}:",
|
||||
"settings.timeline.group": "grupo",
|
||||
"settings.timeline.collapse": "Colapso",
|
||||
"settings.timeline.visibility.show": "Mostrar",
|
||||
"settings.timeline.visibility.hide": "Ocultar",
|
||||
"settings.timeline.visibility.label": "Visibilidad {{activity}}",
|
||||
"settings.timeline.grouped.label": "{{activity}} agrupado",
|
||||
"settings.timeline.collapsed.label": "{{activity}} colapsó",
|
||||
"session.new.workspace.search.empty": "No hay espacios de trabajo coincidentes",
|
||||
"settings.workspaces.description": "Revisar espacios de trabajo y administrar el uso del disco",
|
||||
"settings.workspaces.empty.description": "Los espacios de trabajo creados en OpenCode aparecerán aquí",
|
||||
"settings.workspaces.sessions.filtered.one": "Sesión {{count}}",
|
||||
"settings.workspaces.sessions.filtered.other": "Sesiones {{count}}",
|
||||
"settings.workspaces.deleteAll.confirm.one":
|
||||
"Esto eliminará permanentemente el espacio de trabajo seleccionado {{count}}.",
|
||||
"settings.workspaces.deleteAll.confirm.other":
|
||||
"Esto eliminará permanentemente los espacios de trabajo seleccionados de {{count}}.",
|
||||
"settings.workspaces.deleteWithoutSessions": "Eliminar espacios de trabajo sin sesiones",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"Esto eliminará permanentemente el espacio de trabajo {{count}} sin sesiones vinculadas.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"Esto eliminará permanentemente los espacios de trabajo {{count}} sin sesiones vinculadas.",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"Se mantendrán los espacios de trabajo con cambios no fusionados o ubicaciones activas.",
|
||||
"settings.workspaces.delete.button": "Eliminar espacios de trabajo",
|
||||
"workspace.lifecycle.deleting": "Eliminando…",
|
||||
"session.summary.tooltip": "Resumen",
|
||||
"session.summary.server": "Extensiones",
|
||||
"session.summary.chooseProject": "Elige un proyecto",
|
||||
"session.summary.mcp.onCreation": "Se aplica cuando se crea el espacio de trabajo.",
|
||||
"session.summary.mcp.prepareFailed": "No se pudieron preparar los servidores MCP",
|
||||
"session.summary.mcp.unavailable": "El servidor MCP {{name}} no está disponible en este espacio de trabajo.",
|
||||
"session.summary.mcp.signInBeforeSend": "Inicie sesión en {{name}} antes de enviar el mensaje.",
|
||||
"session.summary.mcp.notReady":
|
||||
"El servidor MCP {{name}} no está listo. Resuelva su conexión antes de enviar el mensaje.",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "Servidores MCP configurados",
|
||||
"session.summary.plugins": "Complementos",
|
||||
"session.summary.plugins.configured": "Complementos configurados",
|
||||
"session.summary.skills": "Habilidades",
|
||||
"session.summary.skills.configured": "Habilidades configuradas",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "Fallido",
|
||||
"session.summary.retry": "Reintentar",
|
||||
"session.summary.connecting": "Conectando…",
|
||||
"session.summary.needsAuth": "Es necesario iniciar sesión",
|
||||
"session.summary.configure": "Archivo de configuración",
|
||||
"session.summary.copyConfigPath": "Copiar la ruta del archivo de configuración",
|
||||
"session.summary.configFileMissing": "No se encontró ningún archivo de configuración",
|
||||
"session.summary.mcp.empty": "No hay servidores MCP configurados",
|
||||
"session.summary.mcp.add": "Agregar servidores en opencode.json",
|
||||
"session.summary.plugins.manage": "Administrar complementos en opencode.json",
|
||||
"session.summary.plugins.empty": "No hay complementos configurados",
|
||||
"session.summary.plugins.add": "Agregar complementos en opencode.json",
|
||||
"session.summary.skills.manage": "Gestionar habilidades en opencode.json",
|
||||
"session.summary.skills.empty": "No hay habilidades configuradas",
|
||||
"session.summary.skills.add": "Agregar habilidades en opencode.json",
|
||||
"session.summary.lsp.configured": "Configurado LSPs",
|
||||
"session.summary.lsp.empty": "No hay servidores LSP configurados",
|
||||
"session.summary.lsp.manage": "Administrar LSP en opencode.json",
|
||||
"workspace.delete.location": "Ubicación",
|
||||
"session.queue.attachments.many": "Más accesorios {{count}}",
|
||||
"settings.workspaces.sessions.filtered.many": "Sesiones {{count}}",
|
||||
"settings.workspaces.deleteAll.confirm.many":
|
||||
"Esto eliminará permanentemente los espacios de trabajo seleccionados de {{count}}.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.many":
|
||||
"Esto eliminará permanentemente los espacios de trabajo {{count}} sin sesiones vinculadas.",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"Se conservarán los espacios de trabajo con cambios sin fusionar, sesiones vinculadas o ubicaciones activas.",
|
||||
"provider.connect.error.unsupportedFields": "Este formulario de autenticación contiene campos no compatibles",
|
||||
"session.review.filesChangedCount.one": "{{count}} archivo cambiado",
|
||||
"session.review.filesChangedCount.other": "{{count}} archivos cambiados",
|
||||
"session.review.filesChangedCount.many": "{{count}} archivos cambiados",
|
||||
"settings.about.writtenByNames": "Escrito por {{names}}",
|
||||
"settings.about.illustratedByNames": "Ilustrado por {{names}}",
|
||||
"home.projects.all": "Todos los proyectos",
|
||||
"session.tab.files": "Archivos",
|
||||
"session.files.openTabs": "Archivos abiertos",
|
||||
"session.tab.usage": "Uso",
|
||||
"session.view.select": "Vista de sesión",
|
||||
"session.background.moveTasks": "Mover {{tasks}} a segundo plano",
|
||||
"session.background.moveRunning": "Mover a segundo plano",
|
||||
"session.background.inBackground": "Ejecutando {{tasks}} en segundo plano",
|
||||
"session.background.tasksRunning.one": "{{count}} tarea en segundo plano en ejecución",
|
||||
"session.background.tasksRunning.other": "{{count}} tareas en segundo plano en ejecución",
|
||||
"session.background.combine": "{{first}} y {{second}}",
|
||||
"session.background.shell.one": "{{count}} shell",
|
||||
"session.background.shell.other": "{{count}} shells",
|
||||
"session.background.subagent.one": "{{count}} subagente",
|
||||
"session.background.subagent.other": "{{count}} subagentes",
|
||||
"session.timeline.working": "Trabajando",
|
||||
"session.review.wrapLines": "Ajustar líneas",
|
||||
"session.websearch.title": "Búsqueda web de terceros",
|
||||
"session.websearch.description": "Selecciona el proveedor de búsqueda que usan los agentes para buscar en la web",
|
||||
"session.websearch.provider": "Proveedor de búsqueda",
|
||||
"session.websearch.any": "Cualquiera",
|
||||
"session.websearch.disable": "No usar la búsqueda",
|
||||
"session.websearch.enable": "Activar",
|
||||
"session.websearch.loadFailed": "No se pudieron cargar los proveedores de búsqueda.",
|
||||
"session.websearch.empty": "No hay proveedores de búsqueda disponibles.",
|
||||
"session.websearch.failed": "No se pudo guardar tu elección. Inténtalo de nuevo.",
|
||||
"session.websearch.retry": "Reintentar",
|
||||
"session.new.worktree.draftPlaceholder": "Redacta un seguimiento mientras se prepara el árbol de trabajo…",
|
||||
"session.search.placeholder": "Buscar...",
|
||||
"session.search.noResults": "No hay coincidencias",
|
||||
"titlebar.tabs": "Pestañas",
|
||||
"titlebar.channel.local": "Local",
|
||||
"titlebar.channel.dev": "Dev",
|
||||
"titlebar.channel.beta": "Beta",
|
||||
"titlebar.toggleDebugTools": "Alternar herramientas de depuración",
|
||||
"settings.tab.experimental": "Experimental",
|
||||
"settings.experimental.description": "Prueba funciones experimentales",
|
||||
"settings.tab.about": "Acerca de",
|
||||
"settings.about.version": "Versión {{version}}",
|
||||
"settings.about.devVersion": "desarrollo",
|
||||
"settings.about.license": "Publicado bajo la licencia MIT",
|
||||
"settings.about.writtenBy": "Escrito por",
|
||||
"settings.about.illustratedBy": "Ilustrado por",
|
||||
"settings.about.and": "y",
|
||||
"settings.about.otherContributor.one": "{{count}} más",
|
||||
"settings.about.otherContributor.other": "{{count}} más",
|
||||
"settings.about.firstPublished": "Publicado por primera vez en Misuri, EE. UU.",
|
||||
"settings.about.firstIllustrated": "Ilustrado por primera vez en Londres, Inglaterra",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode, el agente de programación de código abierto",
|
||||
"settings.about.trademark": "OpenCode es una marca registrada de Anomaly Innovations, Inc.",
|
||||
"settings.about.typeset": "Compuesto con Inter e IBM Plex Mono",
|
||||
"settings.about.tagline": "La IA no puede crear software excelente sin ti",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "Editar proyecto",
|
||||
"settings.timeline.title": "Cronología",
|
||||
"settings.timeline.detail": "Detalle de la cronología",
|
||||
"settings.timeline.description": "Elige cuánta actividad aparece en la cronología. Los mensajes permanecen visibles.",
|
||||
"settings.timeline.preset.everything": "Todo",
|
||||
"settings.timeline.preset.detailed": "Detallado",
|
||||
"settings.timeline.preset.compact": "Compacto",
|
||||
"settings.timeline.preset.quiet": "Discreto",
|
||||
"settings.timeline.preset.text-only": "Solo texto",
|
||||
"settings.timeline.description.everything":
|
||||
"Mostrar toda la actividad por separado. Expandir la salida de shell, las ediciones y el razonamiento.",
|
||||
"settings.timeline.description.detailed":
|
||||
"Expandir la salida de shell y las ediciones. Mostrar los subagentes por separado y agrupar el resto de la actividad en Usado.",
|
||||
"settings.timeline.description.compact": "Agrupar toda la actividad en Usado con los detalles contraídos.",
|
||||
"settings.timeline.description.quiet":
|
||||
"Agrupar las ediciones y los subagentes en Usado. Ocultar el resto de la actividad.",
|
||||
"settings.timeline.description.text-only": "Ocultar toda la actividad. Mostrar solo los mensajes.",
|
||||
"settings.timeline.description.custom":
|
||||
"Usar la ubicación y los detalles seleccionados para cada categoría de actividad.",
|
||||
"settings.timeline.custom": "Personalizado",
|
||||
"settings.timeline.advanced": "Avanzado",
|
||||
"settings.timeline.advanced.description": "Definir la ubicación y los detalles de cada categoría de actividad.",
|
||||
"settings.timeline.category.shell": "Shell",
|
||||
"settings.timeline.category.edit": "Ediciones",
|
||||
"settings.timeline.category.thinking": "Razonamiento",
|
||||
"settings.timeline.category.subagents": "Subagentes",
|
||||
"settings.timeline.category.notices": "Avisos",
|
||||
"settings.timeline.category.tools": "Otras herramientas",
|
||||
"settings.general.row.mobileDiffWrap.description":
|
||||
"Ajustar las líneas largas en los diffs móviles en vez de desplazarse horizontalmente",
|
||||
"session.background.tasksRunning.many": "{{count}} tareas en segundo plano en ejecución",
|
||||
"session.background.shell.many": "{{count}} shells",
|
||||
"session.background.subagent.many": "{{count}} subagentes",
|
||||
"settings.about.otherContributor.many": "{{count}} más",
|
||||
"toast.migration.progress.clearingOldEvents": "Borrando eventos antiguos",
|
||||
"toast.migration.progress.migratingSessions": "Migrando sesiones",
|
||||
"session.new.workspace.existingLabel": "Árbol de trabajo",
|
||||
"desktop.onboarding.defaultProject": "Proyecto predeterminado",
|
||||
"session.location.unavailable": "Ubicación de la sesión no disponible",
|
||||
"session.location.description": "Elige otro directorio para continuar esta sesión.",
|
||||
"session.location.choose": "Elegir directorio",
|
||||
"session.location.worktree": "Elegir árbol de trabajo",
|
||||
"session.location.worktreesFailed": "No se pudieron cargar los árboles de trabajo",
|
||||
"session.location.moving": "Moviendo la sesión…",
|
||||
"dialog.server.menu.hide": "Ocultar de la lista de proyectos",
|
||||
"dialog.server.menu.show": "Mostrar en la lista de proyectos",
|
||||
"session.queue.count.one": "{{count}} en cola",
|
||||
"session.queue.count.many": "{{count}} en cola",
|
||||
"session.queue.count.other": "{{count}} en cola",
|
||||
"session.queue.steer": "Orientar",
|
||||
"session.queue.send": "Enviar",
|
||||
"session.queue.steerTooltip": "Enviar sin interrumpir",
|
||||
"session.queue.remove": "Quitar",
|
||||
"session.queue.reorder": "Reordenar instrucción en cola",
|
||||
"session.new.worktree.creating": "Creando árbol de trabajo",
|
||||
"settings.backToApp": "Volver a la aplicación",
|
||||
"settings.appearance.section.experimental": "Experimental",
|
||||
"settings.appearance.row.tabs.title": "Pestañas",
|
||||
"settings.appearance.row.tabs.description": "Elige cómo se organizan las pestañas de sesión",
|
||||
"settings.appearance.row.tabs.horizontal": "Horizontal",
|
||||
"settings.appearance.row.tabs.vertical": "Vertical",
|
||||
"settings.general.row.followUpBehavior.title": "Comportamiento de los seguimientos",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"Elige si poner los seguimientos en cola u orientar el turno actual. Usa {{keybind}} para cambiar.",
|
||||
"settings.general.row.followUpBehavior.queue": "Poner en cola",
|
||||
"settings.general.row.followUpBehavior.steer": "Orientar",
|
||||
"settings.general.row.reasoningMode.title": "Razonamiento del modelo",
|
||||
"settings.general.row.reasoningMode.description":
|
||||
"Elige cómo se muestra el razonamiento del modelo en la línea de tiempo",
|
||||
"settings.general.row.reasoningMode.hidden": "Oculto",
|
||||
"settings.general.row.reasoningMode.compact": "Compacto",
|
||||
"settings.general.row.reasoningMode.full": "Completo",
|
||||
"session.new.workspace.createFrom": "Crear desde una rama",
|
||||
"session.new.workspace.branch.search.placeholder": "Buscar ramas",
|
||||
"desktop.menu.app": "OpenCode",
|
||||
"desktop.menu.file": "Archivo",
|
||||
"desktop.menu.edit": "Editar",
|
||||
@@ -628,7 +976,6 @@ export const dict = {
|
||||
"toast.context.noLineSelection.title": "Sin selección de líneas",
|
||||
"toast.context.noLineSelection.description": "Primero selecciona un rango de líneas en una pestaña de archivo.",
|
||||
|
||||
|
||||
"toast.session.unshare.success.title": "La sesión dejó de compartirse",
|
||||
"toast.session.unshare.success.description": "La sesión dejó de compartirse correctamente.",
|
||||
"toast.session.unshare.failed.title": "Fallo al dejar de compartir sesión",
|
||||
@@ -731,6 +1078,7 @@ export const dict = {
|
||||
"session.error.serverConnection": "No se puede conectar a este servidor",
|
||||
"session.review.filesChanged": "Archivos modificados: {{count}}",
|
||||
"session.review.change.one": "Cambio",
|
||||
"session.review.change.many": "Cambios",
|
||||
"session.review.change.other": "Cambios",
|
||||
"session.review.loadingChanges": "Cargando cambios…",
|
||||
"session.review.empty": "Aún no hay cambios en esta sesión",
|
||||
@@ -1193,4 +1541,139 @@ export const dict = {
|
||||
"error.childStore.persistedProjectIconCreateFailed": "Error al crear icono de proyecto persistente",
|
||||
"error.childStore.storeCreateFailed": "Error al crear almacén",
|
||||
"terminal.connectionLost.abnormalClose": "WebSocket cerrado anormalmente: {{code}}",
|
||||
|
||||
"provider.disconnect.toast.noCredentials.description": "No se encontraron credenciales extraíbles para {{provider}}.",
|
||||
"provider.disconnect.toast.failed.description": "No se pudo desconectar {{provider}}.",
|
||||
"toast.migration.failed.title": "La migración de datos falló",
|
||||
"command.session.background": "Pasar al fondo",
|
||||
"session.timeline.notice.finished": "{{actor}} terminado",
|
||||
"session.timeline.notice.failed": "{{actor}} falló",
|
||||
"session.timeline.notice.cancelled": "{{actor}} cancelado",
|
||||
"settings.tab.preferences": "Preferencias",
|
||||
"settings.tab.notifications": "Notificaciones",
|
||||
"settings.tab.projects": "Proyectos",
|
||||
"settings.tab.extensions": "Extensiones",
|
||||
"settings.preferences.description": "Personalizar preferencias y tema y comportamiento predeterminado",
|
||||
"settings.appearance.description": "Personaliza el tema y las fuentes",
|
||||
"settings.notifications.description": "Elige cuándo recibir notificaciones y escuchar sonidos",
|
||||
"settings.shortcuts.description": "Personaliza atajos para acciones comunes",
|
||||
"settings.servers.description": "Administrar conexiones de servidor",
|
||||
"settings.projects.title": "Proyectos",
|
||||
"settings.projects.description": "Administrar la configuración del proyecto en este servidor",
|
||||
"settings.projects.empty": "No se encontraron proyectos",
|
||||
"settings.projects.server.all": "Todos los servidores",
|
||||
"settings.mcps.description": "Administrar servidores y herramientas de Model Context Protocol (MCP)",
|
||||
"settings.extensions.description": "Administrar extensiones disponibles en este servidor",
|
||||
"settings.extensions.tab.mcps": "MCP",
|
||||
"settings.extensions.tab.skills": "Habilidades",
|
||||
"settings.extensions.availableAll": "Disponible para todos los proyectos",
|
||||
"settings.extensions.manageConfig": "Administrar en opencode.json",
|
||||
"settings.extensions.addSkills": "Cómo agregar habilidades",
|
||||
"dialog.server.authenticate.title": "Autenticar",
|
||||
"project.settings.general.description": "Administrar el nombre y la apariencia del proyecto",
|
||||
"project.settings.scripts": "Guiones",
|
||||
"project.settings.scripts.description": "Configurar scripts para este proyecto",
|
||||
"project.settings.extensions.description": "Ver extensiones disponibles para este proyecto",
|
||||
"project.settings.extensions.tab.lsps": "LSP",
|
||||
"project.settings.extensions.added": "Agregado a este proyecto",
|
||||
"project.settings.extensions.shared": "Compartido con todos los proyectos.",
|
||||
"project.settings.extensions.lsp.detected": "Servidores de idiomas detectados",
|
||||
"project.settings.extensions.lsp.description": "Detectado automáticamente a partir de tipos de archivos",
|
||||
"project.settings.extensions.setupRequired": "Configuración requerida",
|
||||
"settings.general.section.general": "General",
|
||||
"common.viewAll": "Ver todo",
|
||||
"session.new.workspace.local.tooltip": "Usar el checkout actual",
|
||||
"session.new.workspace.new.tooltip": "Crear un checkout aislado",
|
||||
"session.new.workspace.fromBranch": "de {{branch}}",
|
||||
"session.new.workspace.trigger.tooltip": "Seleccione dónde ejecutar la sesión",
|
||||
"session.new.workspace.search.placeholder": "Buscar espacios de trabajo",
|
||||
"settings.tab.workspaces": "Espacios de trabajo",
|
||||
"settings.workspaces.filter.all": "Todos los proyectos",
|
||||
"settings.workspaces.empty": "Sin espacios de trabajo",
|
||||
"settings.workspaces.count.one": "Espacio de trabajo {{count}}",
|
||||
"settings.workspaces.count.other": "Espacios de trabajo {{count}}",
|
||||
"settings.workspaces.sessions.one": "Sesión {{count}} en {{project}}",
|
||||
"settings.workspaces.sessions.other": "Sesiones {{count}} en {{project}}",
|
||||
"settings.workspaces.lastActiveSession": "Última sesión activa",
|
||||
"settings.workspaces.deleteAll": "Eliminar todos los espacios de trabajo",
|
||||
"settings.workspaces.delete.warning":
|
||||
"El directorio y la rama del espacio de trabajo se eliminarán permanentemente, incluidos los cambios no combinados que se muestran a continuación.",
|
||||
"settings.workspaces.delete.blocked.active": "El espacio de trabajo activo no se puede eliminar.",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"Las sesiones vinculadas permanecerán, pero su directorio de trabajo se eliminará permanentemente.",
|
||||
"settings.workspaces.default.title": "Entorno predeterminado",
|
||||
"settings.workspaces.default.description": "Elige dónde comienzan las nuevas sesiones",
|
||||
"settings.workspaces.default.lastUsed": "Último usado por proyecto",
|
||||
"settings.workspaces.default.local": "directorio local",
|
||||
"settings.workspaces.default.new": "Nuevo espacio de trabajo",
|
||||
"workspace.move.title": "Mover al espacio de trabajo",
|
||||
"workspace.move.menu.title": "Mover sesión a",
|
||||
"workspace.move.failed": "No se pudo mover la sesión",
|
||||
"workspace.lifecycle.creating": "Creando espacio de trabajo",
|
||||
"workspace.lifecycle.created": "Espacio de trabajo creado",
|
||||
"workspace.lifecycle.starting": "Iniciando sesión",
|
||||
"workspace.onboarding.title": "Aislar sesiones con espacios de trabajo",
|
||||
"workspace.onboarding.description":
|
||||
"Cada uno tiene su propio pago, por lo que nada interfiere con su repositorio local.",
|
||||
"workspace.lifecycle.moving": "Moverse al espacio de trabajo",
|
||||
"workspace.lifecycle.set": "Espacio de trabajo establecido",
|
||||
"session.summary.title": "Detalles de la sesión",
|
||||
"session.summary.noBranch": "Sin rama",
|
||||
"session.summary.basedOn": "Basado en {{branch}}",
|
||||
"settings.workspaces.count.many": "{{count}} espacios de trabajo",
|
||||
"settings.workspaces.sessions.many": "{{count}} sesiones en {{project}}",
|
||||
"desktop.menu.installCli": "Instalar CLI...",
|
||||
"desktop.cli.installed.title": "CLI instalada",
|
||||
"desktop.cli.installed.message":
|
||||
"La CLI se ha instalado en {{path}}.\n\nReinicia el terminal para usar el comando 'opencode2'.",
|
||||
"desktop.cli.failed.title": "Error de instalación",
|
||||
"desktop.cli.failed.message": "No se pudo instalar la CLI: {{error}}",
|
||||
"command.project.copyID": "Copiar ID del proyecto",
|
||||
"command.session.copyID": "Copiar ID de la sesión",
|
||||
"server.row.incompatible":
|
||||
"Este servidor ejecuta OpenCode {{version}}, que no es compatible con esta aplicación. Actualízalo a OpenCode V2 para continuar.",
|
||||
"toast.session.copyID.failed.title": "No se pudo copiar el ID de la sesión",
|
||||
"toast.session.copyID.failed.description": "Ocurrió un error al copiar el ID de la sesión",
|
||||
"toast.project.copyID.failed.title": "No se pudo copiar el ID del proyecto",
|
||||
"toast.project.copyID.failed.description": "Ocurrió un error al copiar el ID del proyecto",
|
||||
"error.page.title.status": "Error en la solicitud al servidor",
|
||||
"error.page.description.status": "El servidor devolvió una respuesta HTTP {{status}}.",
|
||||
"error.page.action.reload": "Volver a cargar",
|
||||
"session.error.incompatible": "Esta versión del servidor no es compatible",
|
||||
"session.error.incompatible.description":
|
||||
"{{server}} ejecuta OpenCode {{version}}, que no es compatible con esta aplicación. Actualiza el servidor a OpenCode V2 para continuar.",
|
||||
"session.background.moveInline": "Pulsa {{keybind}} para pasar el trabajo en curso a segundo plano",
|
||||
"session.background.running": "Trabajo en curso en segundo plano",
|
||||
"session.background.runningCount.one": "{{count}} elemento en curso en segundo plano",
|
||||
"session.background.runningCount.other": "{{count}} elementos en curso en segundo plano",
|
||||
"session.background.runningCount.many": "{{count}} de elementos en curso en segundo plano",
|
||||
"settings.general.row.terminalPlacement.title": "Posición del terminal",
|
||||
"settings.general.row.terminalPlacement.description": "Elige dónde se abre el terminal en las sesiones",
|
||||
"settings.general.row.terminalPlacement.side": "Lateral",
|
||||
"settings.general.row.terminalPlacement.bottom": "Inferior",
|
||||
"command.debugBar.toggle": "Alternar barra de depuración",
|
||||
"command.session.location.cycle": "Cambiar la ubicación de la sesión",
|
||||
"dialog.provider.anthropic.note": "Acceso directo a los modelos Claude mediante una clave de API",
|
||||
"provider.connect.title.anthropicProMax": "Iniciar sesión con Anthropic",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"prompt.toast.uploading.cancel": "Cancelar carga",
|
||||
"prompt.toast.uploading.cancelFile": "Cancelar carga de {{filename}}",
|
||||
"prompt.toast.uploadFailed.title": "Error al cargar",
|
||||
"session.browser.empty.title": "Introduce la URL",
|
||||
"session.browser.empty.description": "O pide «Abrir en el navegador de la aplicación»",
|
||||
"session.browser.failed.title": "No se puede acceder a la URL",
|
||||
"session.browser.failed.description": "Comprueba la URL y la conexión e inténtalo de nuevo.",
|
||||
"debugBar.providerAriaLabel": "Diagnóstico del rendimiento del proveedor",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttft.tip": "Tiempo desde el envío de la solicitud al proveedor hasta la primera salida del modelo.",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.ttfa.tip": "Tiempo desde el envío de la solicitud al proveedor hasta el primer texto de respuesta.",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.tps.tip": "Tókenes de salida por segundo después de la primera salida del modelo.",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
"debugBar.e2e.tip": "Tiempo desde el envío de la solicitud al proveedor hasta que finaliza el flujo de respuesta.",
|
||||
"settings.updates.action.download": "Descargar OpenCode",
|
||||
"settings.updates.migration.title": "Pasar de Beta a Estable",
|
||||
"settings.updates.migration.description":
|
||||
"Por ahora, OpenCode Beta se está trasladando a OpenCode Estable. Descarga la versión {{version}} e instala OpenCode desde la imagen de disco para seguir recibiendo actualizaciones.",
|
||||
}
|
||||
|
||||
@@ -1060,6 +1060,46 @@ export const dict = {
|
||||
"session.delete.confirm": 'Kas kustutada seanss "{{name}}"?',
|
||||
"session.delete.button": "Kustuta seanss",
|
||||
"workspace.new": "Uus tööruum",
|
||||
"common.viewAll": "Kuva kõik",
|
||||
"session.new.workspace.local.tooltip": "Kasuta praegust väljavõtet",
|
||||
"session.new.workspace.new.tooltip": "Loo eraldatud väljavõte",
|
||||
"session.new.workspace.fromBranch": "harust {{branch}}",
|
||||
"session.new.workspace.trigger.tooltip": "Vali, kus seanss käivitada",
|
||||
"session.new.workspace.search.placeholder": "Otsi tööruume",
|
||||
"settings.tab.workspaces": "Tööruumid",
|
||||
"settings.workspaces.filter.all": "Kõik projektid",
|
||||
"settings.workspaces.empty": "Tööruume pole",
|
||||
"settings.workspaces.count.one": "{{count}} tööruum",
|
||||
"settings.workspaces.count.other": "{{count}} tööruumi",
|
||||
"settings.workspaces.sessions.one": "{{count}} seanss projektis {{project}}",
|
||||
"settings.workspaces.sessions.other": "{{count}} seanssi projektis {{project}}",
|
||||
"settings.workspaces.lastActiveSession": "Viimane aktiivne seanss",
|
||||
"settings.workspaces.deleteAll": "Kustuta kõik tööruumid",
|
||||
"settings.workspaces.delete.warning":
|
||||
"Tööruumi kataloog ja haru eemaldatakse jäädavalt koos kõigi allpool näidatud ühendamata muudatustega.",
|
||||
"settings.workspaces.deleteAll.warning":
|
||||
"Ühendamata muudatuste, lingitud seansside või aktiivsete asukohtadega tööpuud jäetakse alles.",
|
||||
"settings.workspaces.delete.blocked.active": "Aktiivset tööruumi ei saa kustutada.",
|
||||
"settings.workspaces.delete.blocked.linked":
|
||||
"Lingitud seansid säilivad, kuid nende töökataloog eemaldatakse jäädavalt.",
|
||||
"settings.workspaces.default.title": "Vaikekeskkond",
|
||||
"settings.workspaces.default.description": "Vali, kus uued seansid algavad",
|
||||
"settings.workspaces.default.lastUsed": "Viimati kasutatud projekti kohta",
|
||||
"settings.workspaces.default.local": "Kohalik kataloog",
|
||||
"settings.workspaces.default.new": "Uus tööruum",
|
||||
"workspace.move.title": "Teisalda tööruumi",
|
||||
"workspace.move.menu.title": "Teisalda seanss asukohta",
|
||||
"workspace.move.failed": "Seansi teisaldamine ebaõnnestus",
|
||||
"workspace.lifecycle.creating": "Tööruumi loomine",
|
||||
"workspace.lifecycle.created": "Tööruum loodud",
|
||||
"workspace.lifecycle.starting": "Seansi käivitamine",
|
||||
"workspace.onboarding.title": "Eralda seansid tööruumidega",
|
||||
"workspace.onboarding.description": "Igal seansil on oma väljavõte, nii et miski ei sega kohalikku hoidlat",
|
||||
"workspace.lifecycle.moving": "Tööruumi teisaldamine",
|
||||
"workspace.lifecycle.set": "Tööruum määratud",
|
||||
"session.summary.title": "Seansi üksikasjad",
|
||||
"session.summary.noBranch": "Haru puudub",
|
||||
"session.summary.basedOn": "Põhineb harul {{branch}}",
|
||||
"workspace.type.local": "kohalik",
|
||||
"workspace.type.sandbox": "liivakast",
|
||||
"workspace.create.failed.title": "Tööruumi loomine ebaõnnestus",
|
||||
@@ -1085,4 +1125,416 @@ export const dict = {
|
||||
"workspace.reset.archived.many": "{{count}} seanssi arhiivitakse.",
|
||||
"workspace.reset.note": "See lähtestab tööruumi, et see vastaks vaikeharule.",
|
||||
"dialog.usageExceeded.dontShowAgain": "Ära kuva enam",
|
||||
"provider.disconnect.toast.noCredentials.description": "Pakkuja {{provider}} jaoks ei leitud eemaldatavaid mandaate.",
|
||||
"provider.disconnect.toast.failed.description": "Pakkuja {{provider}} ühenduse katkestamine ebaõnnestus.",
|
||||
"toast.migration.failed.title": "Andmete migreerimine ebaõnnestus",
|
||||
"command.session.background": "Teisalda taustale",
|
||||
"session.timeline.notice.finished": "{{actor}} lõpetas",
|
||||
"session.timeline.notice.failed": "{{actor}} ebaõnnestus",
|
||||
"session.timeline.notice.cancelled": "{{actor}} tühistati",
|
||||
"settings.tab.preferences": "Eelistused",
|
||||
"settings.tab.notifications": "Teavitused",
|
||||
"settings.tab.projects": "Projektid",
|
||||
"settings.tab.extensions": "Laiendused",
|
||||
"settings.preferences.description": "Kohandage eelistusi, teemat ja vaikekäitumist",
|
||||
"settings.appearance.description": "Kohandage teemat ja fonte",
|
||||
"settings.notifications.description": "Valige, millal teavitusi saada ja helisid kuulda",
|
||||
"settings.shortcuts.description": "Kohandage levinud toimingute otseteid",
|
||||
"settings.servers.description": "Hallake serveriühendusi",
|
||||
"settings.projects.title": "Projektid",
|
||||
"settings.projects.description": "Hallake selle serveri projektisätteid",
|
||||
"settings.projects.empty": "Projekte ei leitud",
|
||||
"settings.projects.server.all": "Kõik serverid",
|
||||
"settings.mcps.description": "Hallake Model Context Protocoli (MCP) servereid ja tööriistu",
|
||||
"settings.extensions.description": "Hallake selles serveris saadaolevaid laiendusi",
|
||||
"settings.extensions.tab.mcps": "MCP-d",
|
||||
"settings.extensions.tab.skills": "Oskused",
|
||||
"settings.extensions.availableAll": "Saadaval kõigile projektidele",
|
||||
"settings.extensions.manageConfig": "Halda failis opencode.json",
|
||||
"settings.extensions.addSkills": "Kuidas oskusi lisada",
|
||||
"dialog.server.authenticate.title": "Autendi",
|
||||
"project.settings.general.description": "Hallake projekti nime ja välimust",
|
||||
"project.settings.scripts": "Skriptid",
|
||||
"project.settings.scripts.description": "Seadistage selle projekti skripte",
|
||||
"project.settings.extensions.description": "Vaadake selle projekti jaoks saadaolevaid laiendusi",
|
||||
"project.settings.extensions.tab.lsps": "LSP-d",
|
||||
"project.settings.extensions.added": "Lisatud sellesse projekti",
|
||||
"project.settings.extensions.shared": "Jagatud kõigi projektidega",
|
||||
"project.settings.extensions.lsp.detected": "Tuvastatud keeleserverid",
|
||||
"project.settings.extensions.lsp.description": "Automaatselt tuvastatud failitüüpide järgi",
|
||||
"project.settings.extensions.setupRequired": "Vajab seadistamist",
|
||||
"settings.general.section.general": "Üldine",
|
||||
"desktop.menu.installCli": "Paigalda CLI...",
|
||||
"desktop.cli.installed.title": "CLI on paigaldatud",
|
||||
"desktop.cli.installed.message":
|
||||
"CLI paigaldati asukohta {{path}}\n\nKäsu 'opencode2' kasutamiseks taaskäivita terminal.",
|
||||
"desktop.cli.failed.title": "Paigaldamine ebaõnnestus",
|
||||
"desktop.cli.failed.message": "CLI paigaldamine ebaõnnestus: {{error}}",
|
||||
"command.project.copyID": "Kopeeri projekti ID",
|
||||
"command.session.copyID": "Kopeeri seansi ID",
|
||||
"server.row.incompatible":
|
||||
"See server käitab OpenCode'i versiooni {{version}}, mis ei ühildu selle rakendusega. Jätkamiseks uuenda server OpenCode V2-le.",
|
||||
"toast.session.copyID.failed.title": "Seansi ID kopeerimine ebaõnnestus",
|
||||
"toast.session.copyID.failed.description": "Seansi ID kopeerimisel tekkis viga",
|
||||
"toast.project.copyID.failed.title": "Projekti ID kopeerimine ebaõnnestus",
|
||||
"toast.project.copyID.failed.description": "Projekti ID kopeerimisel tekkis viga",
|
||||
"error.page.title.status": "Serveripäring ebaõnnestus",
|
||||
"error.page.description.status": "Server tagastas HTTP-vastuse {{status}}.",
|
||||
"error.page.action.reload": "Laadi uuesti",
|
||||
"session.error.incompatible": "Seda serveriversiooni ei toetata",
|
||||
"session.error.incompatible.description":
|
||||
"{{server}} käitab OpenCode'i versiooni {{version}}, mis ei ühildu selle rakendusega. Jätkamiseks uuenda server OpenCode V2-le.",
|
||||
"session.background.moveInline": "Vajuta {{keybind}}, et teisaldada käimasolev töö taustale",
|
||||
"session.background.running": "Töötab taustal",
|
||||
"session.background.runningCount.one": "{{count}} üksus töötab taustal",
|
||||
"session.background.runningCount.other": "{{count}} üksust töötab taustal",
|
||||
"settings.general.row.terminalPlacement.title": "Terminali paigutus",
|
||||
"settings.general.row.terminalPlacement.description": "Vali, kus terminal seanssides avaneb",
|
||||
"settings.general.row.terminalPlacement.side": "Küljel",
|
||||
"settings.general.row.terminalPlacement.bottom": "All",
|
||||
"session.location.unavailable": "Seansi asukoht pole saadaval",
|
||||
"session.location.description": "Selle seansi jätkamiseks vali teine kataloog.",
|
||||
"session.location.choose": "Vali kataloog",
|
||||
"session.location.worktree": "Vali tööpuu",
|
||||
"session.location.worktreesFailed": "Tööpuude laadimine nurjus",
|
||||
"session.location.moving": "Seansi teisaldamine…",
|
||||
"dialog.server.menu.hide": "Peida projektide loendist",
|
||||
"dialog.server.menu.show": "Kuva projektide loendis",
|
||||
"session.queue.count.one": "{{count}} järjekorras",
|
||||
"session.queue.count.other": "{{count}} järjekorras",
|
||||
"session.queue.steer": "Suuna",
|
||||
"session.queue.send": "Saada",
|
||||
"session.queue.steerTooltip": "Saada katkestamata",
|
||||
"session.queue.remove": "Eemalda",
|
||||
"session.queue.reorder": "Muuda järjekorras oleva viiba järjestust",
|
||||
"session.new.worktree.creating": "Tööpuu loomine",
|
||||
"settings.backToApp": "Tagasi rakendusse",
|
||||
"settings.appearance.section.experimental": "Katseline",
|
||||
"settings.appearance.row.tabs.title": "Vahekaardid",
|
||||
"settings.appearance.row.tabs.description": "Vali seansivahekaartide paigutus",
|
||||
"settings.appearance.row.tabs.horizontal": "Horisontaalne",
|
||||
"settings.appearance.row.tabs.vertical": "Vertikaalne",
|
||||
"settings.general.row.followUpBehavior.title": "Jätkusõnumite käitumine",
|
||||
"settings.general.row.followUpBehavior.description":
|
||||
"Vali, kas panna jätkusõnumid järjekorda või suunata praegust vooru. Vahetamiseks kasuta {{keybind}}.",
|
||||
"settings.general.row.followUpBehavior.queue": "Pane järjekorda",
|
||||
"settings.general.row.followUpBehavior.steer": "Suuna",
|
||||
"settings.general.row.reasoningMode.title": "Mudeli arutluskäik",
|
||||
"settings.general.row.reasoningMode.description": "Vali, kuidas mudeli arutluskäiku ajajoonel kuvatakse",
|
||||
"settings.general.row.reasoningMode.hidden": "Peidetud",
|
||||
"settings.general.row.reasoningMode.compact": "Kompaktne",
|
||||
"settings.general.row.reasoningMode.full": "Täielik",
|
||||
"session.new.workspace.createFrom": "Loo harust",
|
||||
"session.new.workspace.branch.search.placeholder": "Otsi harusid",
|
||||
"toast.migration.progress.clearingOldEvents": "Vanade sündmuste kustutamine",
|
||||
"toast.migration.progress.migratingSessions": "Seansside migreerimine",
|
||||
"session.new.workspace.existingLabel": "Tööpuu",
|
||||
"desktop.onboarding.defaultProject": "Vaikeprojekt",
|
||||
"home.projects.all": "Kõik projektid",
|
||||
"session.tab.files": "Failid",
|
||||
"session.files.openTabs": "Ava failid",
|
||||
"session.tab.usage": "Kasutamine",
|
||||
"session.view.select": "Seansi vaade",
|
||||
"session.background.moveTasks": "Teisalda {{tasks}} taustale",
|
||||
"session.background.moveRunning": "Liiguta taustale",
|
||||
"session.background.inBackground": "{{tasks}} töötab taustal",
|
||||
"session.background.tasksRunning.one": "{{count}} taustaülesanne töötab",
|
||||
"session.background.tasksRunning.other": "{{count}} taustaülesanded töötavad",
|
||||
"session.background.combine": "{{first}} ja {{second}}",
|
||||
"session.background.shell.one": "{{count}} Shell",
|
||||
"session.background.shell.other": "{{count}} Shelli",
|
||||
"session.background.subagent.one": "{{count}} alamagent",
|
||||
"session.background.subagent.other": "{{count}} alamagendid",
|
||||
"session.timeline.working": "Töötab",
|
||||
"session.review.wrapLines": "Ridade murdmine",
|
||||
"session.websearch.title": "Kolmanda osapoole veebiotsing",
|
||||
"session.websearch.description": "Valige otsingupakkuja agendid, mida veebist otsimiseks kasutavad",
|
||||
"session.websearch.provider": "Otsi pakkuja",
|
||||
"session.websearch.any": "Ükskõik milline",
|
||||
"session.websearch.disable": "Ärge kasutage otsingut",
|
||||
"session.websearch.enable": "Luba",
|
||||
"session.websearch.loadFailed": "Otsingupakkujaid ei saanud laadida.",
|
||||
"session.websearch.empty": "Otsingupakkujaid pole saadaval.",
|
||||
"session.websearch.failed": "Teie valikut ei saanud salvestada. Palun proovi uuesti.",
|
||||
"session.websearch.retry": "Proovi uuesti",
|
||||
"session.new.worktree.draftPlaceholder": "Koostage tööpuu ettevalmistamise ajal järelmeetmete mustand…",
|
||||
"session.search.placeholder": "Leia…",
|
||||
"session.search.noResults": "Vasteid pole",
|
||||
"titlebar.tabs": "Vahekaardid",
|
||||
"titlebar.channel.local": "Kohalik",
|
||||
"titlebar.channel.dev": "Dev",
|
||||
"titlebar.channel.beta": "Beta",
|
||||
"titlebar.toggleDebugTools": "Silumistööriistade sisse- ja väljalülitamine",
|
||||
"settings.tab.experimental": "Eksperimentaalne",
|
||||
"settings.experimental.description": "Proovige eksperimentaalseid funktsioone",
|
||||
"settings.tab.about": "Teave",
|
||||
"settings.about.version": "Versioon {{version}}",
|
||||
"settings.about.devVersion": "arendus",
|
||||
"settings.about.license": "Välja antud MIT-i litsentsi alusel",
|
||||
"settings.about.writtenBy": "Kirjutas",
|
||||
"settings.about.illustratedBy": "Illustreerinud",
|
||||
"settings.about.and": "ja",
|
||||
"settings.about.otherContributor.one": "{{count}} muu",
|
||||
"settings.about.otherContributor.other": "{{count}} teised",
|
||||
"settings.about.firstPublished": "Esmakordselt avaldati USA-s Missouris",
|
||||
"settings.about.firstIllustrated": "Esmakordselt illustreeritud Londonis, Inglismaal",
|
||||
"settings.about.website": "www.opencode.ai",
|
||||
"settings.about.description": "OpenCode, avatud lähtekoodiga kodeerimisagent",
|
||||
"settings.about.trademark": "OpenCode on ettevõtte Anomaly Innovations, Inc. registreeritud kaubamärk.",
|
||||
"settings.about.typeset": "Sisestatud Inter ja IBM Plex Mono",
|
||||
"settings.about.tagline": "AI ei saa ilma sinuta suurepärast tarkvara luua",
|
||||
"settings.about.copyright": "© Anomaly Innovations, Inc.",
|
||||
"project.settings.title": "Redigeeri projekti",
|
||||
"settings.timeline.title": "Ajaskaala",
|
||||
"settings.timeline.detail": "Ajaskaala üksikasjad",
|
||||
"settings.timeline.description": "Valige, kui palju tegevusi ajaskaalal kuvatakse. Sõnumid jäävad nähtavaks.",
|
||||
"settings.timeline.preset.everything": "Kõik",
|
||||
"settings.timeline.preset.detailed": "Üksikasjalik",
|
||||
"settings.timeline.preset.compact": "Kompaktne",
|
||||
"settings.timeline.preset.quiet": "Vaikne",
|
||||
"settings.timeline.preset.text-only": "Ainult tekst",
|
||||
"settings.timeline.description.everything":
|
||||
"Kuva kõik tegevused eraldi. Laiendage kesta väljundit, redigeerimisi ja mõtlemist.",
|
||||
"settings.timeline.description.detailed":
|
||||
"Laienda kesta väljundit ja redigeerimisi. Kuva alamagendid eraldi ja muud tegevused grupeerige jaotises Kasutatud.",
|
||||
"settings.timeline.description.compact": "Grupeeri kõik tegevused jaotises Kasutatud koos ahendatud üksikasjadega.",
|
||||
"settings.timeline.description.quiet": "Grupitöötlused ja alamagendid jaotises Kasutatud. Peida muu tegevus.",
|
||||
"settings.timeline.description.text-only": "Peida kogu tegevus. Kuva ainult sõnumid.",
|
||||
"settings.timeline.description.custom": "Kasutage iga tegevuskategooria jaoks valitud paigutust ja üksikasju.",
|
||||
"settings.timeline.custom": "Kohandatud",
|
||||
"settings.timeline.advanced": "Täpsemalt",
|
||||
"settings.timeline.advanced.description": "Määrake iga tegevuskategooria paigutus ja üksikasjad.",
|
||||
"settings.timeline.category.shell": "Shell",
|
||||
"settings.timeline.category.edit": "Muudatused",
|
||||
"settings.timeline.category.thinking": "Mõtlemine",
|
||||
"settings.timeline.category.subagents": "Alamagendid",
|
||||
"settings.timeline.category.notices": "Märkused",
|
||||
"settings.timeline.category.tools": "Muud tööriistad",
|
||||
"settings.general.row.mobileDiffWrap.description":
|
||||
"Horisontaalselt kerimise asemel mähkige pikad jooned mobiilidiffidesse",
|
||||
"provider.connect.error.unsupportedFields": "See autentimisvorm sisaldab toetamata välju",
|
||||
"session.review.filesChangedCount.one": "{{count}} faili muudetud",
|
||||
"session.review.filesChangedCount.other": "{{count}} faili muudetud",
|
||||
"settings.about.writtenByNames": "Kirjutas {{names}}",
|
||||
"settings.about.illustratedByNames": "Illustreerinud {{names}}",
|
||||
"ssh.label": "SSH",
|
||||
"ssh.offline": "Pole ühendatud võrguga {{host}}. Teie mustand on säilinud; kaugtöö võib endiselt töötada.",
|
||||
"ssh.placeholder": "ssh kasutaja@example.com",
|
||||
"ssh.add": "Lisa SSH server",
|
||||
"ssh.server.menu.label": "SSH server",
|
||||
"ssh.target": "Host või SSH käsk",
|
||||
"ssh.connect": "Ühendage",
|
||||
"ssh.connectTo": "Ühendage seadmega {{host}}",
|
||||
"ssh.authenticate": "SSH autentimine",
|
||||
"ssh.action.authenticate": "Autentida",
|
||||
"ssh.session.disconnected": "SSH ühendus inaktiivne",
|
||||
"ssh.session.connecting": "Ühendamine serveriga SSH",
|
||||
"ssh.session.reconnectDescription":
|
||||
"Ühendage uuesti selle seansi vaatamiseks ja töö jätkamiseks. Teie kaugseanss säilib.",
|
||||
"ssh.session.reconnect": "Ühendage uuesti",
|
||||
"ssh.authenticationRequired": "{{host}} jaoks on vajalik autentimine",
|
||||
"ssh.trust": "Usalda ja ühenda",
|
||||
"ssh.continue": "Jätka",
|
||||
"ssh.retry": "Proovi uuesti",
|
||||
"ssh.update": "Värskendage ja ühendage uuesti",
|
||||
"ssh.openProject": "Avatud projekt",
|
||||
"ssh.project": "Avatud projekt saidil {{host}}",
|
||||
"ssh.disconnect": "Katkesta ühendus",
|
||||
"ssh.forget": "Unusta ühendus",
|
||||
"ssh.stage.disconnected": "Ühendus katkestatud. Kaugserver jäetakse tööle.",
|
||||
"ssh.stage.connecting": "Ühendamine üle SSH…",
|
||||
"ssh.stage.checking": "OpenCode kontrollimine…",
|
||||
"ssh.stage.downloading": "Serveri allalaadimine…",
|
||||
"ssh.stage.uploading": "Serveri üleslaadimine…",
|
||||
"ssh.stage.starting": "Ühendamine seadmega OpenCode…",
|
||||
"ssh.stage.ready": "Ühendatud",
|
||||
"ssh.stage.authentication": "Nõutav autentimine",
|
||||
"ssh.stage.incompatible": "Vajalik serveri värskendus",
|
||||
"ssh.stage.failed": "Ühendus ebaõnnestus",
|
||||
"ssh.error.input": "Sisestage hosti või SSH ühenduse käsk. Kaugkäsklused ja toetamata SSH suvandid pole lubatud.",
|
||||
"ssh.error.connection": "Ühendust SSH ei õnnestunud luua. Kontrollige oma võrku ja SSH konfiguratsiooni.",
|
||||
"ssh.error.platform":
|
||||
"Seda kaugplatvormi ei toetata. Automaatne seadistamine nõuab praegu mudelit x64 või arm64 Linux või macOS.",
|
||||
"ssh.error.version": "Kaugteenus peab enne ühenduse loomist vastama sellele töölauaversioonile.",
|
||||
"ssh.error.install":
|
||||
"Kaugserverit ei saanud installida. Kontrollige ühenduvust, kettaruumi ja seda, kas tar on installitud.",
|
||||
"ssh.error.unpublished":
|
||||
"Sellel töölauaversioonil pole avaldatud kaugserverit. Arendusjärkude jaoks installige ja käivitage hostis V2, seejärel proovige uuesti.",
|
||||
"ssh.error.service": "SSH on ühendatud, kuid server OpenCode ei saanud valmis.",
|
||||
"ssh.error.host-key":
|
||||
"Võõrustaja identiteeti ei õnnestunud kinnitada. Enne SSH teadaolevate hostide värskendamist kontrollige selle sõrmejälge.",
|
||||
"ssh.error.ssh-missing": "OpenSSH ei leitud. Installige OpenSSH klient ja veenduge, et ssh oleks PATH-il saadaval.",
|
||||
"command.browser.open": "Ava brauser",
|
||||
"command.browser.reload": "Laadi brauseri leht uuesti",
|
||||
"command.session.summary.toggle": "Lülitab kokkuvõtet",
|
||||
"mcp.auth.interactiveForm": "MCP server {{name}} nõuab interaktiivset autentimisvormi",
|
||||
"server.connect.title": "Ühendage serveriga",
|
||||
"server.connect.description": "Alustamiseks sisestage oma serveri aadress ja parool.",
|
||||
"server.connect.button": "Ühendage",
|
||||
"server.connect.address.invalid": "Sisestage kehtiv serveri aadress HTTP või HTTPS.",
|
||||
"server.connect.failed": "Ühendust ei õnnestunud luua. Kontrollige serveri aadressi ja parooli ning proovige uuesti.",
|
||||
"server.connect.pair.description": "Ühenduse üksikasjade hankimiseks käivitage see käsk oma arvutis.",
|
||||
"server.connect.scan": "Skaneeri QR-kood",
|
||||
"server.connect.scan.description": "Suunake oma kaamera koodile QR, mida näitab opencode pair.",
|
||||
"server.connect.scan.invalid": "See ei ole OpenCode sidumiskood. Skannige koodi, mida näitab opencode pair.",
|
||||
"server.connect.camera": "Kaamera sidumine",
|
||||
"server.connect.camera.starting": "Kaamera avamine…",
|
||||
"server.connect.mixedContent":
|
||||
"Selle HTTP serveriga ei saanud HTTPS lehelt ühendust luua. Kasutage selle asemel HTTPS serveri aadressi.",
|
||||
"server.connect.camera.insecure": "QR skannimine nõuab selle lehe avamist HTTPS või localhost kaudu.",
|
||||
"server.connect.camera.unavailable":
|
||||
"Selle brauseri jaoks pole kaamerat saadaval. Sisestage ühenduse üksikasjad käsitsi.",
|
||||
"server.connect.camera.error":
|
||||
"Kaamerat ei saanud avada. Lubage juurdepääs kaamerale või sisestage ühenduse üksikasjad käsitsi.",
|
||||
"dialog.server.menu.remove": "Eemalda",
|
||||
"file.error.notFound": "Faili ei leitud: {{name}}",
|
||||
"home.workspaceTip": "Alustage järgmist seanssi uues tööruumis, et hoida muudatused isoleerituna",
|
||||
"session.tab.browser": "Brauser",
|
||||
"session.tab.add": "Lisa vahekaart",
|
||||
"session.queue.attachments.one": "Plus {{count}} kinnitus",
|
||||
"session.queue.attachments.other": "Pluss {{count}} lisaseadmed",
|
||||
"session.browser.address": "Brauseri aadress",
|
||||
"session.browser.replaced": "Brauseri juhtimine teisaldati teise töölauaaknasse.",
|
||||
"session.browser.suspended": "Brauser peatatud. Ühendage uuesti ühenduse loomiseks selle seansiga.",
|
||||
"session.browser.address.placeholder": "Sisesta URL",
|
||||
"settings.backToSettings": "Tagasi seadete juurde",
|
||||
"settings.backToProjects": "Tagasi projektide juurde",
|
||||
"settings.search.placeholder": "Otsi",
|
||||
"settings.search.results": "Seadete tulemused",
|
||||
"settings.search.group.pages": "Leheküljed",
|
||||
"settings.search.group.settings": "Seaded",
|
||||
"settings.search.group.projects": "Projektid",
|
||||
"settings.search.group.servers": "Serverid",
|
||||
"settings.search.result": "{{title}}, {{scope}}, {{page}}",
|
||||
"settings.search.page": "{{title}}, {{scope}}",
|
||||
"settings.search.result.unscoped": "{{title}}, {{page}}",
|
||||
"settings.search.empty": "Päringule {{query}}",
|
||||
"settings.search.empty.query": 'ei leitud tulemusi "{{query}}"',
|
||||
"settings.search.refine": "Kitsendage otsingut, et näha täpsemaid tulemusi.",
|
||||
"settings.server.description": "Selle serveri ühenduse ja eelistuste haldamine",
|
||||
"settings.server.section.connection": "Ühendus",
|
||||
"settings.server.preferences.websearch.title": "Kolmanda osapoole otsing",
|
||||
"settings.server.preferences.websearch.description":
|
||||
"Valige otsingupakkuja agendid, mida veebist otsimiseks kasutavad",
|
||||
"settings.projects.search.placeholder": "Otsi projekte",
|
||||
"project.settings.name.title": "Projekti nimi",
|
||||
"project.settings.name.description": "Selle projekti jaoks kuvatud nimi kogu OpenCode",
|
||||
"project.settings.icon.description": "Soovitatav: 128 × 128 pikslit. Pildi üleslaadimiseks klõpsake või lohistage.",
|
||||
"project.settings.color.description": "Kasutatakse projekti ikooni jaoks, kui kohandatud pilti pole määratud",
|
||||
"project.settings.worktree.startup.description": "Käitab üks kord pärast uue tööpuu loomist",
|
||||
"project.settings.worktree.startup.hint.base": "Kasutage põhitööpuuna $OPENCODE_WORKTREE_BASE.",
|
||||
"project.settings.worktree.startup.hint.new": "Kasutage uue tööpuu jaoks $OPENCODE_WORKTREE_PATH.",
|
||||
"project.settings.extensions.empty.mcps.title": "MCPs puudub veel",
|
||||
"project.settings.extensions.empty.mcps.description": "MCPs, mis on saadaval OpenCode jaoks, kuvatakse siin",
|
||||
"project.settings.extensions.empty.plugins.title": "Pluginaid pole veel",
|
||||
"project.settings.extensions.empty.plugins.description": "OpenCode jaoks saadaolevad pistikprogrammid kuvatakse siin",
|
||||
"project.settings.extensions.empty.skills.title": "Oskusi veel pole",
|
||||
"project.settings.extensions.empty.skills.description": "Siin kuvatakse OpenCode jaoks saadaolevad oskused",
|
||||
"project.settings.extensions.lsp.configured": "Konfigureeritud keeleserverid",
|
||||
"project.settings.extensions.lsp.status.enabled": "Lubatud konfiguratsioonis",
|
||||
"project.settings.extensions.lsp.status.disabled": "Keelatud konfiguratsioonis",
|
||||
"project.settings.extensions.lsp.empty.title": "Keeleservereid pole konfigureeritud",
|
||||
"project.settings.extensions.lsp.empty.description": "Selle projekti jaoks seadistatud keeleserverid kuvatakse siin",
|
||||
"project.settings.extensions.lsp.disabled.title": "Keeleserverid keelatud",
|
||||
"project.settings.extensions.lsp.disabled.description": "LSP on selle projekti konfiguratsioonis keelatud",
|
||||
"project.settings.extensions.lsp.loadFailed": "Keeleserveri konfiguratsiooni ei saanud laadida",
|
||||
"project.settings.extensions.lsp.retry": "Proovi uuesti",
|
||||
"settings.timeline.summary": "{{preset}}:",
|
||||
"settings.timeline.group": "Rühm",
|
||||
"settings.timeline.collapse": "Ahenda",
|
||||
"settings.timeline.visibility.show": "Näita",
|
||||
"settings.timeline.visibility.hide": "Peida",
|
||||
"settings.timeline.visibility.label": "{{activity}} nähtavus",
|
||||
"settings.timeline.grouped.label": "{{activity}} rühmitatud",
|
||||
"settings.timeline.collapsed.label": "{{activity}} varises kokku",
|
||||
"session.new.workspace.search.empty": "Sobivaid tööpuid pole",
|
||||
"settings.workspaces.description": "Vaadake üle tööpuud ja hallake kettakasutust",
|
||||
"settings.workspaces.empty.description": "Siin kuvatakse programmis OpenCode loodud tööpuud",
|
||||
"settings.workspaces.sessions.filtered.one": "{{count}} seanss",
|
||||
"settings.workspaces.sessions.filtered.other": "{{count}} seansid",
|
||||
"settings.workspaces.deleteAll.confirm.one": "See kustutab jäädavalt valitud tööpuu {{count}}.",
|
||||
"settings.workspaces.deleteAll.confirm.other": "See kustutab {{count}} valitud tööpuud jäädavalt.",
|
||||
"settings.workspaces.deleteWithoutSessions": "Kustuta tööpuud ilma seanssideta",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.one":
|
||||
"See kustutab {{count}} tööpuu jäädavalt ilma lingitud seanssideta.",
|
||||
"settings.workspaces.deleteWithoutSessions.confirm.other":
|
||||
"See kustutab jäädavalt {{count}} tööpuud ilma lingitud seanssideta.",
|
||||
"settings.workspaces.deleteWithoutSessions.warning":
|
||||
"Ühendamata muudatuste või aktiivsete asukohtadega tööpuud jäetakse alles.",
|
||||
"settings.workspaces.delete.button": "Kustuta tööpuud",
|
||||
"workspace.lifecycle.deleting": "Kustutamine…",
|
||||
"session.summary.tooltip": "Kokkuvõte",
|
||||
"session.summary.server": "Laiendused",
|
||||
"session.summary.chooseProject": "Valige projekt",
|
||||
"session.summary.mcp.onCreation": "Kehtib tööpuu loomisel",
|
||||
"session.summary.mcp.prepareFailed": "MCP servereid ei saanud ette valmistada",
|
||||
"session.summary.mcp.unavailable": "MCP server {{name}} pole selles tööpuus saadaval.",
|
||||
"session.summary.mcp.signInBeforeSend": "Enne viipa saatmist logige sisse {{name}}.",
|
||||
"session.summary.mcp.notReady": "MCP server {{name}} pole valmis. Enne viipa saatmist lahendage selle ühendus.",
|
||||
"session.summary.mcp": "MCP",
|
||||
"session.summary.mcp.title": "Konfigureeritud MCP serverid",
|
||||
"session.summary.plugins": "Pluginad",
|
||||
"session.summary.plugins.configured": "Konfigureeritud pluginad",
|
||||
"session.summary.skills": "Oskused",
|
||||
"session.summary.skills.configured": "Konfigureeritud oskused",
|
||||
"session.summary.lsp": "LSP",
|
||||
"session.summary.failed": "Ebaõnnestunud",
|
||||
"session.summary.retry": "Proovi uuesti",
|
||||
"session.summary.connecting": "Ühendamine…",
|
||||
"session.summary.needsAuth": "Sisselogimine on vajalik",
|
||||
"session.summary.configure": "Konfiguratsioonifail",
|
||||
"session.summary.copyConfigPath": "Kopeeri konfiguratsioonifaili tee",
|
||||
"session.summary.configFileMissing": "Konfiguratsioonifaili ei leitud",
|
||||
"session.summary.mcp.empty": "MCP servereid pole konfigureeritud",
|
||||
"session.summary.mcp.add": "Lisage serverid faili opencode.json",
|
||||
"session.summary.plugins.manage": "Hallake pluginaid saidil opencode.json",
|
||||
"session.summary.plugins.empty": "Ühtegi pluginat pole seadistatud",
|
||||
"session.summary.plugins.add": "Lisage pluginaid faili opencode.json",
|
||||
"session.summary.skills.manage": "Oskuste haldamine failis opencode.json",
|
||||
"session.summary.skills.empty": "Oskusi pole konfigureeritud",
|
||||
"session.summary.skills.add": "Lisage oskused failis opencode.json",
|
||||
"session.summary.lsp.configured": "Konfigureeritud LSPs",
|
||||
"session.summary.lsp.empty": "LSP servereid pole konfigureeritud",
|
||||
"session.summary.lsp.manage": "LSP haldamine failis opencode.json",
|
||||
"workspace.delete.location": "Asukoht",
|
||||
"common.color.orange": "oranž",
|
||||
"common.color.yellow": "kollane",
|
||||
"common.color.cyan": "tsüaan",
|
||||
"common.color.green": "roheline",
|
||||
"common.color.red": "punane",
|
||||
"common.color.pink": "roosa",
|
||||
"common.color.blue": "sinine",
|
||||
"common.color.purple": "lilla",
|
||||
"common.color.gray": "hall",
|
||||
"toast.migration.progress.migratingSessions.current": "Seansside üleviimine {{current}}",
|
||||
"toast.migration.progress.migratingSessions.progress": "Seansside üleviimine {{current}}/{{total}}",
|
||||
"toast.migration.progress.working": "Andmete migreerimine",
|
||||
"toast.migration.progress.working.current": "Andmete migreerimine {{current}}",
|
||||
"toast.migration.progress.working.progress": "Andmete üleviimine {{current}}/{{total}}",
|
||||
"session.browser.unsupported": "See töölauarakendus ei toeta brauseri paani.",
|
||||
"command.debugBar.toggle": "Lülita silumisriba",
|
||||
"command.session.location.cycle": "Vaheta seansi asukohta",
|
||||
"dialog.provider.anthropic.note": "Otsejuurdepääs Claude’i mudelitele API-võtmega",
|
||||
"provider.connect.title.anthropicProMax": "Logi Anthropicuga sisse",
|
||||
"prompt.toast.uploading.percent": "{{percent}}%",
|
||||
"prompt.toast.uploading.cancel": "Tühista üleslaadimine",
|
||||
"prompt.toast.uploading.cancelFile": "Tühista faili {{filename}} üleslaadimine",
|
||||
"prompt.toast.uploadFailed.title": "Üleslaadimine nurjus",
|
||||
"session.browser.empty.title": "Sisesta URL",
|
||||
"session.browser.empty.description": "Või palu „Ava rakenduse brauseris”",
|
||||
"session.browser.failed.title": "URL-ile ei pääse juurde",
|
||||
"session.browser.failed.description": "Kontrolli URL-i ja ühendust ning proovi uuesti.",
|
||||
"debugBar.providerAriaLabel": "Pakkuja jõudluse diagnostika",
|
||||
"debugBar.ttft.label": "TTFT",
|
||||
"debugBar.ttft.tip": "Aeg pakkujale päringu saatmisest mudeli esimese väljundini.",
|
||||
"debugBar.ttfa.label": "TTFA",
|
||||
"debugBar.ttfa.tip": "Aeg pakkujale päringu saatmisest esimese vastusetekstini.",
|
||||
"debugBar.tps.label": "TPS",
|
||||
"debugBar.tps.tip": "Väljundmärke sekundis pärast mudeli esimest väljundit.",
|
||||
"debugBar.e2e.label": "E2E",
|
||||
"debugBar.e2e.tip": "Aeg pakkujale päringu saatmisest vastusevoo lõppemiseni.",
|
||||
"settings.updates.action.download": "Laadi OpenCode alla",
|
||||
"settings.updates.migration.title": "Liigu beetaversioonilt stabiilsele versioonile",
|
||||
"settings.updates.migration.description":
|
||||
"Praegu liigub OpenCode Beta versioonile OpenCode Stable. Laadi alla versioon {{version}} ja installi OpenCode kettatõmmiselt, et jätkata uuenduste saamist.",
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user