open-design/apps/web/src/i18n/locales/zh-CN.ts
lefarcen e1bc83a476
feat(analytics): PostHog product analytics (P0 events, consent-gated, packaged) (#1428)
* feat(analytics): scaffold PostHog product-analytics integration

- Add @open-design/contracts/analytics subpath with the 17 P0 event
  payload types, header constants, and code↔CSV enum mapping helpers.
- Add apps/daemon/src/analytics.ts with env-gated posthog-node client,
  request-scoped analytics context reader, and artifact-id anonymizer.
- Expose GET /api/analytics/config so the web bundle never embeds the
  PostHog key at build time; daemon owns POSTHOG_KEY / POSTHOG_HOST.
- Add apps/web/src/analytics module (identity + lazy posthog-js client
  + React provider) and mount it under <I18nProvider> in app/layout.

No event wiring yet — that lands in the next commit alongside trigger
points (App.tsx, EntryView, NewProjectPanel, SettingsDialog, FileViewer,
runs.ts).

* feat(analytics): wire app_launch, home_view, home_click, project_create_result

- App.tsx: fire app_launch once after first effect tick. handleCreateProject
  now emits project_create_result on both success and failure paths.
- EntryView.tsx: home_view (page) gated on agents loading so
  has_available_cli isn't transiently false; home_view (asset_panel) fires
  per top-tab change with the right result_count.
- NewProjectPanel.tsx: home_click create_button fires before delegating to
  the parent; a fresh request_id is generated here and threaded through
  onCreate so the matching project_create_result stitches via $insert_id.
- contracts/analytics: tighten createTabToTracking and topTabToTracking
  for the worktree branch's renamed tabs (live-artifact, templates).

* feat(analytics): wire settings_view + 3 settings_click events

- settings_view fires on dialog mount and on every section switch,
  carrying the active section (mapped via settingsSectionToTracking
  for the 16-section worktree layout), execution_mode, and the
  selected CLI provider id when present.
- settings_click execution_mode_tab: setMode now emits before/after
  values whenever the user toggles between Local CLI and BYOK.
- settings_click cli_provider_card: agent card onClick reports
  cli_provider_id via agentIdToTracking (kiro → other).
- settings_click byok_field: onFocus added to api_key, model select,
  and base_url inputs; provider_id widened to include google so the
  worktree's Gemini protocol slot type-checks.

* feat(analytics): wire studio_view + studio_click chat, studio_view artifact

- packages/contracts/src/analytics/artifact-id.ts: FNV-1a 64-bit helper
  produces a 16-hex anonymized id for (projectId, fileName). Stable
  cross-platform so the daemon and the web bundle resolve the same id
  without a Web Crypto round-trip; daemon now re-exports it.
- ChatComposer: studio_view chat_panel fires once per project mount,
  studio_click chat_composer fires on attachment + send buttons with
  estimated user_query_tokens (length/4) and has_attachment.
- FileViewer: studio_view artifact fires once per (project, file) at
  the dispatcher level, before any sub-viewer renders, with
  artifact_kind derived from the renderer registry / file.kind table.
- Widen TrackingExportFormat to include markdown and cloudflare_pages
  so the worktree branch's full share menu can emit verbatim.

* feat(analytics): wire studio_click share_option + artifact_export_result

HtmlViewer's share menu now emits both events per click via a
fireShareExport helper:

- studio_click share_option fires immediately on click with the chosen
  export_format and a fresh request_id.
- artifact_export_result fires when the export resolves — success for
  sync exporters (html, markdown, template) the moment the call
  returns, success/failed for async exporters (pdf, zip, deploy)
  via .then/.catch. The same request_id threads both events so
  PostHog stitches click → result via $insert_id.

DEPLOY_PROVIDER_OPTIONS maps to the CSV's vercel / cloudflare_pages
slots; markdown is now a first-class export_format value.

Also ignore .env.local so local POSTHOG_KEY / .env-style secrets
don't get committed.

* feat(analytics): emit run_created and run_finished from the daemon

POST /api/runs now reads the analytics context off the
x-od-analytics-* headers the web client sets on every fetch, then:

- Captures run_created with project_id, conversation_id, run_id,
  model_id, agent_provider_id (mapped via agentIdToTracking),
  skill_id, design_system_id, plus the token_count_source marker.
- Schedules a run_finished capture on runs.wait(run) resolution,
  mapping succeeded/canceled/failed to success/cancelled/failed and
  reporting total_duration_ms.

Both events use a stable insert_id derived from the same uuid so
PostHog dedupes the daemon-side mirror against any future
web-side capture without double-counting.

Token sub-fields (user_query_tokens/system_prompt_tokens/...) stay
omitted in v1 — the claude-stream parser only exposes input/output
totals today. See tracking-doc-issues.md §3.2.

* feat(analytics): emit settings_cli_test_result + settings_byok_test_result

The original BLOCKING-list assumed these CSV P0 events were not
implementable in this branch because main lacked Test buttons. The
worktree HEAD actually wires `handleTestAgent` and `handleTestProvider`
in SettingsDialog, so both events are now in scope.

- handleTestAgent emits settings_cli_test_result on success and
  failure paths with cli_provider_id mapped via agentIdToTracking,
  result drawn from result.ok / catch branch, error_code from
  result.kind or the thrown error name, and duration_ms timed via
  performance.now().
- handleTestProvider emits settings_byok_test_result analogously,
  using apiProtocol (anthropic|openai|azure|ollama|google) directly
  as provider_id — wider than the CSV's 5-value enum, documented in
  tracking-doc-issues.md §2.5.

Contracts: add SettingsCliTestResultProps / SettingsByokTestResultProps
plus matching track* helpers. AnalyticsEventName union now covers all
14 P0 events this branch supports.

* feat(analytics): gate PostHog on the existing telemetry.metrics consent

The integration now reuses the same first-launch privacy banner +
Settings → Privacy toggle that gates Langfuse, so a single user
decision controls both telemetry sinks.

- /api/analytics/config now consults the persisted AppConfigPrefs:
  it returns enabled=true only when POSTHOG_KEY is set AND the user
  has chosen "Share usage data" (telemetry.metrics === true). The
  response also echoes installationId so the web client uses the
  same anonymous id Langfuse keys off of — one identity per install,
  shared across both sinks.
- Web AnalyticsProvider:
  - Bootstrap fetch resolves installationId and threads it through
    the x-od-analytics-anonymous-id header on every /api/* fetch,
    so daemon-side captures (run_created / run_finished /
    project_create_result) land on the same person record.
  - Exposes a setConsent(granted) method that calls posthog-js's
    opt_in_capturing / opt_out_capturing, wired from App.tsx via a
    useEffect watching config.telemetry?.metrics. Toggling Privacy
    → metrics now stops/resumes events immediately, no reload.
- app_launch additionally gates on telemetry.metrics so a freshly-
  declined user fires nothing, and a freshly-opted-in user fires on
  the next reload.

* feat(packaging): bake POSTHOG_KEY into packaged daemon spawn env

Wires PostHog product analytics through the same Langfuse-style build-
secret pipeline so official Open Design builds ship with the key while
fork builds compile without it (the integration short-circuits cleanly
when POSTHOG_KEY is absent).

tools/pack
- resolveToolPackConfig reads POSTHOG_KEY / POSTHOG_HOST from
  process.env at packaging time, validates them (no whitespace in the
  key, http(s) URL for host, trailing-slash strip), and stamps them on
  ToolPackConfig. Fork builds without the env vars simply omit the
  fields; the daemon-side gate keeps things off in that case.
- Mac, Windows, and Linux packaged-config writers each append the two
  fields to open-design-config.json next to the existing
  telemetryRelayUrl entry.

apps/packaged
- RawPackagedConfig / PackagedConfig surface posthogKey / posthogHost
  so the Electron entry and headless entry both forward them to the
  daemon sidecar.
- buildPackagedDaemonSpawnEnv emits POSTHOG_KEY / POSTHOG_HOST into
  the daemon child env when present. The daemon's existing analytics
  module reads these via process.env — no daemon-side changes needed.
- The headless packaged path falls back to process.env for fields the
  builder hasn't injected, mirroring how OPEN_DESIGN_TELEMETRY_RELAY_URL
  is read there.

CI
- release-beta.yml and release-stable.yml expose POSTHOG_KEY (secret)
  and POSTHOG_HOST (var) at workflow-env scope so every packaging job
  inherits them. PR / fork builds without these set simply skip the
  bake step.

Tests
- tools/pack: config.test.ts covers bake-through, fork-build omission,
  whitespace rejection, invalid-URL rejection, and trailing-slash
  normalization.
- apps/packaged: sidecars.test.ts covers buildPackagedDaemonSpawnEnv
  forwarding the keys when present and omitting them when null.

* feat(analytics): enable PostHog autocapture + perf + exceptions

Flip on the PostHog SDK's automatic diagnostic features so we capture
click paths, page transitions, web vitals, dead clicks, and browser
exceptions without scattering instrumentation through the codebase.

Privacy defense lives in one place — apps/web/src/analytics/scrub.ts —
wired in via posthog-js's `before_send` hook so every outgoing event
passes through the same audit point:

  - $autocapture / $rageclick / $dead_click / $copy_autocapture:
    strips $el_text and value/placeholder/aria-label attrs from any
    input, textarea, password input, or contenteditable element. PostHog
    autocapture does not capture input.value by default, but $el_text
    on a <textarea> reflects the typed content — that's the prompt
    body for us, so it has to be scrubbed every time.
  - $pageview / $pageleave: drops query string and fragment from
    $current_url / $referrer so any future ?q=… can't leak.
  - $exception: rewrites file:// and absolute filesystem paths in
    stack frames to app://apps/<repo-relative> so we don't ship the
    user's home directory.
  - Suppresses $opt_in entirely — duplicate of our explicit
    setConsent toggle in App.tsx.

Element-level defense in depth is limited to the single most sensitive
surface: the chat composer textarea gets `ph-no-capture` so PostHog
never even generates an event for clicks inside that subtree. Every
other input relies on scrub.ts — sprinkling the class through every
form would be noisy and easy to forget on new surfaces.

The existing Privacy → "Share usage data" toggle continues to gate
every new feature: posthog-js's opt_out_capturing() halts autocapture,
$pageview, $exception, web vitals, and dead clicks alongside the
explicit capture() calls — one global switch.

11 unit tests pin the scrub rules in apps/web/tests/analytics-scrub.test.ts.

* ci(nix): bump pnpmDepsHash for posthog-js + posthog-node additions

Adding posthog-js to apps/web and posthog-node to apps/daemon changed
pnpm-lock.yaml, which Nix's fixed-output pnpmDeps derivation pins by
sha256. The CI nix flake check failed with:

  specified: sha256-KF3Mld72/iau+pJmA7HvnanRx8VLtDP0N624SKrtrrc=
  got:       sha256-PGFgX4lYyeH2TRAXfUq52A3EOa6bb1gO59hPsXhEk3s=

Copy the new hash into both nix/package-web.nix and
nix/package-daemon.nix per the procedure documented in nix/README.md
§"First-build hash pinning".

* feat(analytics): unify PostHog identity with Langfuse installationId

PostHog's distinct_id is the installationId stamped by /api/analytics/
config; Langfuse already reads the same id off app-config.json to
populate trace.userId. With both sinks keying off the same anonymous
identity, dashboards can correlate user actions (PostHog events) with
LLM runs (Langfuse traces) without re-identifying.

Two gaps closed:

1. applyConsent(false) — clear posthog-js's persisted ph_*_posthog
   localStorage entry on opt-out via posthog.reset(). Without this, a
   user who opts out, then clicks Delete my data, then re-opts in
   would see PostHog stitch their new session to the deleted identity
   because bootstrap.distinctID only takes effect on first init.

2. applyIdentity(newInstallationId) — Delete my data rotates the
   installationId in app-config; App.tsx now watches config.installationId
   and calls posthog.reset() then identify(newId) so the next event
   batch is fully decoupled from the deleted one. Idempotent on
   same-id re-renders so benign config refreshes don't churn PostHog
   identities.

The fetch wrapper's x-od-analytics-anonymous-id header also flips to
the new id on rotation so daemon-side captures (run_created /
run_finished) land on the same person record from the very next API
call, not after a reload.

The end-to-end rotation flow is verified against a live PostHog
project; these unit tests pin the safety guards (no-client paths, null
inputs) since stubbing posthog-js's init-loaded callback chain is
brittle.

* fix(langfuse): require both metrics AND content consent for trace reports

Tightens the Langfuse gate so a user who shares anonymous metrics but
NOT conversation content stops emitting Langfuse traces entirely —
Langfuse is used for turn-quality evals which only make sense with
prompt/output bodies. PostHog (product analytics, content-free) stays
gated on `metrics` alone and is unaffected.

i18n: "Conversation content" → "Conversation and tool content" with
hints expanded to mention tool inputs/outputs so the consent surface
matches what the trace actually carries (en + zh-CN).

Bundled here per PR scope — change originated outside this PostHog
PR but lands cleanly on the same files; gating Langfuse strictly
on `content` makes the dual-sink consent model (PostHog = metrics,
Langfuse = metrics + content) symmetric across both i18n locales and
the daemon-side gate.

* feat(analytics): wire byok_provider_option + fix PR review P1s

Adds the BYOK protocol-chip click event (5-value provider_id mirroring
the apiProtocol Settings UI) and resolves four P1 review threads on
PR #1428.

byok_provider_option:
- New SettingsClickByokProviderOptionProps in contracts (provider_id =
  anthropic|openai|azure|google|ollama; maps to CSV's 5 values per
  tracking-doc-issues.md §2.5).
- trackSettingsClickByokProviderOption helper in apps/web/src/analytics.
- SettingsDialog hooks it on the protocol-chip onClick alongside the
  existing setApiProtocol call; is_selected reflects whether the chip
  was already active.

Review fixes:

1. client.ts (Siri-Ray): clear `initPromise` when the resolution is
   null so a Privacy → metrics opt-in after a previous decline triggers
   a fresh /api/analytics/config fetch. Without this, the disabled
   response was cached forever — first-session opt-in needed a reload
   to start sending PostHog events.

2. provider.tsx (Siri-Ray): replace `url.includes('/api/')` with a
   strict same-origin + /api/ pathname check (shared
   `isSameOriginApiCall` helper). Outbound third-party URLs containing
   `/api/` (e.g. provider.example.com/api/x) no longer receive our
   x-od-analytics-* headers.

3. provider.tsx (codex-connector, lefarcen): gate header injection on
   `resolvedAnonId` being non-null. When Privacy → metrics is off,
   /api/analytics/config returns enabled=false → resolvedAnonId stays
   null → wrapper never installs → daemon can't read consent-bearing
   headers → no daemon-side PostHog event. setConsent now also clears
   resolvedAnonId on opt-out and re-fetches on opt-in.

4. daemon/analytics.ts (defense in depth): createAnalyticsService now
   takes dataDir and capture() re-reads app-config to check
   telemetry.metrics inside the fire-and-forget wrapper. Even if a
   stale header somehow reaches the daemon after opt-out, the capture
   is dropped before posthog-node.capture is called.

* fix(web): place "Share usage data" on the right in privacy consent banner

Swap button order in PrivacyConsentModal and the in-settings ConsentCard
so the affirmative "Share usage data" lands on the right and "Not now"
on the left. Matches the OK-on-the-right pattern users expect for
primary actions.

Both buttons keep equal visual prominence (same .privacy-consent-action
styling) so the swap doesn't change the EDPB equal-prominence stance
called out in the original Langfuse telemetry spec.

* feat(analytics): populate run_finished token totals from claude-stream usage

Daemon's claude-stream parser already emits agent usage events with
input_tokens / output_tokens totals; the run service buffers them in
run.events and Langfuse reads them out the same way. The run_finished
PostHog event was leaving these fields empty.

Scan run.events for the most recent agent usage frame on terminal
transition and emit input_tokens / output_tokens / total_tokens when
present. token_count_source flips to 'provider_usage' only when at
least one count landed; runs without provider-side usage data keep
'unknown'.

Provider does not break the input down into the 7 sub-fields the
tracking doc lists (memory / context / attachment / system_prompt /
…); those stay omitted until a parser change exposes them.

* feat(analytics): estimate user_query_tokens from prompt length

The user_query_tokens field for run_created / run_finished was hardcoded
to 0. We can't tokenize without bundling a model-specific tokenizer, but
the character/4 heuristic is the industry-standard estimate when one
isn't available and is enough for funnel analysis (prompt-length cohorts,
short-vs-long-query conversion rates).

Extracted from req.body via the same telemetryPromptFromRunRequest
pattern the daemon already uses for langfuse-bridge (currentPrompt then
message fallback). Only the integer count goes to PostHog — the prompt
text itself never leaves the daemon.

token_count_source flips appropriately:
- run_created with a prompt: 'estimated' (was 'unknown')
- run_created with no prompt: 'unknown'
- run_finished with provider usage: 'provider_usage' (overrides
  baseProps' 'estimated' value)
- run_finished without provider usage: inherits 'estimated' or 'unknown'
  from baseProps so input/output absent doesn't mask the estimate.
2026-05-12 22:32:42 +08:00

1515 lines
82 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { Dict } from '../types';
export const zhCN: Dict = {
'common.cancel': '取消',
'common.save': '保存',
'common.close': '关闭',
'common.delete': '删除',
'common.rename': '重命名',
'common.preview': '预览',
'common.share': '分享',
'common.search': '搜索',
'common.searchEllipsis': '搜索…',
'common.loading': '加载中…',
'common.all': '全部',
'common.none': '无',
'common.default': '默认',
'common.installed': '已安装',
'common.notInstalled': '未安装',
'common.active': '使用中',
'common.offline': '未运行',
'common.selected': '已选',
'common.create': '创建',
'common.openPreview': '打开预览',
'common.exitFullscreen': '退出全屏',
'common.fullscreen': '全屏',
'common.openInNewTab': '在新标签页中打开',
'common.exportPdf': '导出为 PDF',
'common.exportZip': '下载为 .zip',
'common.exportHtml': '导出为独立 HTML',
'common.justNow': '刚刚',
'common.minutesAgo': '{n} 分钟前',
'common.hoursAgo': '{n} 小时前',
'common.daysAgo': '{n} 天前',
'common.now': '刚刚',
'common.minutesShort': '{n}分',
'common.hoursShort': '{n}时',
'common.daysShort': '{n}天',
'common.untitled': '未命名',
'app.brand': 'Open Design',
'app.brandPill': '研究预览版',
'app.brandSubtitle': '由 Nexu Labs 出品',
'app.welcomeLoading': '正在加载工作区…',
'settings.welcomeKicker': '欢迎',
'settings.welcomeTitle': '初始化 Open Design',
'settings.welcomeSubtitle':
'选择你希望使用的执行方式。后续可以随时从顶部「设置」按钮中修改。',
'settings.kicker': '设置',
'settings.title': '执行模式与模型',
'settings.subtitle': '在本机 CLI 与 BYOK 之间选择。API Key 只保存在当前浏览器中。',
'settings.modeAria': '执行模式',
'settings.protocolAria': 'API 协议',
'settings.modeDaemon': '本机 CLI',
'settings.modeDaemonHelp': '通过本机的代码代理 CLI 执行',
'settings.modeDaemonOffline': '后台守护进程未运行',
'settings.modeDaemonOfflineMeta': '守护进程未运行',
'settings.modeDaemonInstalledMeta': '已安装 {count} 个',
'settings.modeApi': 'API 提供方',
'settings.modeApiMeta': 'BYOK',
'settings.codeAgent': '代码代理',
'settings.codeAgentHint': '通过扫描 PATH 自动检测,选择你希望使用的 CLI。',
'settings.rescan': '↻ 重新扫描',
'settings.rescanTitle': '重新扫描 PATH',
'settings.rescanRunning': '扫描中...',
'settings.rescanSuccess': '扫描完成,{count} 个可用。',
'settings.rescanFailed': '扫描失败,请检查后台守护进程后重试。',
'settings.test': '测试',
'settings.testTitle': '发送极小的测试提示词以验证连接',
'settings.testRunning': '正在测试连接…',
'settings.testCancel': '取消',
'settings.testSuccessApi': '已连接。{ms} 毫秒响应 — \'{sample}\'',
'settings.testSuccessCli': '{agentName} 在 {ms} 毫秒内响应 — \'{sample}\'',
'settings.testAuthFailed': '鉴权失败,请检查 API 密钥。',
'settings.testForbidden': '访问被拒绝。请检查账号、地区或组织。',
'settings.testNotFoundModel': '未在此端点找到模型 \'{model}\'。',
'settings.testInvalidModelId': '模型 ID \'{model}\' 格式无效。自定义 ID 必须以字母或数字开头,且不能包含空格。',
'settings.testInvalidBaseUrl': 'Base URL 无效或不可达。',
'settings.testRateLimited': '提供商对测试进行了限流,配置看起来有效。',
'settings.testUpstream': '提供商返回 {status},请稍后再试。',
'settings.testTimeout': '测试在 {ms} 毫秒后超时。',
'settings.testAgentMissing': '{agentName} 未安装,或不在 PATH 中。',
'settings.testAgentSpawn': '无法启动 {agentName}{detail}。',
'settings.testUnknown': '测试失败:{detail}',
'settings.agentInstall.install': '安装',
'settings.agentInstall.docs': '文档',
'settings.agentInstall.pathHint':
'如果你通过 npm 或 Homebrew 安装了 CLI但仍显示为未安装请确认该工具的 bin 目录已加入 Open Design daemon 继承的 PATH在 macOS 上Terminal 与 GUI 应用的 PATH 可能不同)。请参阅 QUICKSTART.md“Local agent CLI and PATH” 章节)。',
'settings.agentInstall.stepOpenLinks': '在目标代理卡片上打开“安装”或“文档”链接。',
'settings.agentInstall.stepAuth':
'返回 Open Design 之前,请先在对应 CLI 中完成认证(登录或添加 API 凭据)。',
'settings.agentInstall.stepRescan': '在此区域点击“重新扫描”。',
'settings.agentInstall.stepSelect': '当代理显示为已安装后,选择该代理卡片。',
'settings.noAgentsDetected':
'尚未检测到任何代理。请安装 Claude Code、Codex、Gemini CLI、OpenCode、Cursor Agent、Qwen 或 GitHub Copilot CLI 中的一个,然后点击「重新扫描」。',
'settings.apiSection': 'Anthropic API',
'settings.quickFillProvider': '快速填充提供方',
'settings.customProvider': '自定义提供方',
'settings.apiKey': 'API Key',
'settings.showKey': '显示 Key',
'settings.hideKey': '隐藏 Key',
'settings.show': '显示',
'settings.hide': '隐藏',
'settings.model': '模型',
'settings.fetchModels': '拉取模型',
'settings.fetchModelsTitle': '从当前提供方拉取可用模型',
'settings.fetchModelsRunning': '正在拉取模型…',
'settings.fetchModelsSuccess': '已拉取 {count} 个模型。',
'settings.fetchModelsEmpty': '未返回可兼容的文本模型。',
'settings.fetchModelsUnsupported': '此协议暂不支持自动发现模型。',
'settings.fetchModelsFailed': '无法拉取模型:{detail}',
'settings.suggestedModelsHint':
'这些是此协议的建议模型。你的提供方可能支持不同的模型。',
'settings.baseUrl': 'Base URL',
'settings.baseUrlInvalid': '请输入有效的公网 http:// 或 https:// URL。允许 localhost会阻止私有网络 IP。',
'settings.azureDeploymentModel': '部署名称',
'settings.azureDeploymentModelHint':
'对于 Azure OpenAI此字段会作为 /openai/deployments/<model> 中的部署名称使用。请填写你在 Azure 中创建的部署名称。',
'settings.azureModelFetchHint':
'对于 Azure OpenAI请填写你在 Azure 中创建的部署名称。当前 BYOK 端点无法自动发现 deployment。',
'settings.apiVersion': 'API 版本',
'settings.maxTokens': '最大 tokens可选',
'settings.maxTokensHint':
'响应长度上限。每个 model 有调优过的默认值(在 placeholder 里显示),留空即使用,输入数字则覆盖。',
'settings.apiHint': '请求会通过本机 daemon 代理发送到你设置的 Base URL。Key 只保存在当前浏览器中,并随提供方请求发送。',
'settings.skipForNow': '暂时跳过',
'settings.getStarted': '开始使用',
'settings.envConfigure': '配置执行模式',
'settings.localCli': '本机 CLI',
'settings.anthropicApi': 'Anthropic API',
'settings.noAgentSelected': '尚未选择代理',
'settings.language': '界面语言',
'settings.languageHint': '切换界面语言,设置仅保存在当前浏览器。',
'settings.appearance': '外观',
'settings.appearanceHint': '选择浅色、深色或跟随系统设置。',
'settings.themeSystem': '系统',
'settings.themeLight': '浅色',
'settings.themeDark': '深色',
'settings.modelPicker': '模型',
'settings.reasoningPicker': '推理强度',
'settings.modelPickerHint':
'当 CLI 提供 `models` 命令时会自动拉取。选择「默认」则沿用 CLI 自身的配置;选择「自定义」可手动输入任何 CLI 支持的模型 id。',
'settings.cliEnvTitle': 'CLI 配置位置',
'settings.cliEnvHint':
'为打包版应用运行和 agent 检测设置非敏感配置目录。',
'settings.cliEnvClaudeConfigDir': 'Claude Code 配置目录',
'settings.cliEnvClaudeBaseUrl': 'Claude proxy base URL',
'settings.cliEnvClaudeApiKey': 'Claude proxy API key',
'settings.cliEnvCodexHome': 'Codex home',
'settings.cliEnvCodexBin': 'Codex 可执行文件路径',
'settings.cliEnvCodexBaseUrl': 'Codex/OpenAI proxy base URL',
'settings.cliEnvCodexApiKey': 'Codex/OpenAI proxy API key',
'settings.modelCustom': '自定义(在下方填写)…',
'settings.modelCustomLabel': '自定义模型 id',
'settings.modelCustomPlaceholder': '例如 anthropic/claude-sonnet-4-6',
'settings.mediaProviders': '媒体生成提供商',
'settings.mediaProvidersHint': '图片、视频、音频生成的 API key。存于本机并同步到本地守护进程。',
'settings.mcpServerTitle': 'MCP 服务器',
'settings.mcpServerHint': '将 Open Design 作为 MCP 服务器暴露给你的编码代理。',
'settings.externalMcpTitle': '外部 MCP',
'settings.externalMcpHint': '接入外部服务的 MCP 工具Higgsfield、GitHub 等)。',
'settings.mediaProviderApiKey': 'API key',
'settings.mediaProviderBaseUrl': 'Base URL',
'settings.mediaProviderConfigured': '已配置',
'settings.mediaProviderUnset': '未配置',
'settings.mediaProviderClear': '清除',
'settings.mediaProviderClearConfirm': '清除已保存的 {name} 设置?您需要再次输入才能使用 {name}。',
'settings.mediaProviderPlaceholder': '粘贴 API key',
'settings.mediaProviderBaseUrlPlaceholder': '覆盖默认 Base URL',
'settings.mediaProviderReload': '从本地守护进程重新加载',
'settings.mediaProviderReloadError': '无法从本地守护进程重新加载媒体提供方设置。',
'settings.mediaProviderReloadSuccess': '已从本地守护进程重新加载媒体提供方设置。',
'settings.mediaProviderLoadError': '无法从本地守护进程加载媒体提供方设置。当前将使用浏览器中保存的设置。',
'settings.privacy': '隐私',
'settings.privacyHint': '与 Open Design 团队共享哪些数据',
'settings.privacyConsentKicker': '帮助我们改进 Open Design',
'settings.privacyConsentLead': 'Open Design 可以将使用数据共享给我们的团队以协助改进。包括:',
'settings.privacyConsentFooter': '你可以随时在 设置 → 隐私 中修改任意一项。我们绝不上传你生成的产物文件内容。',
'settings.privacyConsentShare': '帮助改进',
'settings.privacyConsentDecline': '暂不',
'settings.privacyMetrics': '匿名指标',
'settings.privacyMetricsHint': '运行次数、token 用量、错误率、时长。不包含 prompt,不包含项目数据。',
'settings.privacyContent': '对话和工具内容',
'settings.privacyContentHint': '你发送的 prompt、助手回复、工具输入与工具输出(发送前截断)。API key、token、JWT、邮箱、IP 与信用卡号在发送前会自动剥离。',
'settings.privacyArtifacts': '项目产物清单',
'settings.privacyArtifactsHint': '生成文件的名称、类型、大小。文件内容绝不发送。',
'settings.privacyInstallationId': '匿名 ID',
'settings.privacyOptedOut': '已退出',
'settings.privacyDataDeletion': '删除我的数据',
'settings.privacyDataDeletionHint': '轮换你的匿名 ID 并停止发送。已有数据按我们的留存策略自然过期。',
'settings.about': '关于',
'settings.aboutHint': '版本和运行时详情',
'settings.appVersion': '版本',
'settings.appChannel': '渠道',
'settings.appRuntime': '运行时',
'settings.appPlatform': '平台',
'settings.appArchitecture': '架构',
'settings.runtimePackaged': '已打包应用',
'settings.runtimeDevelopment': '开发环境',
'settings.versionUnavailable': '守护进程离线时无法获取版本详情。',
// MCP server settings
'settings.mcpTitle': 'MCP server',
'settings.mcpHint':
'让其他仓库中的编码助手Claude Code、Cursor、VS Code、Antigravity、Zed、Windsurf读取你的 Open Design 项目。无需先导出 zip即可将设计拉取到你的应用中。',
'settings.mcpDaemonError':
'无法连接到本地守护进程以解析安装路径({error})。请确保 Open Design 正在运行,然后重新打开此面板。',
'settings.mcpBuildDaemon': '请先构建守护进程。',
'settings.mcpNodeMissing': 'Node 二进制文件缺失。',
'settings.mcpBuildHint':
'apps/daemon/dist/cli.js 缺失。请运行 `pnpm --filter @open-design/daemon build` 并刷新。',
'settings.mcpMethodCli': 'CLI 命令',
'settings.mcpInstructionCli': '在你的终端中运行此命令。',
'settings.mcpMethodToml': 'TOML 配置',
'settings.mcpInstructionCodex':
'将以下配置追加到 {path}。Codex CLI 与 Codex IDE 扩展共享同一配置。',
'settings.mcpMethodOneClick': '一键安装',
'settings.mcpInstructionCursor':
'点击"在 Cursor 中安装"以通过确认对话框安装,或将此 JSON 合并到 {path}。',
'settings.mcpDeeplinkInstallCursor': '在 Cursor 中安装',
'settings.mcpMethodJson': 'JSON 配置',
'settings.mcpInstructionCopilot':
'打开命令面板({shortcut}),运行 "MCP: Open User Configuration",然后合并此 JSON。Copilot Chat 必须处于 Agent 模式,工具才会显示。',
'settings.mcpInstructionAntigravity':
'在 Antigravity 中Agent 面板 "..." 菜单 → MCP Servers → Manage MCP Servers → View raw config。合并此 JSON。',
'settings.mcpInstructionZed':
'打开 Zed Settings{shortcut}然后将此配置合并到顶层对象中。Zed 使用 "context_servers",而非 "mcpServers"。',
'settings.mcpInstructionWindsurf':
'打开 {path}(或在 Cascade 中使用 MCPs 图标 → Configure并合并',
'settings.mcpCopyAria': '复制 MCP 配置片段',
'settings.mcpResolvingFailed': '# 解析路径失败,请查看上方错误',
'settings.mcpLoadingPaths': '# 正在从本地守护进程加载安装路径…',
'settings.mcpCopied': '已复制',
'settings.mcpCopy': '复制',
'settings.mcpCursorApproval': 'Cursor 会在写入配置前弹出确认对话框。',
'settings.mcpRestartNote': '重启客户端以加载新 server。',
'settings.mcpRestartDetail':
'大多数编辑器仅在启动时加载 MCP server。在 Cursor / VS Code / Antigravity / Windsurf 中,你可以在命令面板中运行 `Developer: Reload Window`无需完全重启。Zed 和 Claude Code 需要退出并重新打开。',
'settings.mcpCapabilitiesTitle': '你的助手可以做什么',
'settings.mcpCapabilityRead':
'读取或搜索项目中的任意文件HTML、JSX、CSS、JSON、SVG、Markdown。',
'settings.mcpCapabilityPull':
'一次调用拉取设计包:入口文件及其引用的所有 CSS 变量、组件和字体。',
'settings.mcpCapabilityDefault':
'默认使用你在 Open Design 中打开的项目和文件,因此你可以直接说"在我的应用中构建这个",无需重复说明是哪个设计。',
'settings.mcpRunningNote':
'Open Design 必须处于运行状态MCP 工具调用才能成功。如果你在打开 Open Design 之前启动了编码助手,请重启助手以便它能连接到正在运行的守护进程。',
'entry.tabDesigns': '我的设计',
'entry.tabTemplates': '模板',
'entry.tabDesignSystems': '设计体系',
'entry.tabConnectors': '连接器',
'entry.openSettingsTitle': '设置',
'entry.openSettingsAria': '打开设置',
'entry.resizeAria': '调整侧边栏宽度',
'entry.loadingWorkspace': '正在加载工作区…',
'entry.tabImageTemplates': '图片模板',
'entry.tabVideoTemplates': '视频模板',
'promptTemplates.searchPlaceholder': '搜索模板…',
'promptTemplates.countLabel': '{n} 个结果',
'promptTemplates.emptyImage': '还没有安装图片 Prompt 模板。',
'promptTemplates.emptyVideo': '还没有安装视频 Prompt 模板。',
'promptTemplates.emptyNoMatch': '没有匹配的模板。',
'promptTemplates.attributionFooter': '改编自公开 Prompt 库,每张卡片都链接到原作者。',
'promptTemplates.openPreviewTitle': '打开 Prompt 与预览',
'promptTemplates.sourcePrefix': '来源:',
'promptTemplates.fetchError': '无法加载此模板正文。',
'promptTemplates.promptLabel': 'Prompt 正文',
'promptTemplates.copyPrompt': '复制 Prompt',
'promptTemplates.copyDone': '已复制!',
'promptTemplates.modelHint': '建议模型:{model}',
'promptTemplates.openSource': '查看原始来源',
'promptTemplates.openFullscreen': '打开全屏预览',
'promptTemplates.closeFullscreen': '关闭全屏预览',
'promptTemplates.allSources': '所有来源',
'promptTemplates.sourceFilterAria': '按来源筛选',
'promptTemplates.retry': '重试',
'connectors.title': '连接器',
'connectors.subtitle': '可为实时制品提供数据的本地和未来数据源。',
'connectors.account': '账号',
'connectors.noAccount': '未连接',
'connectors.tools': '工具',
'connectors.connect': '连接',
'connectors.disconnect': '断开连接',
'connectors.authorizationPending': '等待授权中...',
'connectors.authorizationPendingHint': '请在已打开的窗口中完成授权。',
'connectors.cancelAuthorization': '取消',
'connectors.configure': '配置',
'connectors.unavailable': '不可用',
'connectors.phaseStubTitle': '连接器 API 将在 Phase 3 提供;这里是预览入口。',
'connectors.statusAvailable': '可用',
'connectors.statusConnected': '已连接',
'connectors.statusError': '错误',
'connectors.statusDisabled': '已停用',
'connectors.gateTitle': '添加 Composio API 密钥以继续',
'connectors.gateBody': '在上方粘贴密钥并点击“保存密钥”,即可加载可用集成。',
'connectors.aboutLabel': '简介',
'connectors.detailsLabel': '详情',
'connectors.statusLabel': '状态',
'connectors.category.aiAgents': 'AI 代理',
'connectors.category.aiInfrastructure': 'AI 基础设施',
'connectors.category.accounting': '会计',
'connectors.category.admin': '管理',
'connectors.category.advertising': '广告',
'connectors.category.analytics': '分析',
'connectors.category.automation': '自动化',
'connectors.category.cms': 'CMS',
'connectors.category.crm': 'CRM',
'connectors.category.calendar': '日历',
'connectors.category.commerce': '电商',
'connectors.category.communication': '沟通',
'connectors.category.contacts': '联系人',
'connectors.category.dataPlatform': '数据平台',
'connectors.category.database': '数据库',
'connectors.category.design': '设计',
'connectors.category.developer': '开发者工具',
'connectors.category.documentation': '文档',
'connectors.category.erp': 'ERP',
'connectors.category.education': '教育',
'connectors.category.email': '邮件',
'connectors.category.events': '活动',
'connectors.category.fieldService': '现场服务',
'connectors.category.finance': '财务',
'connectors.category.fitness': '健身',
'connectors.category.forms': '表单',
'connectors.category.gaming': '游戏',
'connectors.category.hr': '人力资源',
'connectors.category.hospitality': '酒店与款待',
'connectors.category.itsm': 'ITSM',
'connectors.category.integration': '集成',
'connectors.category.localization': '本地化',
'connectors.category.logistics': '物流',
'connectors.category.maps': '地图',
'connectors.category.marketing': '营销',
'connectors.category.media': '媒体',
'connectors.category.meetings': '会议',
'connectors.category.nonprofit': '非营利',
'connectors.category.observability': '可观测性',
'connectors.category.payments': '支付',
'connectors.category.personal': '个人',
'connectors.category.presentations': '演示文稿',
'connectors.category.procurement': '采购',
'connectors.category.product': '产品',
'connectors.category.productivity': '生产力',
'connectors.category.projectManagement': '项目管理',
'connectors.category.recruiting': '招聘',
'connectors.category.research': '研究',
'connectors.category.salesIntelligence': '销售情报',
'connectors.category.scheduling': '日程安排',
'connectors.category.search': '搜索',
'connectors.category.security': '安全',
'connectors.category.signing': '签署',
'connectors.category.social': '社交',
'connectors.category.spreadsheets': '电子表格',
'connectors.category.storage': '存储',
'connectors.category.support': '支持',
'connectors.category.surveys': '问卷',
'connectors.category.tasks': '任务',
'connectors.category.timeTracking': '时间追踪',
'connectors.category.video': '视频',
'connectors.category.whiteboard': '白板',
'connectors.categoryLabel': '类别',
'connectors.providerLabel': '提供方',
'connectors.toolsSection': '工具',
'connectors.toolsLoading': '正在加载工具…',
'connectors.noToolsAvailable': '暂无可用工具,连接后即可发现此集成提供的能力。',
'connectors.toolDetailsUnavailable': 'Tool details are unavailable, but this connector reports {n} tools.',
'connectors.loadMoreTools': 'Load more tools',
'connectors.openDetailsAria': '查看 {name} 详情',
'connectors.toolsBadgeNone': '暂无工具',
'connectors.toolsBadgeOne': '{n} 个工具',
'connectors.toolsBadgeMany': '{n} 个工具',
'connectors.searchPlaceholder': '搜索连接器…',
'connectors.searchAriaLabel': '按名称、提供方或工具搜索连接器',
'connectors.searchClear': '清除搜索',
'connectors.emptyNoMatchTitle': '没有匹配“{query}”的连接器',
'connectors.emptyNoMatchBody': '换个关键词试试,或清除搜索以浏览完整目录。',
'connectors.emptyNoMatchAction': '清除搜索',
'newproj.tabPrototype': '原型',
'newproj.tabLiveArtifact': '实时制品',
'newproj.tabDeck': '幻灯片',
'newproj.tabTemplate': '从模板',
'newproj.tabMedia': '媒体',
'newproj.tabOther': '其它',
'newproj.titlePrototype': '新建原型',
'newproj.titleLiveArtifact': '新建实时制品',
'newproj.titleDeck': '新建幻灯片',
'newproj.titleTemplate': '从模板开始',
'newproj.titleImage': '新建图片',
'newproj.titleVideo': '新建视频',
'newproj.titleAudio': '新建音频',
'newproj.titleMedia': '新建媒体',
'newproj.titleOther': '新建项目',
'newproj.namePlaceholder': '项目名称',
'newproj.fidelityLabel': '精度',
'newproj.fidelityWireframe': '线框图',
'newproj.fidelityHigh': '高保真',
'newproj.toggleSpeakerNotes': '使用演讲备注',
'newproj.toggleSpeakerNotesHint': '减少幻灯片上的文字,要点放到备注中。',
'newproj.toggleAnimations': '加入动效',
'newproj.toggleAnimationsHint': '在模板基础上叠加动效(入场、悬停、过渡)。',
'newproj.surfaceOptionsLabel': 'Companion surfaces',
'newproj.includeLandingPage': 'Include landing page',
'newproj.includeLandingPageHint':
'Add a responsive marketing page for ads, waitlists, launch campaigns, app downloads, or product explanation.',
'newproj.includeOsWidgets': 'Include OS widgets',
'newproj.includeOsWidgetsHint':
'Add platform-native home screen, lock screen, or quick-access widgets for mobile/tablet apps.',
'newproj.includeOsWidgetsDisabledHint':
'Available when iOS, Android, or tablet app is selected as a target platform.',
'newproj.templateLabel': '模板',
'newproj.noTemplatesTitle': '还没有模板',
'newproj.noTemplatesBody':
'打开任意项目,在文件查看器内的「分享」菜单将其保存为模板,模板将出现在这里。',
'newproj.savedTemplate': '已保存的模板',
'newproj.fileSingular': '个文件',
'newproj.filePlural': '个文件',
'newproj.create': '创建',
'newproj.createLiveArtifact': '创建实时制品',
'newproj.createFromTemplate': '基于模板创建',
'newproj.createDisabledTitle': '请先在任意项目内通过「分享」菜单将其保存为模板。',
'newproj.importClaudeZip': '导入 Claude Design ZIP',
'newproj.importClaudeZipTitle': '导入 Claude Design 导出的 .zip 文件',
'newproj.importingClaudeZip': '正在导入…',
'newproj.privacyFooter': '默认情况下只有你能看到自己的项目。',
'newproj.designSystem': '设计体系',
'newproj.dsNoneFreeform': '不指定 — 自由发挥',
'newproj.dsNoneSubtitleEmpty': '不使用体系 token由你决定整体配色',
'newproj.dsNoneSubtitleSelected': '跳过体系 token由代理自行选择配色。',
'newproj.dsCategoryFallback': '设计体系',
'newproj.dsSearch': '搜索设计体系…',
'newproj.dsModeAria': '选择模式',
'newproj.dsModeSingle': '单选',
'newproj.dsModeMulti': '多选',
'newproj.dsNoneTitle': '不指定 — 自由发挥',
'newproj.dsNoneSub': '跳过体系 token由代理自行选择配色。',
'newproj.dsEmpty': '没有匹配「{query}」的设计体系。',
'newproj.dsFootSingular': '只作为灵感参考。',
'newproj.dsFootPlural': '只作为灵感参考。',
'newproj.dsFootClear': '清除',
'newproj.dsBadgeDefault': '默认',
'newproj.dsPrimaryFallback': '主体系',
'newproj.surfaceImage': '图片',
'newproj.surfaceVideo': '视频',
'newproj.surfaceAudio': '音频',
'newproj.modelLabel': '模型',
'newproj.modelSearch': '搜索模型…',
'newproj.modelEmpty': '没有匹配的模型。',
'newproj.modelRecommended': '推荐',
'newproj.modelMissingTitle': '选择模型',
'newproj.modelMissingSub': '为此场景选一个模型。',
'newproj.aspectLabel': '比例',
'newproj.videoLengthLabel': '时长',
'newproj.videoLengthSeconds': '{n} 秒',
'newproj.audioKindLabel': '音频类型',
'newproj.audioKindMusic': '音乐',
'newproj.audioKindSpeech': '配音 / TTS',
'newproj.audioKindSfx': '音效',
'newproj.audioDurationLabel': '时长',
'newproj.audioDurationSeconds': '{n} 秒',
'newproj.voiceLabel': '声音',
'newproj.voicePlaceholder': '提供商 voice id可选',
'newproj.connectorsLabel': '连接器',
'newproj.connectorsHint': '实时制品可以从这些数据源拉取信息。',
'newproj.connectorsEmptyTitle': '尚未配置连接器',
'newproj.connectorsEmptyBody': '连接一个数据源,让实时制品加载真实数据而非占位内容。',
'newproj.connectorsEmptyCta': '去配置连接器 →',
'newproj.connectorsLoading': '正在加载连接器…',
'newproj.connectorsCountOne': '已连接 {n} 个',
'newproj.connectorsCountMany': '已连接 {n} 个',
'newproj.connectorsManage': '管理',
'newproj.promptTemplateLabel': '参考模板',
'newproj.promptTemplateNoneTitle': '不指定 — 自由发挥',
'newproj.promptTemplateNoneSub': '跳过模板库,自己描述需求',
'newproj.promptTemplateRefSub': '参考模板',
'newproj.promptTemplateSearch': '搜索模板…',
'newproj.promptTemplateEmpty': '当前还没有此类型的模板。',
'newproj.promptTemplateBodyLabel': 'Prompt可继续优化',
'newproj.promptTemplateOptimizeHint':
'可以任意编辑 — 修改后的内容会作为 agent 生成时的参考。',
'newproj.promptTemplateBodyEmpty': '正文为空 — agent 不会拿到模板参考。',
'designs.subRecent': '最近',
'designs.subYours': '我的设计',
'designs.filterAria': '筛选项目',
'designs.searchPlaceholder': '搜索…',
'designs.emptyNoProjects': '还没有项目。请在左侧创建一个。',
'designs.emptyNoMatch': '没有匹配的项目。',
'designs.deleteTitle': '删除项目',
'designs.deleteConfirm': '确定删除「{name}」?',
'designs.cardFreeform': '自由设计',
'designs.badgeLive': 'Live',
'designs.liveArtifactBadgesAria': '实时产物标记',
'designs.liveCount': '{n} 个实时',
'designs.statusLive': '实时产物',
'designs.statusArchived': '已归档',
'designs.statusError': '错误',
'designs.statusRefreshing': '刷新中…',
'designs.statusRefreshFailed': '刷新失败',
'designs.statusRefreshed': '已刷新',
'designs.status.notStarted': '未开始',
'designs.status.queued': '等待中',
'designs.status.running': '运行中',
'designs.status.awaitingInput': '等待回复',
'designs.status.succeeded': '已完成',
'designs.status.failed': '失败',
'designs.status.canceled': '已取消',
'designs.viewToggleAria': '视图模式',
'designs.viewGrid': '网格视图',
'designs.viewKanban': '看板视图',
'designs.kanbanEmptyColumn': '暂无设计',
'designs.deleteAria': '删除项目 {name}',
'designs.menuMore': '更多操作',
'designs.menuRename': '重命名',
'designs.menuDelete': '删除',
'designs.renamePrompt': '为「{name}」输入新名称',
'designs.selectMode': '选择',
'designs.cancelSelect': '取消',
'designs.deleteSelected': '删除所选',
'designs.selectedCount': '已选择 {n} 项',
'designs.deleteSelectedConfirm': '确定删除选中的 {n} 个项目?',
'designs.tagPrototype': '原型',
'designs.tagLiveArtifact': 'Live Artifact',
'designs.tagSlide': 'Slide',
'designs.tagMedia': 'Media',
'designs.renameTitle': '重命名项目',
'designs.renameSave': '确定',
'designs.renameCancel': '取消',
'examples.typeLabel': '类型',
'examples.surfaceLabel': '类型',
'examples.surfaceWeb': '网页',
'examples.surfaceImage': '图片',
'examples.surfaceVideo': '视频',
'examples.surfaceAudio': '音频',
'examples.scenarioLabel': '场景',
'examples.modeAll': '全部',
'examples.modePrototypeDesktop': '原型 · 桌面端',
'examples.modePrototypeMobile': '原型 · 移动端',
'examples.modeDeck': '幻灯片',
'examples.modeDocument': '文档与模板',
'examples.modeOrbit': 'Orbit',
'examples.modeLive': '实时',
'examples.scenarioGeneral': '通用',
'examples.scenarioEngineering': '工程',
'examples.scenarioProduct': '产品',
'examples.scenarioDesign': '设计',
'examples.scenarioMarketing': '市场',
'examples.scenarioSales': '销售',
'examples.scenarioFinance': '财务',
'examples.scenarioHr': '人力资源',
'examples.scenarioOperations': '运营',
'examples.scenarioSupport': '支持',
'examples.scenarioLegal': '法务',
'examples.scenarioEducation': '教育',
'examples.scenarioPersonal': '个人',
'examples.emptyNoSkills': '没有可用的技能,守护进程是否在运行?',
'examples.searchPlaceholder': '搜索示例…',
'examples.searchAria': '按名称搜索示例',
'examples.emptyNoMatch': '没有匹配当前筛选的示例。',
'examples.openPreview': '⤢ 打开预览',
'examples.loadingPreview': '正在加载预览…',
'examples.hoverPreview': '将鼠标悬停以查看预览',
'examples.usePrompt': '使用此 Prompt',
'examples.previewModalTitle': '在弹窗中查看完整预览',
'examples.shareTitle': '分享此示例',
'examples.shareLoadFirst': '请先悬停以加载预览',
'examples.unavailablePlaceholder': '此技能未附带 {kind} 预览样例 — 打开查看详情',
'examples.shareUnavailable': '此技能未附带 {kind} 预览样例可分享',
'examples.shareMenu': '分享 ▾',
'examples.exportPdfAllSlides': '导出为 PDF全部幻灯片',
'examples.exportPptxLocked': '导出为 PPTX…请先打开模板',
'examples.tagSlideDeck': '幻灯片',
'examples.tagTemplate': '模板',
'examples.tagDesignSystem': '设计体系',
'examples.tagMobilePrototype': '移动端原型',
'examples.tagDesktopPrototype': '桌面端原型',
'examples.tagImage': '图片',
'examples.tagVideo': '视频',
'examples.tagAudio': '音频',
'examples.previewLabel': '预览',
'ds.surfaceLabel': '类型',
'ds.surfaceWeb': '网页',
'ds.surfaceImage': '图片',
'ds.surfaceVideo': '视频',
'ds.surfaceAudio': '音频',
'ds.searchPlaceholder': '搜索设计体系…',
'ds.emptyNoMatch': '没有匹配的设计体系。',
'ds.badgeDefault': '默认',
'ds.preview': '预览',
'ds.previewTitle': '预览设计体系',
'ds.categoryAll': '全部',
'ds.categoryUncategorized': '未分类',
'ds.showcase': '展示',
'ds.tokens': 'Token',
'ds.specToggle': 'DESIGN.md',
'ds.specLoading': '正在加载 DESIGN.md…',
'avatar.title': '账户与设置',
'avatar.localCli': '本机 CLI',
'avatar.anthropicApi': 'Anthropic API',
'avatar.useLocal': '使用本机 CLI',
'avatar.useApi': '使用 API · BYOK',
'avatar.codeAgent': '代码代理',
'avatar.rescan': '重新扫描 PATH',
'avatar.settings': '设置',
'avatar.backToProjects': '返回项目列表',
'avatar.metaActive': '使用中',
'avatar.metaOffline': '未运行',
'avatar.metaSelected': '已选',
'avatar.noAgentSelected': '尚未选择代理',
'avatar.modelSection': '模型',
'avatar.modelLabel': '模型',
'avatar.reasoningLabel': '推理',
'avatar.customSuffix': '(自定义)',
'project.backToProjects': '返回项目列表',
'project.metaFreeform': '自由设计',
'project.resizeChatPanel': '调整聊天面板大小',
'chat.tabChat': '对话',
'chat.tabComments': '评论',
'chat.commentsSoon': '评论 — 即将上线',
'chat.comments.attached': '已附加到对话',
'chat.comments.emptyAttached': '没有已附加的评论。',
'chat.comments.saved': '已保存的评论',
'chat.comments.emptySaved': '没有已保存的评论。',
'chat.comments.add': '添加',
'chat.comments.addAll': '全部添加',
'chat.comments.remove': '移除',
'chat.comments.placeholder': '评论此元素…',
'chat.comments.addSend': '添加并发送',
'chat.comments.updateSend': '更新并发送',
'chat.comments.removeAttachment': '移除评论附件',
'chat.comments.removeAttachmentAria': '移除 {name} 的评论附件',
'chat.conversationsTitle': '对话历史',
'chat.conversationsAria': '对话历史',
'chat.newConversation': '新建对话',
'chat.newConversationsTitle': '新建对话',
'chat.conversationsHeading': '对话',
'chat.new': '新建',
'chat.emptyConversations': '还没有对话。',
'chat.deleteConversation': '删除对话',
'chat.deleteConversationConfirm': '确定删除「{title}」?该操作会删除其消息。',
'chat.untitledConversation': '未命名对话',
'chat.startTitle': '开始一个对话',
'chat.startHint':
'可以拖拽或粘贴图片作为视觉参考,或键入 @ 引用本项目中的文件。也可以从下面的示例开始:',
'chat.fillInputTitle': '点击填充到输入框',
'chat.jumpToLatest': '回到最新',
'chat.scrollToLatest': '滚动到最新',
'chat.you': '你',
'chat.openFile': '打开 {name}',
'chat.composerPlaceholder': '描述你想要的设计 — 可粘贴/拖入图片,或用 @ 引用文件或技能…',
'chat.composerHint': '⌘/Ctrl + Enter 发送 · 可粘贴图片 · @ 引用文件或技能 · / 调出命令',
'chat.cliSettingsTitle': 'CLI 与模型设置',
'chat.cliSettingsAria': '打开 CLI 与模型设置',
'chat.attachTitle': '附加文件(也可以粘贴/拖入)',
'chat.attachAria': '附加文件',
'chat.importTitle': '导入素材(即将上线)',
'chat.importLabel': '导入',
'chat.importComingSoon': '即将上线',
'chat.importSoon': '即将',
'chat.importFig': '上传 .fig 文件',
'chat.importGitHub': '连接 GitHub',
'chat.importWeb': '抓取网页元素',
'chat.importFolder': '关联代码目录',
'chat.importSkills': '技能与设计体系',
'chat.importProject': '引用其它项目',
'chat.linkedFolderRemoveAria': '移除关联文件夹 {path}',
'chat.linkedFolderNotFound': '文件夹不存在',
'chat.linkedFolderAlready': '该文件夹已关联',
'chat.linkedFolderPickError': '无法打开文件夹选择器',
'chat.send': '发送',
'chat.stop': '停止',
'chat.removeAria': '移除 {name}',
'chat.example1Title': '编辑风路演 PPT',
'chat.example1Tag': '杂志',
'chat.example1Prompt':
'为一家正在融种子轮的设计工作室制作 10 张编辑风路演 PPT —— 瑞士网格布局,超大号衬线标题加粗体首字下沉,等宽字体的章节编号,留白充足,整页大图与文字密集页穿插出现。封面、愿景、市场、产品、增长、团队、融资诉求、联系方式。',
'chat.example2Title': 'SaaS 分析仪表盘',
'chat.example2Tag': '数据',
'chat.example2Prompt':
'为一款面向开发者的 SaaS 设计一份信息密度高的分析仪表盘 —— 顶部 KPI 条带含周环比变化、两张堆叠折线图MRR 与活跃工作区)、全球使用热力图、留存矩阵、客户排行榜以及实时事件流。深色主题,等宽数字,迷你图作为点缀。',
'chat.example3Title': '长滚动年度报告',
'chat.example3Tag': '编辑',
'chat.example3Prompt':
'为一家关注气候议题的非营利机构制作互动式年度报告 —— 长滚动编辑式布局,混合大段引言区块、数据可视化(堆叠柱状图、动态计数器、项目地点分布的等值线地图)、摄影分隔页、捐赠者墙,以及最终行动号召。现代衬线正文、无衬线图表标签、大地纸张配色。',
'preview.shareMenu': '分享 ▾',
'preview.openInNewTab': '在新标签页中打开',
'preview.exit': '⤓ 退出',
'preview.fullscreen': '⤢ 全屏',
'preview.closeTitle': '关闭Esc',
'preview.loading': '正在加载{label}…',
'preview.errorTitle': '无法加载此示例。',
'preview.errorBody': '示例 HTML 加载失败。请确认 Open Design 正在运行后重试。',
'preview.retry': '重试',
'preview.unavailableTitle': '此技能暂未附带预览样例。',
'preview.unavailableBody': '此技能用于生成 {kind} 产物 — 请在对话中运行此 Prompt 来生成。',
'preview.showSidebar': '展开{label}',
'preview.hideSidebar': '收起{label}',
'misc.savedTemplate': '已保存的模板',
'misc.primary': '主体系',
'misc.designSystem': '设计体系',
'workspace.designFiles': '设计文件',
'workspace.focusMode': '专注工作区',
'workspace.showChat': '显示聊天',
'workspace.closeTab': '关闭标签页',
'workspace.deleteFileConfirm': '从项目文件夹中删除「{name}」?',
'workspace.deleteSelectedFilesConfirm': '从项目文件夹中删除选中的 {n} 个文件?',
'workspace.deleteSelectedFilesPartial': '有 {n} 个文件删除失败。',
'workspace.openFromDesignFiles': '请从',
'workspace.designFilesLink': '设计文件',
'workspace.loadingSketch': '正在加载草图…',
'designFiles.title': '设计文件',
'designFiles.upload': '上传文件',
'designFiles.pasteText': '粘贴为文本文件',
'designFiles.newSketch': '新建草图',
'designFiles.empty': '生成的设计会出现在这里',
'designFiles.refresh': '刷新',
'designFiles.delete': '删除',
'designFiles.searchPlaceholder': '搜索文件…',
'designFiles.up': '上一级',
'designFiles.back': '返回',
'designFiles.crumbs': '项目',
'designFiles.rowMenu': '行菜单',
'designFiles.openInTab': '在标签页中打开',
'designFiles.download': '下载',
'designFiles.downloadSelected': '下载选中的 {n} 个文件为 ZIP',
'designFiles.deleteSelected': '删除 {n} 个',
'designFiles.clearSelection': '取消选择',
'designFiles.selectPage': '全选此页',
'designFiles.selectAll': '全选',
'designFiles.dropTitle': '⤓ 把文件拖到这里',
'designFiles.dropDesc': '图片、文档、参考资料或文件夹 — 智能体都会用作上下文。',
'designFiles.upload.title': '上传文件',
'designFiles.paste.title': '将文本粘贴为文件',
'designFiles.upload.label': '上传',
'designFiles.paste.label': '粘贴',
'designFiles.previewOpen': '打开',
'designFiles.previewClose': '关闭预览',
'designFiles.modified': '修改于 {time} · {size}',
'designFiles.weeksAgo': '{n} 周前',
'designFiles.groupBy': '分组方式',
'designFiles.groupByKind': '类型',
'designFiles.groupByModified': '修改时间',
'designFiles.expandGroup': '展开',
'designFiles.collapseGroup': '折叠',
'designFiles.sectionPages': '页面',
'designFiles.sectionScripts': '脚本',
'designFiles.sectionImages': '图片',
'designFiles.sectionSketches': '草图',
'designFiles.sectionLiveArtifacts': '实时制品',
'designFiles.sectionOther': '其它',
'designFiles.modifiedToday': '今天',
'designFiles.modifiedYesterday': '昨天',
'designFiles.modifiedPrevious7Days': '最近 7 天',
'designFiles.modifiedPrevious30Days': '最近 30 天',
'designFiles.modifiedOlder': '更早',
'designFiles.showMore': '再显示 {n} 个',
'designFiles.kindHtml': 'HTML 页面',
'designFiles.kindImage': '图片',
'designFiles.kindSketch': '草图',
'designFiles.kindText': '文本',
'designFiles.kindCode': '脚本',
'designFiles.kindPdf': 'PDF',
'designFiles.kindDocument': '文档',
'designFiles.kindPresentation': '演示文稿',
'designFiles.kindSpreadsheet': '电子表格',
'designFiles.kindLiveArtifact': '实时制品',
'designFiles.kindBinary': '二进制',
'designFiles.colName': '名称',
'designFiles.colKind': '类型',
'designFiles.colModified': '修改时间',
'designFiles.perPage': '显示',
'designFiles.all': '全部',
'designFiles.prev': '上一页',
'designFiles.next': '下一页',
'designFiles.jumpToPage': '跳转到页面',
'designFiles.pageInfo': '{start}{end} / {total}',
'quickSwitcher.placeholder': '打开文件…',
'quickSwitcher.empty': '此项目中没有文件',
'quickSwitcher.noMatches': '无匹配项',
'quickSwitcher.navigate': '导航',
'quickSwitcher.open': '打开',
'quickSwitcher.close': '关闭',
'pasteDialog.title': '粘贴文本',
'pasteDialog.hint': '将保存到项目文件夹中,名称随你定。',
'pasteDialog.fileNameLabel': '文件名',
'pasteDialog.namePlaceholder': 'notes.txt',
'pasteDialog.contentLabel': '内容',
'pasteDialog.contentPlaceholder': '在此粘贴任何内容…',
'pasteDialog.save': '保存',
'pasteDialog.cancel': '取消',
'sketch.save': '保存草图',
'sketch.cancel': '取消',
'sketch.saving': '保存中…',
'sketch.tooltipDirty': '尚未保存',
'sketch.tooltipClean': '已保存',
'fileViewer.empty': '请选择一个文件查看。',
'fileViewer.loading': '加载中…',
'fileViewer.exportPptx': '导出为 PPTX',
'fileViewer.openInNewTab': '在新标签页中打开',
'fileViewer.copyPath': '复制路径',
'fileViewer.copied': '已复制!',
'fileViewer.share': '分享',
'fileViewer.binaryMeta': '二进制 · {size}',
'fileViewer.binaryNote': '二进制文件({size} 字节)。请下载或在本地打开查看。',
'fileViewer.pdfMeta': 'PDF · {size}',
'fileViewer.documentMeta': '文档',
'fileViewer.presentationMeta': '演示文稿',
'fileViewer.spreadsheetMeta': '电子表格',
'fileViewer.previewUnavailable': '无法生成预览,请下载或打开文件查看。',
'fileViewer.download': '下载',
'fileViewer.open': '打开',
'fileViewer.imageMeta': '图片 · {size}',
'fileViewer.reactMeta': 'React 组件 · {size}',
'fileViewer.sketchMeta': '草图 · {size}',
'fileViewer.markdownStreamingMeta': '正在流式预览…',
'fileViewer.markdownErrorMeta': '预览可能不完整(生成错误)。',
'fileViewer.markdownStreamingStatus': '正在流式生成…显示部分 Markdown。',
'fileViewer.markdownErrorStatus': '生成错误。正在显示最后可用内容。',
'fileViewer.videoMeta': '视频 · {size}',
'fileViewer.audioMeta': '音频 · {size}',
'fileViewer.reload': '重新加载',
'fileViewer.reloadDisk': '从磁盘重新加载',
'fileViewer.copy': '复制',
'fileViewer.copyTitle': '复制文件内容',
'fileViewer.saveDisabled': '保存(只读预览)',
'fileViewer.save': '保存',
'fileViewer.preview': '预览',
'fileViewer.source': '源代码',
'fileViewer.tweaks': '调整',
'fileViewer.comment': '评论',
'fileViewer.edit': '编辑',
'fileViewer.draw': '绘制',
'manualEdit.layers': "Layers",
'manualEdit.editableCount': "{count} editable",
'manualEdit.title': "Manual editor",
'manualEdit.selectLayer': "Select a layer",
'manualEdit.empty': "Click an element in the preview or choose a layer.",
'manualEdit.noClass': "no class",
'manualEdit.tabsAria': "Manual edit tabs",
'manualEdit.tabContent': "Content",
'manualEdit.tabStyle': "Style",
'manualEdit.tabAttributes': "Attributes",
'manualEdit.tabHtml': "Html",
'manualEdit.tabSource': "Source",
'manualEdit.attributesJson': "Attributes JSON",
'manualEdit.selectedHtml': "Selected element HTML",
'manualEdit.fullSource': "Full artifact source",
'manualEdit.applyContent': "Apply Content",
'manualEdit.applyStyle': "Apply Style",
'manualEdit.applyAttributes': "Apply Attributes",
'manualEdit.applyHtml': "Apply HTML",
'manualEdit.applySource': "Apply Source",
'manualEdit.invalidAttributes': "Invalid attributes JSON.",
'manualEdit.changes': "Changes",
'manualEdit.undo': "Undo",
'manualEdit.redo': "Redo",
'manualEdit.noChanges': "No manual edits yet.",
'manualEdit.imageUrl': "Image URL",
'manualEdit.altText': "Alt text",
'manualEdit.label': "Label",
'manualEdit.text': "Text",
'manualEdit.href': "Href",
'manualEdit.textColor': "Text color",
'manualEdit.background': "Background",
'manualEdit.fontSize': "Font size",
'manualEdit.weight': "Weight",
'manualEdit.align': "Align",
'manualEdit.padding': "Padding",
'manualEdit.margin': "Margin",
'manualEdit.radius': "Radius",
'manualEdit.border': "Border",
'manualEdit.width': "Width",
'manualEdit.minHeight': "Min height",
'fileViewer.zoomOut': '缩小',
'fileViewer.zoomIn': '放大',
'fileViewer.resetZoom': '重置缩放',
'fileViewer.viewportAria': 'Preview viewport',
'fileViewer.viewportDesktop': 'Desktop',
'fileViewer.viewportDesktopTitle': 'Full-width desktop preview',
'fileViewer.viewportTablet': 'Tablet',
'fileViewer.viewportTabletTitle': 'Tablet preview at 820 × 1180 (modern portrait baseline)',
'fileViewer.viewportMobile': 'Mobile',
'fileViewer.viewportMobileTitle': 'Mobile preview at 390 × 844',
'fileViewer.reloadAria': '重新加载',
'fileViewer.previousSlide': '上一张',
'fileViewer.nextSlide': '下一张',
'fileViewer.slideNavAria': '幻灯片导航',
'fileViewer.present': '演示',
'fileViewer.presentInTab': '在当前标签页',
'fileViewer.presentFullscreen': '全屏',
'fileViewer.presentNewTab': '新标签页',
'fileViewer.exitPresentation': '退出演示',
'fileViewer.shareLabel': '分享',
'fileViewer.exportPdf': '导出为 PDF',
'fileViewer.exportPdfAllSlides': '导出为 PDF全部幻灯片',
'fileViewer.exportPptxBusy': '请等待当前任务完成。',
'fileViewer.exportPptxHint': '请求代理将此设计转换为 PPTX。',
'fileViewer.exportPptxNa': '此处暂不支持导出 PPTX。',
'fileViewer.exportZip': '下载为 .zip',
'fileViewer.exportHtml': '导出为独立 HTML',
'fileViewer.exportMd': '导出为 Markdown',
'fileViewer.exportJsx': '导出为 JSX',
'fileViewer.exportReactHtml': '导出预览 HTML',
'fileViewer.saveAsTemplate': '保存为模板…',
'fileViewer.savingTemplate': '正在保存模板…',
'fileViewer.savedTemplate': '已保存为「{name}」',
'fileViewer.savedTemplateFail': '保存模板失败,请重试。',
'fileViewer.templateNamePrompt': '模板名称',
'fileViewer.templateNameDefault': '未命名模板',
'fileViewer.templateDescPrompt': '简短描述(可选 — 这个模板用于什么场景?)',
'liveArtifact.refresh.button': '刷新',
'liveArtifact.refresh.buttonTitle': '刷新此 live artifact',
'liveArtifact.refresh.loadingTitle': '正在加载 live artifact…',
'liveArtifact.refresh.noSourceTitle': '暂无可刷新来源。',
'liveArtifact.refresh.running': '刷新中…',
'liveArtifact.refresh.runningMessage': '正在刷新数据和预览,可能需要一点时间。',
'liveArtifact.refresh.runningAction': '刷新成功前会继续显示上一次预览。',
'liveArtifact.refresh.successOne': '刷新完成,数据已更新。',
'liveArtifact.refresh.successMany': '刷新完成,数据已更新。',
'liveArtifact.refresh.successAction': '预览已使用最新提交的数据重新加载。',
'liveArtifact.refresh.previousFailure': '上次刷新失败:{message}',
'liveArtifact.refresh.failureAction': '请检查「刷新历史」,修复来源或权限问题后重试。',
'liveArtifact.refresh.networkFailure': '刷新请求失败。请检查网络连接后重试。',
'liveArtifact.refresh.genericFailure': '刷新失败。',
'liveArtifact.refresh.statusNever': '不可刷新',
'liveArtifact.refresh.statusReady': '可刷新',
'liveArtifact.refresh.statusSucceeded': '已是最新',
'liveArtifact.refresh.statusFailed': '刷新失败',
'liveArtifact.refresh.statusRunning': '正在刷新',
'liveArtifact.refresh.statusRunningDescription': '刷新任务正在进行中。',
'liveArtifact.refresh.statusSucceededDescription': '上次刷新已成功完成。',
'liveArtifact.refresh.statusFailedDescription': '上次刷新未能成功完成。',
'liveArtifact.refresh.statusReadyDescription':
'已配置可刷新的数据源,但暂无正在进行的任务。',
'liveArtifact.refresh.statusNeverDescription': '该实时产物尚未配置刷新数据源。',
'liveArtifact.refresh.eventStarted': '已开始',
'liveArtifact.refresh.eventSucceeded': '已成功',
'liveArtifact.refresh.eventFailed': '失败',
'liveArtifact.refresh.eventStartedDetail': '刷新已开始…',
'liveArtifact.refresh.sourcesUpdatedOne': '已更新 {n} 个数据源',
'liveArtifact.refresh.sourcesUpdatedMany': '已更新 {n} 个数据源',
'liveArtifact.refresh.timelineEmpty':
'本次会话还没有刷新记录。点击「刷新」即可记录时间线,或等待自动任务完成。',
'liveArtifact.refresh.heroLastRefreshedLabel': '上次刷新',
'liveArtifact.refresh.heroLastRefreshedNever': '从未',
'liveArtifact.refresh.justNow': '刚刚',
'liveArtifact.refresh.factCreated': '创建时间',
'liveArtifact.refresh.factLastUpdated': '最后更新',
'liveArtifact.refresh.factUnknown': '未知',
'liveArtifact.refresh.persistedTitle': '持久化刷新记录',
'liveArtifact.refresh.persistedHint': '来自 refreshes.jsonl 的条目',
'liveArtifact.refresh.persistedEmpty': '尚无持久化的刷新记录。',
'liveArtifact.refresh.persistedStatusSucceeded': '成功',
'liveArtifact.refresh.persistedStatusRunning': '进行中',
'liveArtifact.refresh.persistedStatusFailed': '失败',
'liveArtifact.refresh.persistedStatusCancelled': '已取消',
'liveArtifact.refresh.persistedStatusSkipped': '已跳过',
'liveArtifact.refresh.sessionTitle': '会话活动',
'liveArtifact.refresh.sessionHint': '本标签页打开期间观察到的事件',
'liveArtifact.refresh.docSourceTitle': '文档来源',
'liveArtifact.refresh.docSourceHint': '已配置的数据源',
'liveArtifact.refresh.docSourceType': '类型',
'liveArtifact.refresh.docSourceTool': '工具',
'liveArtifact.refresh.docSourceConnector': '连接器',
'liveArtifact.refresh.debugSummary': '高级调试元数据',
'liveArtifact.refresh.debugNote': '可能包含连接器 ID、文件名、来源元数据以及内部 artifact 路径。',
'fileViewer.deployToVercel': '部署到 Vercel',
'fileViewer.redeployToVercel': '重新部署',
'fileViewer.deployingToVercel': '正在部署到 Vercel…',
'fileViewer.deployProviderLabel': '部署平台',
'fileViewer.vercelProvider': 'Vercel',
'fileViewer.cloudflarePagesProvider': 'Cloudflare Pages',
'fileViewer.deployToProvider': '部署到 {provider}',
'fileViewer.redeployToProvider': '重新部署到 {provider}',
'fileViewer.deployingToProvider': '正在部署到 {provider}…',
'fileViewer.preparingPublicLink': '正在准备公开链接…',
'fileViewer.copyDeployLink': '复制链接',
'fileViewer.deployModalTitle': '部署',
'fileViewer.deployModalSubtitle': '使用所选平台账号部署当前 HTML 预览。',
'fileViewer.vercelToken': 'Vercel token',
'fileViewer.vercelTokenGetLink': '获取 Vercel token',
'fileViewer.vercelTokenPlaceholder': '粘贴你的 Vercel token',
'fileViewer.vercelTokenReuseHint': '将使用已保存的令牌。输入新令牌可替换。',
'fileViewer.vercelTokenRequired': '请先输入并保存 Vercel 令牌。',
'fileViewer.cloudflareApiToken': 'Cloudflare API 令牌',
'fileViewer.cloudflareApiTokenGetLink': '获取 Cloudflare API 令牌',
'fileViewer.cloudflareApiTokenPlaceholder': '粘贴你的 Cloudflare API 令牌',
'fileViewer.cloudflareApiTokenReuseHint': '将使用已保存的 Cloudflare API 令牌。输入新令牌可替换。',
'fileViewer.cloudflareApiTokenRequired': '请先输入并保存 Cloudflare API 令牌。',
'fileViewer.cloudflareApiTokenScopeHint': '令牌需要 Account: Cloudflare Pages: Edit 权限,以及账号读取权限。',
'fileViewer.vercelTeamId': '团队 ID',
'fileViewer.vercelTeamSlug': '团队标识',
'fileViewer.cloudflareAccountId': '账户 ID',
'fileViewer.cloudflareAccountIdHint': '必填。可在 Cloudflare 控制台中找到账户 ID。',
'fileViewer.cloudflareAccountIdRequired': '请先输入并保存 Cloudflare 账户 ID。',
'fileViewer.cloudflareZoneLabel': 'Domain',
'fileViewer.cloudflareZonePlaceholder': 'Save Cloudflare settings to load domains',
'fileViewer.cloudflareZoneRequired': 'Select a Cloudflare domain first.',
'fileViewer.cloudflareZonesLoading': 'Loading Cloudflare domains…',
'fileViewer.cloudflareZonesRefresh': 'Refresh domains',
'fileViewer.cloudflareZonesLoadFailed': 'Could not load Cloudflare domains.',
'fileViewer.cloudflareZonesEmpty': 'No active full Cloudflare domains were found for this account.',
'fileViewer.cloudflareDomainPrefixLabel': 'Subdomain prefix',
'fileViewer.cloudflareDomainPrefixPlaceholder': 'demo',
'fileViewer.cloudflareDomainPrefixInvalid': 'Use one DNS label only: lowercase letters, numbers, and hyphens.',
'fileViewer.cloudflareHostnamePreview': 'Custom domain preview: {hostname}',
'fileViewer.cloudflareCustomDomainHint': 'Optional: choose a Cloudflare domain and prefix to bind a custom subdomain. pages.dev will still be available.',
'fileViewer.cloudflarePagesDevLinkLabel': 'pages.dev URL',
'fileViewer.cloudflareCustomDomainLinkLabel': 'Custom domain',
'fileViewer.optional': '可选',
'fileViewer.vercelPreviewOnly': '当前仅部署 Preview。',
'fileViewer.cloudflarePagesPreviewHint': 'Cloudflare Pages 使用 Direct Upload。',
'fileViewer.savingConfig': '保存中…',
'fileViewer.deployConfigSaveFailed': '保存 Vercel 设置失败。',
'fileViewer.deployFailed': '部署失败,请检查 Vercel 设置后重试。',
'fileViewer.deployProviderConfigSaveFailed': '无法保存 {provider} 设置。',
'fileViewer.deployProviderFailed': '{provider} 部署失败。请检查设置后重试。',
'fileViewer.deployResultLabel': '部署链接',
'fileViewer.deployLinkReady': '已就绪',
'fileViewer.deployLinkPreparingLabel': '公开链接准备中',
'fileViewer.deployLinkDelayed': '站点已经部署,平台仍在准备公开链接。',
'fileViewer.deployLinkFailed': '自定义域名失败',
'fileViewer.deployLinkProtectedLabel': '部署访问保护已开启',
'fileViewer.deployLinkProtected': '站点已部署,但此预览链接要求登录后才能访问。请关闭 Deployment Protection 或使用自定义域名。',
'fileViewer.retryLink': '立即重试',
'questionForm.submit': '提交',
'questionForm.skip': '跳过',
'questionForm.locked': '已回答',
'conv.switch': '切换对话',
'conv.label': '对话',
'conv.heading': '对话历史',
'conv.new': '+ 新建',
'conv.empty': '还没有对话。',
'conv.untitled': '未命名对话',
'conv.renameTooltip': '双击重命名',
'conv.delete': '删除对话',
'conv.deleteConfirm': '确定删除「{title}」?该操作会删除其消息。',
'agentPicker.label': '代理',
'agentPicker.modeChoose': '选择执行模式',
'agentPicker.localCli': '本机 CLI',
'agentPicker.daemonOff': '守护进程未运行',
'agentPicker.byok': 'API · BYOK',
'agentPicker.selectAgent': '选择已检测到的代码代理 CLI',
'agentPicker.noAgents': 'PATH 中未发现代理',
'agentPicker.notInstalled': '未安装',
'agentPicker.rescan': '重新扫描 PATH 中的代理',
'tool.openInTab': '在标签页中打开 {name}',
'tool.open': '打开',
'tool.todos': '待办',
'tool.write': '写入',
'tool.edit': '编辑',
'tool.read': '读取',
'tool.bash': 'Bash',
'tool.glob': 'Glob',
'tool.grep': 'Grep',
'tool.fetch': '抓取',
'tool.search': '搜索',
'tool.lines': '{n} 行',
'tool.changeSingular': '处变更',
'tool.changePlural': '处变更',
'tool.in': '于 {path}',
'tool.hide': '隐藏',
'tool.output': '输出',
'tool.running': '运行中…',
'tool.error': '错误',
'tool.done': '完成',
'assistant.role': '助手',
'assistant.workingLabel': '执行中',
'assistant.doneLabel': '已完成',
'assistant.emptyResponseLabel': '无输出',
'assistant.emptyResponseMessage': '服务商结束了请求,但没有返回文本或设计产物。请尝试更换模型或服务商、检查额度,或重试。',
'assistant.unfinishedLabel': '已停止,仍有未完成任务',
'assistant.unfinishedSummary': '剩余 {n} 个任务',
'assistant.unfinishedMore': '还有 {n} 个',
'assistant.continueRemaining': '继续剩余任务',
'assistant.outTokens': '{n} 输出',
'assistant.producedFiles': '本轮产出的文件',
'assistant.openFile': '打开',
'assistant.downloadFile': '下载',
'assistant.thinking': '思考中',
'assistant.systemReminder': '系统提示',
'assistant.waitingFirstOutput': '等待首批输出中',
'assistant.statusBootingAgent': '正在启动代理',
'assistant.statusStarting': '启动中',
'assistant.statusRequesting': '正在发送请求',
'assistant.statusThinking': '思考中',
'assistant.statusStreaming': '流式输出中',
'assistant.slowHint':
'耗时比平时更久。一般 510 秒内会出现表单,可以「停止」后重新表述。',
'assistant.verbEditing': '编辑',
'assistant.verbWriting': '写入',
'assistant.verbReading': '读取',
'assistant.verbSearching': '搜索',
'assistant.verbRunning': '运行',
'assistant.verbTodos': '待办',
'assistant.verbFetching': '抓取',
'assistant.verbCalling': '调用',
'qf.answered': '已回答',
'qf.choose': '请选择…',
'qf.required': '必填',
'qf.lockedSubmitted': '答案已发送,代理将在本次会话后续使用。',
'qf.lockedPrev': '该表单来自此前的对话。',
'qf.hint': '挑选合适的选项;可选项可以跳过,代理会使用合理的默认值。',
'qf.submitDefault': '发送答案',
'qf.submitDisabledTitle': '请先填写必填项',
'qf.submitTitle': '发送答案',
'qf.cardSelected': '已选',
'qf.cardRefs': '参考:',
'qf.cardSampleText': '飞燕环宇 · 0123',
'sketch.toolSelect': '选择(占位)',
'sketch.toolPen': '钢笔',
'sketch.toolText': '文本',
'sketch.toolRect': '矩形',
'sketch.toolArrow': '箭头',
'sketch.toolEraser': '橡皮擦',
'sketch.color': '颜色',
'sketch.strokeSize': '描边粗细',
'sketch.undo': '撤销',
'sketch.clear': '清空',
'sketch.close': '关闭',
'sketch.closeConfirm': '关闭草图并放弃未保存的更改吗?',
'sketch.textPrompt': '请输入文本:',
'sketch.textModalTitle': '添加文本',
'feedback.prompt': '本次回复有帮助吗?',
'feedback.thumbsUp': '有帮助',
'feedback.thumbsDown': '没帮助',
'feedback.submittedPositive': '感谢您的反馈。',
'feedback.submittedNegative': '感谢您的反馈,我们会据此改进。',
'feedback.commentLabel': '哪里可以改进?(可选)',
'feedback.commentPlaceholder': '告诉我们可以做得更好的地方',
'feedback.commentSubmit': '发送评论',
'feedback.commentSaved': '评论已保存',
'feedback.change': '更改',
'pet.title': '宠物',
'pet.tabBuiltIn': '内置',
'pet.tabBuiltInHint': 'Open Design 内置的精选宠物 — 一键领养。',
'pet.builtInEmpty': '暂时无法加载内置宠物。等本地服务恢复后,刷新「社区」页签再试。',
'pet.tabCustom': '自定义',
'pet.tabCustomHint': '自己取名、选符号或上传精灵图。',
'pet.tabCommunity': '社区',
'pet.tabCommunityHint': '来自 Codex 的孵化宠物 — 领养或用 AI 生成新的。',
'pet.tabsAria': '宠物来源',
'pet.subtitle': '领养一只小宠物,让它陪你一起设计。',
'pet.navTitle': '宠物',
'pet.navHint': '领养与自定义',
'pet.adopt': '领养',
'pet.adoptedBadge': '已领养',
'pet.adoptCallout': '领养一只宠物',
'pet.changePet': '更换宠物',
'pet.wake': '唤醒',
'pet.tuck': '收起',
'pet.wakeTitle': '唤醒宠物 — 显示浮窗。',
'pet.tuckTitle': '收起宠物 — 隐藏浮窗。',
'pet.settingsTitle': '打开宠物设置',
'pet.useCustom': '使用我的宠物',
'pet.customTitle': '自定义你的宠物',
'pet.customHint': '挑一个名字、表情和主题色,浮窗会即时更新。',
'pet.customGreetingPlaceholder': '来自宠物的问候…',
'pet.fieldName': '名字',
'pet.fieldGlyph': '表情',
'pet.fieldGlyphHint': '建议使用单个 emoji例如 🐝、🦄、🐢)。',
'pet.fieldGreeting': '问候语',
'pet.fieldAccent': '主题色',
'pet.fieldAccentCustom': '自定义颜色',
'pet.overlayAria': '宠物伙伴',
'pet.spriteAria': '{name} — 拖动可移动,点击与它互动',
'pet.spriteTitle': '{name} 来打招呼啦!点击聊天。',
'pet.railAria': '宠物选择器',
'pet.railTitle': '宠物',
'pet.railHint': '挑一只小伙伴,让它在你的工作区里飘着。',
'pet.railExpand': '展开宠物选择器',
'pet.railCollapse': '收起宠物选择器',
'pet.railHide': '隐藏宠物选择器',
'pet.railShow': '显示宠物选择器',
'pet.railCustomFlavor': '自定义 — 名字、表情、颜色随你定。',
'pet.railCustomize': '自定义…',
'pet.composerTitle': '宠物 — 唤醒、收起或选一只',
'pet.composerMenuTitle': '宠物',
'pet.composerMenuHint': '小贴士:输入 /pet 即可切换',
'pet.composerOpenSettings': '在设置中自定义',
'pet.welcomeTeaserTitle': '领养一只宠物',
'pet.welcomeTeaserBody': '一只小小的浮窗伙伴,会陪着你工作。',
'pet.welcomeTeaserCta': '挑一只',
'pet.imageUpload': '上传形象',
'pet.imageReplace': '替换形象',
'pet.imageRemove': '改用 emoji',
'pet.imageHintIdle': '支持 PNG / JPG / WebP / GIF / SVG。要做精灵动画传一张横向序列图并设置帧数。',
'pet.imageHintActive': '正在使用你上传的形象。把帧数设为 > 1 即可让横向序列图动起来。',
'pet.fieldFrames': '帧数',
'pet.fieldFramesHint': '1 = 静态;> 1 = 横向序列图。',
'pet.fieldFps': '速度 (fps)',
'pet.fieldFpsHint': '控制序列图的播放速度。',
'pet.atlasImport': '导入 Codex 精灵图',
'pet.atlasImportTitle': '导入 hatch-pet 8x9 / 192x208 精灵图(PNG 或 WebP)。',
'pet.atlasPickerTitle': '选择动画行',
'pet.atlasPickerHint': 'Codex 宠物自带 9 个动画状态。默认会保留完整精灵图,这样宠物会根据悬停、拖拽方向、长时间空闲自动切换动画。也可以只保留一个循环。',
'pet.atlasCancel': '丢弃精灵图',
'pet.atlasAdopt': '锁定这一行',
'pet.atlasAdoptFull': '使用完整精灵图(动态)',
'pet.atlasAdoptFullTitle': '保留全部动画行,让宠物对悬停、拖拽方向以及长时间空闲做出反应。',
'pet.atlasAdoptRowTitle': '只把高亮的这一行切成单循环条带。',
'pet.atlasActiveHint': '动态精灵图已启用 — 宠物会根据你的交互(悬停、拖拽、空闲)自动切换动画。',
'pet.atlasRow.idle': '待机',
'pet.atlasRow.running-right': '向右跑',
'pet.atlasRow.running-left': '向左跑',
'pet.atlasRow.waving': '挥手',
'pet.atlasRow.jumping': '跳跃',
'pet.atlasRow.failed': '失败',
'pet.atlasRow.waiting': '等待',
'pet.atlasRow.running': '奔跑',
'pet.atlasRow.review': '审视',
'pet.hatchTitle': '用 AI 孵化新宠物',
'pet.hatchHint': '通过聊天调用内置的 hatch-pet 技能生成 Codex 风格的精灵图,完成后回到这里导入。',
'pet.hatchConcept': '宠物概念(可选)',
'pet.hatchConceptPlaceholder': '例如:一只穿着毛衣的像素风柴犬',
'pet.hatchCopy': '复制提示词',
'pet.hatchCopied': '已复制!',
'pet.hatchFoot': '技能保存好宠物后,回到这里点击「导入 Codex 精灵图」即可。',
'pet.slashPopoverAria': '斜杠命令',
'pet.slashPopoverTitle': '命令',
'pet.slashPopoverHint': '↑↓ 切换 · 回车选择 · esc 关闭',
'pet.slashPet': '切换、领养或跳转到宠物设置。',
'pet.slashPetWake': '唤醒漂浮的宠物。',
'pet.slashPetTuck': '把宠物收起来。',
'pet.slashHatch': '调用 hatch-pet 技能生成一只 Codex 宠物。',
'pet.slashHatchArg': '<概念>',
'pet.slashSearch': '通过 OD research 命令搜索网页。',
'pet.slashSearchArg': '<查询>',
'pet.codexTitle': '最近孵化',
'pet.codexSubtitle': 'hatch-pet 技能打包的宠物会出现在这里,可一键领养。',
'pet.codexSubtitleWithDir': '正在扫描 {dir},查找 hatch-pet 技能打包的宠物。',
'pet.codexEmpty': '还没有孵化的宠物。在聊天中输入 /hatch 来生成一只。',
'pet.codexLoading': '正在查找已孵化的宠物…',
'pet.codexRefresh': '刷新',
'pet.codexAdopt': '领养',
'pet.codexAdopting': '领养中…',
'pet.communitySync': '下载社区宠物',
'pet.communitySyncing': '下载中…',
'pet.communitySyncTitle': '从 Codex Pet Share 与 j20 Hatchery 同步最新宠物到 ~/.codex/pets/。',
'pet.communitySyncDone': '已同步 {wrote} 个新宠物(共 {total} 个)。',
'pet.communitySyncFailed': '同步失败:{error}',
'pet.codexBundled': '内置',
'pet.codexBundledTitle': 'Open Design 内置宠物,无需下载。',
'settings.notifications': '通知',
'settings.notificationsHint': '任务完成时的声音和桌面通知',
'settings.notifyCompletionSound': '完成提示音',
'settings.notifyCompletionSoundHint': '一轮任务结束时播放,默认关闭',
'settings.notifySuccessSound': '成功音色',
'settings.notifyFailureSound': '失败音色',
'settings.notifyDesktop': '桌面通知',
'settings.notifyDesktopHint': '窗口不在前台时弹出系统通知',
'settings.notifyDesktopBlocked': '浏览器已拒绝通知权限,请在站点设置中开启',
'settings.notifyDesktopUnsupported': '当前环境不支持桌面通知',
'settings.notifyTest': '测试通知',
'settings.notifyTestSent': '测试通知已发送;如果没有弹窗,请检查浏览器和系统通知设置。',
'settings.notifyTestFailed': '通知调用失败,请检查浏览器和系统通知设置。',
'settings.notifySoundDing': '叮',
'settings.notifySoundChime': '风铃',
'settings.notifySoundTwoToneUp': '上行双音',
'settings.notifySoundPluck': '拨弦',
'settings.notifySoundBuzz': '蜂鸣',
'settings.notifySoundTwoToneDown': '下行双音',
'settings.notifySoundThud': '低响',
'settings.skills': '技能',
'settings.skillsHint': '智能体在任务中可以调用的功能技能',
'settings.skillsNew': '新建技能',
'settings.skillsEmpty': '请在左侧选择一个技能,或新建一个。',
'settings.skillsEdit': '编辑',
'settings.skillsDelete': '删除',
'settings.skillsDeleteConfirm': '确认删除',
'settings.skillsName': '名称',
'settings.skillsTriggers': '触发词(逗号或换行分隔)',
'settings.skillsDescription': '描述',
'settings.skillsBody': 'SKILL.md 内容',
'settings.skillsCreate': '创建',
'settings.skillsSave': '保存',
'settings.skillsSaving': '保存中…',
'settings.skillsFiles': '文件',
'settings.skillsNoFiles': '该技能目录下暂无文件。',
'settings.designSystems': '设计系统',
'settings.designSystemsHint': '浏览并启用智能体可使用的设计系统',
'settings.librarySkills': '技能',
'settings.libraryDesignSystems': '设计系统',
'settings.librarySearch': '搜索...',
'settings.libraryAll': '全部',
'settings.libraryPreview': '预览',
'settings.libraryPreviewClose': '关闭',
'settings.libraryLoading': '加载中...',
'settings.libraryNoResults': '没有匹配的项目。',
'settings.libraryEnabled': '已启用',
'settings.libraryDisabled': '已禁用',
'settings.connectorsNavHint': '外部系统连接',
'settings.connectorsHint': '管理此设备的连接器和工具提供商设置。',
'settings.connectorsComposioApiKey': 'Composio API 密钥',
'settings.connectorsSavedTitle': '已保存到本地 daemon',
'settings.connectorsSavedWithTail': '已保存 · ••••{tail}',
'settings.connectorsSaved': '已保存',
'settings.connectorsGetApiKey': '获取 API 密钥',
'settings.connectorsReplaceKeyPlaceholder': '粘贴新密钥以替换已保存的密钥',
'settings.connectorsApiKeyPlaceholder': '粘贴 Composio API 密钥',
'settings.connectorsClear': '清除',
'settings.connectorsClearConfirmTitle': '清除已保存的 Composio API 密钥?',
'settings.connectorsClearConfirmBody': '删除密钥会断开此工作区下所有的 Composio 连接器。已连接的账号、OAuth 授权和工具访问权限都将被一并移除。',
'settings.connectorsClearConfirmContinue': '继续',
'settings.connectorsClearFinalTitle': '此操作会断开所有连接器',
'settings.connectorsClearFinalBody': '该操作无法撤销。粘贴新密钥后,需要从头重新连接每个集成。',
'settings.connectorsClearFinalConfirm': '删除密钥并断开',
'settings.connectorsClearArming': '稍等\u2026',
'settings.connectorsClearCancel': '取消',
'settings.connectorsSaveKey': "保存密钥",
'settings.connectorsSaveKeyTitle': "将此密钥发送到本地 daemon",
'settings.connectorsKeySaving': "保存中…",
'settings.connectorsKeyError': "保存密钥失败。请确认本地 daemon 已启动后再试。",
'settings.connectorsHelpSaved': '你的密钥会解锁下方目录,并保留在本地 daemon 中。粘贴新密钥可替换,或清除以移除。',
'settings.connectorsHelpUnsaved': "尚未保存 — 点击「保存密钥」即可把它存入本地 daemon并解锁下方目录。",
'settings.connectorsHelpEmpty': '添加密钥以解锁下方目录。密钥会本地存储在 daemon 中,绝不会通过环境变量发送。',
'settings.connectorsLoadingSavedKey': '正在从本地 daemon 中检查已保存的密钥…',
'settings.autosaveSaving': "保存中…",
'settings.autosaveSaved': "所有更改已保存",
'settings.autosaveError': "保存更改失败。本地 daemon 可能不在线。",
'settings.libraryToggleLabel': '切换',
// Memory (auto-extracted personalization saved as on-disk markdown)
'settings.memory': '记忆',
'settings.memoryHint': '从对话中自动沉淀的个性化信息',
'settings.memoryDescription': '自动从聊天中提取出的关于你的偏好和上下文的事实,以 Markdown 文件形式保存,并自动注入到每次对话中。',
'settings.memoryEnabled': '已启用',
'settings.memoryDisabled': '已关闭',
'settings.memoryEnableLabel': '启用记忆注入',
'settings.memoryDisabledBanner': '记忆当前已关闭。已有的事实文件保留在磁盘上,但不会被注入到新对话,也不会从新对话中提取新事实。',
'settings.memoryNew': '新建记忆',
'settings.memoryEdit': '编辑',
'settings.memoryDelete': '删除',
'settings.memoryPreview': '预览',
'settings.memoryEmpty': '还没有记忆。',
'settings.memoryEmptyHintZh': '记住: 用户偏好深色主题',
'settings.memoryEmptyHintEn': 'I prefer dark mode',
'settings.memoryName': '例如UI 偏好',
'settings.memoryDesc': '一句话 — 这条记忆是关于什么的?',
'settings.memoryBody': '- 规则一\n- 规则二\n\n为什么可选\n何时适用可选',
'settings.memoryBodyHint': '先用 bullet 列出规则,再补「为什么」和「何时适用」(可选)。支持 Markdown。也可以点上方示例直接载入。',
'settings.memoryStartersLabel': '不知道写什么?点一下填到表单里:',
'settings.memoryStarterUserName': '我的角色',
'settings.memoryStarterUserDesc': '我是一名前端工程师,在做 SaaS 设计工具',
'settings.memoryStarterUserBody': '- 角色:高级前端工程师\n- 技术栈React、TypeScript、Vite\n- 方向:设计 / 协作工具\n- 时区GMT+8Asia/Shanghai\n\n何时适用任何对话里举例时优先用前端 / Web 场景。',
'settings.memoryStarterFeedbackName': 'UI 偏好',
'settings.memoryStarterFeedbackDesc': '深色主题、字号偏大、信息密度低',
'settings.memoryStarterFeedbackBody': '- 主题:默认深色\n- 正文字号:≥ 18px\n- 信息密度:留白多一些,一屏不要塞太多东西\n\n为什么长时间使用眼睛不容易累。\n何时适用让你画 UI、网页、PPT 时都按这个走。',
'settings.memoryStarterProjectName': '当前项目',
'settings.memoryStarterProjectDesc': 'Open Design v0.5 — 聊天驱动的设计编辑器',
'settings.memoryStarterProjectBody': '- 目标:本季度交付聊天驱动的编辑体验\n- 优先级:流式渲染、本地多模态、离线优先\n- 技术栈Next.js 16、Express daemon、SQLite\n\n何时适用与本项目相关的所有对话。',
'settings.memorySaveHint': '不会自动保存 — 点击「创建」/「保存」才生效。',
'settings.memoryIndexSaveHint': '索引不会自动保存 — 改完后点击「保存索引」才生效。',
'settings.memoryIndexUnsaved': '有未保存的修改',
'settings.memoryFlashCreated': '✓ 已创建',
'settings.memoryFlashSaved': '✓ 已保存',
'settings.memoryFlashDeleted': '✓ 已删除',
'settings.memoryFlashIndexSaved': '✓ 索引已保存',
'settings.memoryNameLabel': '标题',
'settings.memoryTypeLabel': '类型',
'settings.memoryDescLabel': '描述',
'settings.memoryBodyLabel': '内容',
'settings.memoryTypeUser': '用户',
'settings.memoryTypeFeedback': '反馈',
'settings.memoryTypeProject': '项目',
'settings.memoryTypeReference': '引用',
'settings.memoryIndex': 'MEMORY.md索引',
'settings.memoryIndexSave': '保存索引',
'settings.memoryIndexReset': '重置',
'settings.memoryToastChanged': '记忆已更新',
'settings.memoryToastClickHint': '查看',
'settings.memoryAll': '全部',
'settings.memoryExtractions': '抽取历史',
'settings.memoryExtractionsHint': '最近的 LLM 抽取记录。每次对话结束后启发式正则会先跑LLM 抽取在后台异步进行。',
'settings.memoryExtractionsEmpty': '暂无抽取记录。下一次对话结束后会出现在这里。',
'settings.memoryExtractionsRefresh': '刷新',
'settings.memoryExtractionPhaseRunning': '抽取中…',
'settings.memoryExtractionPhaseSuccess': '成功',
'settings.memoryExtractionPhaseSkipped': '已跳过',
'settings.memoryExtractionPhaseFailed': '失败',
'settings.memoryExtractionSkipNoProvider': '未配置 API keyLLM 抽取未运行。',
'settings.memoryExtractionSkipDisabled': '记忆功能已关闭。',
'settings.memoryExtractionSkipEmpty': '用户消息为空,没有可抽取的内容。',
'settings.memoryExtractionSkipNoMatch': '本轮没有命中任何正则规则。',
'settings.memoryExtractionKindHeuristic': '正则',
'settings.memoryExtractionKindLlm': 'LLM',
'settings.memoryExtractionProviderEnv': '环境变量',
'settings.memoryExtractionProviderMediaConfig': '媒体设置',
'settings.memoryExtractionProviderOverride': '记忆设置',
'settings.memoryExtractionProposed': '候选',
'settings.memoryExtractionWritten': '写入',
'settings.memoryExtractionDuration': '耗时',
'settings.memoryExtractionDelete': '删除',
'settings.memoryExtractionsClear': '清空',
'settings.memoryExtractionsClearTitle': '清空整个抽取历史',
'settings.memoryNoProviderBannerTitle': 'LLM 抽取未启用',
'settings.memoryNoProviderBannerBody': '未找到可用的 API keyLLM 抽取已跳过。可以在媒体提供商里填入 OpenAI key或设置环境变量 ANTHROPIC_API_KEY / OPENAI_API_KEY 来启用。启发式抽取仍在运行。',
'settings.libraryInstall': '安装',
'settings.libraryInstallGithub': 'GitHub',
'settings.libraryInstallLocal': '本地路径',
'settings.libraryInstallUrl': 'https://github.com/owner/repo',
'settings.libraryInstallPath': '/path/to/skill-folder',
'settings.libraryInstallButton': '安装',
'settings.libraryUninstall': '卸载',
'settings.libraryBuiltIn': '内置',
'settings.libraryInstalled': '已安装',
'notify.successTitle': '任务已完成',
'notify.failureTitle': '任务失败',
'notify.successBody': '一轮回答已经写完。',
'notify.failureBody': '本轮任务出错,请查看错误信息。',
'settings.memoryModelInlineLabel': 'Memory 模型',
'settings.memoryModelInlineSameAsChat': '与聊天一致',
'settings.memoryModelInlineSameAsChatWithModel': '与聊天一致({model}',
'settings.memoryModelInlineSameAsChatWithProvider': '与聊天一致({provider}',
'settings.memoryModelInlineHintCli': '可选。Memory 提取仍然使用环境变量或媒体设置里的 API key 调用对应供应商;这里选模型只是替换自动挑选的默认值。',
'settings.memoryModelInlineHintCliConstrained': '可选。Memory 将调用 {provider};需要对应的环境变量或媒体设置里的 API key或在下面选一个模型来覆盖。',
'settings.memoryModelInlineHintByok': '可选。复用你聊天用的 API key在同供应商上换一个通常更便宜的模型来跑后台 memory 提取。',
'settings.memoryModelInlineFlashSaved': '已保存',
'settings.memoryModelInlineFlashCleared': '已清除',
'settings.orbit.eyebrow': '自动化',
'settings.orbit.title': 'Orbit',
'settings.orbit.navHint': '每日连接器摘要',
'settings.orbit.lede': '按计划收集连接器活动,并将结果发布为可刷新的 live artifact。',
'settings.orbit.statusOnTitle': '每日计划运行已开启',
'settings.orbit.statusOffTitle': '每日计划运行已关闭',
'settings.orbit.statusActive': '活跃',
'settings.orbit.statusOff': '关闭',
'settings.orbit.runTitle': '启动一次 Orbit 运行并打开实时对话',
'settings.orbit.running': '运行中…',
'settings.orbit.runOpen': '立即运行',
'settings.orbit.dailySummaryTitle': '每日摘要',
'settings.orbit.dailySummarySub': '每天在计划的本地时间运行一次。',
'settings.orbit.on': '开启',
'settings.orbit.off': '关闭',
'settings.orbit.runTimeTitle': '运行时间',
'settings.orbit.runTimeSub': '默认 08:00。保存后应用到 daemon 计划。',
'settings.orbit.runTimeAria': '每日 Orbit 运行时间',
'settings.orbit.nextRun': '下次运行',
'settings.orbit.nextRunScheduledAfterSave': '保存后计划',
'settings.orbit.schedule': '计划',
'settings.orbit.pausedManualOnly': '已暂停 — 仅手动运行',
'settings.orbit.templateTitle': '提示词模板',
'settings.orbit.templateMissing': '模板 {id} 未安装。',
'settings.orbit.templateMissingOption': '{id}(缺失)',
'settings.orbit.templateMissingInstall': '安装 Orbit skill 以引导提示词。',
'settings.orbit.templateMissingPickAnother': '从下拉菜单选择另一个模板。',
'settings.orbit.templateResetTitle': '重置为 {id}',
'settings.orbit.templateReset': '重置',
'settings.orbit.templateHelp': '用 skill 引导 Orbit — 所选模板的示例提示词会注入每次 Orbit 运行,让摘要遵循该模板结构。',
'settings.orbit.templateAria': 'Orbit 提示词模板',
'settings.orbit.templatesLoading': '正在加载模板…',
'settings.orbit.templatesOptgroup': 'Orbit skill 模板',
'settings.orbit.lastRun': '上次运行',
'settings.orbit.triggerManual': '手动',
'settings.orbit.triggerScheduled': '计划',
'settings.orbit.meterAria': '已成功 {succeeded},已跳过 {skipped},失败 {failed},共检查 {checked}',
'settings.orbit.countChecked': '已检查',
'settings.orbit.countSucceeded': '成功',
'settings.orbit.countSkipped': '已跳过',
'settings.orbit.countFailed': '失败',
'settings.orbit.runError': '无法运行 Orbit。请确认本地 daemon 正在运行且连接器已配置。',
'settings.orbit.gateAriaLabel': "使用 Orbit 需要先配置连接器",
'settings.orbit.gateEyebrow': "需要先完成设置",
'settings.orbit.gateTitle': "连接一个工具,让 Orbit 运行起来",
'settings.orbit.gateBody': "Orbit 会汇总你已连接服务的活动。你目前还没有任何连接 —— 至少添加一个集成,让 Orbit 有内容可以报告。",
'settings.orbit.gateBodyNoKey': "Orbit 会汇总连接器的活动,而连接器通过 Composio 运行。在「连接器」中填入 Composio API 密钥即可解锁目录并选择第一个集成。",
'settings.orbit.gateAction': "打开连接器",
'settings.orbit.gateActionNoKey': "配置 Composio",
'settings.orbit.gateLoading': "正在检查连接器…",
'settings.orbit.controlsLockedBadge': "已锁定",
'settings.orbit.controlsLockedHint': "连接一个工具后即可解锁 Orbit 的排程与模板设置。",
'settings.orbit.artifactKickerLive': 'live artifact',
'settings.orbit.artifactKickerLegacy': '旧版摘要',
'settings.orbit.artifactTitle': '每日 Orbit 活动摘要',
'settings.orbit.artifactMetaLive': '由连接器活动生成的可刷新 HTML artifact。',
'settings.orbit.artifactMetaLegacy': '在启用 live artifact 支持之前生成 — 再次运行 Orbit 以发布一个。',
'settings.orbit.copyMarkdownTitle': '复制 Markdown 摘要到剪贴板',
'settings.orbit.copied': '已复制',
'settings.orbit.copy': '复制',
'settings.orbit.openArtifact': '打开 artifact',
'settings.orbit.sourceMarkdown': '源 Markdown',
'liveArtifact.viewer.tabPreview': '预览',
'liveArtifact.viewer.tabCode': '代码',
'liveArtifact.viewer.tabData': '数据',
'liveArtifact.viewer.tabRefreshHistory': '刷新历史',
'liveArtifact.viewer.dataEmpty': '没有可用的 data.json 缓存。',
'liveArtifact.viewer.code.templateHeading': '模板 HTML',
'liveArtifact.viewer.code.renderedHeading': '渲染后 HTML',
'liveArtifact.viewer.code.templateHelp': '用于配合 data.json 生成预览的可编辑模板。',
'liveArtifact.viewer.code.renderedHelp': 'Preview 当前加载的已生成 index.html。',
'liveArtifact.viewer.code.variantAria': '代码版本',
'liveArtifact.viewer.code.variantTemplate': '模板',
'liveArtifact.viewer.code.variantRendered': '已渲染',
'liveArtifact.viewer.code.loading': '正在加载代码…',
'liveArtifact.viewer.code.unavailable': '代码尚不可用。',
'liveArtifact.viewer.code.empty': '此代码文件为空。',
};