docs: translate remaining Chinese source comments to English

This commit is contained in:
Kayshen-X 2026-05-17 09:33:41 +08:00
parent 3ed6c8136f
commit 0ea1ba02a3
23 changed files with 77 additions and 68 deletions

View file

@ -1,8 +1,10 @@
[workspace]
resolver = "2"
# 用 glob 而非显式列表Step 0 增量创建 crate 时不需要每次改 membersper implementer
# Phase 1 batch 2 的 workspace masking 反馈:列出未存在的 crate 会让 `cargo build -p X`
# 在 resolve 阶段就挂掉。glob 自动包含 crates/ 下所有 manifest自然支持增量创建。
# Use a glob instead of an explicit list: incremental crate creation in Step 0
# does not require editing `members` each time (per implementer Phase 1 batch 2
# workspace-masking feedback: listing a non-existent crate makes `cargo build -p X`
# fail at the resolve stage). The glob picks up every manifest under crates/,
# naturally supporting incremental creation.
members = ["crates/*"]
exclude = [
"vendor/agent",
@ -27,9 +29,10 @@ thiserror = "1"
anyhow = "1"
tracing = "0.1"
# WASM 边界相关per kickoff §1.2 黑名单 = 不出现在这里)
# 故意不在 workspace.dependencies 暴露 tokio / reqwest / agent / pen-agent-cli /
# pen-server / native-tls —— 这些只在 native-only crate 内部用 dev-deps 或 target-specific deps。
# WASM-boundary related (per kickoff §1.2 blacklist = must not appear here).
# Intentionally NOT exposing tokio / reqwest / agent / pen-agent-cli /
# pen-server / native-tls in workspace.dependencies — these are used only
# inside native-only crates via dev-deps or target-specific deps.
# Step 1b §3.2 P0.5B Run path (2026-05-09): wasm32-unknown-unknown skia
# build via `vendor/skia-safe-op` — fork of rust-skia 0.97.0 with a new

View file

@ -148,7 +148,7 @@ pub struct AgentSettings {
pub focus: Option<SettingsFocus>,
/// Index into `AgentProvider::ALL` of the card the cursor is
/// currently hovering, used to flip the connect button into a
/// red 断开连接 affordance on already-connected cards. `usize::MAX`
/// red disconnect affordance on already-connected cards. `usize::MAX`
/// means no card is hovered.
pub hover_provider: usize,
/// Sidebar nav item under the cursor (Agents / MCP / Images /

View file

@ -251,7 +251,7 @@ pub struct EditorUiState {
pub export_scale: f32,
pub export_dialog_open: bool,
pub export_format: ExportFormat,
/// Modal "从 Figma 导入".
/// "Import from Figma" modal.
pub figma_import_open: bool,
/// Floating `Cmd+,` agent-settings modal open.
pub agent_settings_open: bool,

View file

@ -706,7 +706,7 @@ fn add_provider_rect(panel: Rect) -> Rect {
fn add_acp_rect(panel: Rect) -> Rect {
let content = content_rect(panel);
// 内置服务商 block: header 32 + subtitle 28 + empty 64 + SECTION_GAP 28 = 152.
// Built-in providers block: header 32 + subtitle 28 + empty 64 + SECTION_GAP 28 = 152.
let y = content.origin.y + 12.0 + 152.0;
let text_w = 96.0;
Rect {

View file

@ -1,9 +1,9 @@
//! `AIChatPlaceholder` — floating "用 AI 开始设计" / chat panel
//! `AIChatPlaceholder` — floating "start designing with AI" / chat panel
//! pinned to the bottom-center of the canvas (Step 4 visual lift +
//! Step 5 P2 dynamic state).
//!
//! Two render modes driven by `ChatState`:
//! - **Empty** (no messages): the original "用 AI 开始设计" hint
//! - **Empty** (no messages): the original "start designing with AI" hint
//! + 2×2 example cards — clicking a card fills the input.
//! - **Active** (≥1 message): renders the message list above the
//! input, hides the example grid.
@ -113,9 +113,9 @@ pub struct AIChatPlaceholder<'a> {
pub label_new_chat: String,
pub label_start_with_ai: String,
pub label_input_placeholder: String,
/// "提示:在对话前选中画布上的元素以提供上下文。" — bottom of
/// the empty-state body, between the example cards and the
/// separator above the input.
/// Tip line ("select canvas elements before chatting to provide
/// context") — bottom of the empty-state body, between the example
/// cards and the separator above the input.
pub label_tip_select_elements: String,
/// Chip label shown when no model is selected / discovered yet
/// (`ai.noModelsConnected`).

View file

@ -1,4 +1,4 @@
//! "从 Figma 导入" modal. Mirrors
//! "Import from Figma" modal. Mirrors
//! `apps/web/src/components/shared/figma-import-dialog.tsx` —
//! 720×400 card with a dashed drop-zone, upload icon, headline,
//! subtitle, and footer hint. Drag-drop of .fig files isn't wired

View file

@ -111,7 +111,7 @@ impl<'a> FileMenu<'a> {
h += DIVIDER_GAP * 2.0 + 1.0;
h += ROW_HEIGHT; // Export image
h += DIVIDER_GAP * 2.0 + 1.0;
h += HEADER_HEIGHT; // 最近文件 header
h += HEADER_HEIGHT; // Recent files header
let recent_len = self.recent.len().max(1);
h += ROW_HEIGHT * recent_len as f32;
h += DIVIDER_GAP * 2.0 + 1.0;
@ -469,7 +469,7 @@ fn paint_recent_row(
1.4,
);
// Reserve space for the age column on the right + a small gap
// so a long file name never overlaps "21 分钟前". Truncate with
// so a long file name never overlaps the age label. Truncate with
// a trailing `…` when the name exceeds that budget.
let aw = cx.backend.measure_text(&entry.age, SHORTCUT_FONT);
let name_x = x + PAD_X + ICON_SIZE + 10.0;

View file

@ -90,13 +90,13 @@ pub enum Icon {
ChevronUp,
/// MessageSquare — chat bubble icon (collapsed AI chat pill).
MessageSquare,
/// LayoutGrid — 2×2 grid layout-mode (弹性布局 / RightPanel).
/// LayoutGrid — 2×2 grid layout-mode (flex layout / RightPanel).
LayoutGrid,
/// Rows3 — horizontal rows layout-mode.
Rows3,
/// Columns3 — vertical columns layout-mode.
Columns3,
/// RotateCw — rotation handle for 位置 section.
/// RotateCw — rotation handle for the Position section.
RotateCw,
/// Diamond — "create component" button glyph.
Diamond,

View file

@ -1,6 +1,7 @@
//! Right-click context menu for LayerPanel rows. Two row sets:
//! layer rows (复制 / 删除 / 创建组件 / 切换锁定 / 切换可见性) and
//! page rows (重命名 / 复制 / 上移 / 下移 / 删除).
//! layer rows (Duplicate / Delete / Create component / Toggle lock /
//! Toggle visibility) and page rows (Rename / Duplicate / Move up /
//! Move down / Delete).
use crate::theme::Theme;
use crate::widgets::editor_state_ext::theme_for;

View file

@ -8,16 +8,16 @@
//! pieces under the openpencil 800-line ceiling.
//!
//! Sections (top → bottom, mirroring TS order):
//! 1. Tab strip (设计 / 代码)
//! 2. Header (kind label) + 创建组件 button
//! 3. 位置 — X / Y / rotation / R
//! 4. 弹性布局 — 3 layout-mode buttons
//! 5. 尺寸 — W / H + 5 sizing checkboxes
//! 6. 图层 — opacity row
//! 7. 填充 — solid color rows + add affordance
//! 8. 描边 — color + width row
//! 9. 效果 — empty list + add affordance
//! 10. 导出 — scale + format dropdowns
//! 1. Tab strip (Design / Code)
//! 2. Header (kind label) + Create component button
//! 3. Position — X / Y / rotation / R
//! 4. Flex layout — 3 layout-mode buttons
//! 5. Size — W / H + 5 sizing checkboxes
//! 6. Layer — opacity row
//! 7. Fill — solid color rows + add affordance
//! 8. Stroke — color + width row
//! 9. Effects — empty list + add affordance
//! 10. Export — scale + format dropdowns
//!
//! Conditional rendering: TS app does `{hasSelection && <RightPanel/>}`.
//! Host calls [`PropertyPanel::for_selection`] which returns
@ -76,7 +76,7 @@ pub enum PropertyPanelAction {
ToggleSizeHugWidth,
ToggleSizeHugHeight,
ToggleSizeClipContent,
/// User clicked the Fill section's "纯色" dropdown — host
/// User clicked the Fill section's fill-type dropdown — host
/// toggles `Document.ui.fill_type_picker_open`.
ToggleFillTypePicker,
/// User picked a fill type from the dropdown.

View file

@ -382,7 +382,7 @@ fn paint_fill_gradient_body(
};
cx.backend
.fill_round_rect(angle_rect, INPUT_RADIUS, theme.muted);
// "角度" prefix at left, value in middle, ° at right.
// Angle prefix at left, value in middle, ° at right.
let prefix = TextLayout::single_run(
"角度",
"system-ui",
@ -421,7 +421,7 @@ fn paint_fill_gradient_body(
);
yy += INPUT_HEIGHT + 6.0;
}
// 色标 header + plus.
// Color stops header + plus.
let header = TextLayout::single_run(
"色标",
"system-ui",

View file

@ -54,7 +54,7 @@ impl VisibleSections {
};
}
/// State for the 5 "尺寸" checkboxes (fill / hug / clip).
/// State for the 5 Size checkboxes (fill / hug / clip).
#[derive(Debug, Clone, Copy)]
pub struct SizeFlags {
pub fill_width: bool,

View file

@ -375,7 +375,7 @@ pub fn paint_flex_section(
let mut y = paint_section_label(cx, theme, labels.flex_layout, x, y, width);
// TS layout-section.tsx uses Columns3 / Rows3 / LayoutGrid for
// the three flex modes; LayoutGrid is the default-active mode
// (Free / 自由布局).
// (Free layout).
let btn_w = 56.0;
let gap = 8.0;
let row_x = x + PAD_X;

View file

@ -38,7 +38,7 @@ pub enum TopBarHit {
ToggleTheme,
/// Globe icon — cycle through UI locales.
ToggleLocale,
/// Agents MCP chip — open the agent settings modal.
/// Agents and MCP chip — open the agent settings modal.
OpenAgentSettings,
}
@ -309,8 +309,8 @@ impl Widget for TopBar {
// the chip anchors immediately to its left (small gap).
// Agent chip — two states:
// - empty (agent_count == 0): LayoutGrid icon + "Agents
// MCP" label. Affordance for "set up agents/MCP".
// - empty (agent_count == 0): LayoutGrid icon + an
// "Agents and MCP" label. Affordance for "set up agents/MCP".
// - active (≥ 1): Sparkles + green dot + "N agent" text.
// Anchored just left of the globe icon button (+small gap).
let count_label;

View file

@ -1,7 +1,8 @@
//! HTTP-server CLI bridge — structural lifecycle for CLIs that
//! run as a local HTTP server we POST JSON requests to. Per the
//! user's architecture note ("opencode 和 codex 我们调用 http
//! server, 通过 ipc 启动本地的 server 模式") the model is: spawn
//! user's architecture note (opencode and codex are driven via an
//! HTTP server, started in local server mode through IPC) the model
//! is: spawn
//! the binary in server mode, watch stdout for a "Listening on …"
//! line that announces the bind port, then send chat requests to
//! that local HTTP endpoint.

View file

@ -68,8 +68,8 @@ jian-ops-schema = { path = "../../vendor/jian/crates/jian-ops-schema" }
# Cross-platform widget render stack (desktop + mobile, NOT wasm).
#
# 2026-05-10 mobile extension (per user "extend, jian 最后也会需要 ios
# 和 android"): skia-safe + jian-skia move out of the desktop-only
# 2026-05-10 mobile extension (per user note that jian will eventually
# need iOS and Android): skia-safe + jian-skia move out of the desktop-only
# block so `NativeBackend` + `widget_host` compile on iOS / Android
# too. skia-safe's `gl` feature is desktop-only (iOS deprecated GL —
# Metal goes in Step 1f; Android uses GL/Vulkan via the platform

View file

@ -86,8 +86,8 @@ pub struct NativeBackend {
///
/// `typeface` covers ASCII (Roboto). `cjk_typeface` is resolved
/// lazily via `FontMgr::match_family_style_character` so non-
/// ASCII labels (`页面 / 图层 / 未命名 / 用 AI 开始设计 / ...`)
/// render through a system CJK font (PingFang on macOS,
/// ASCII labels (localized CJK chrome strings) render through a
/// system CJK font (PingFang on macOS,
/// Noto CJK on Linux/Windows) without re-paying jian-skia's
/// per-call FontCollection cost.
typeface: Option<skia_safe::Typeface>,
@ -367,8 +367,7 @@ impl NativeBackend {
/// - run is ASCII-only → cached Roboto + draw_str
/// - run contains non-ASCII → cached system CJK typeface +
/// draw_str (PingFang / Noto CJK / etc.). PingFang covers
/// Latin too, so mixed runs like "美食 App 首页" render
/// correctly.
/// Latin too, so mixed CJK + Latin runs render correctly.
/// - the system has no CJK font (rare; Linux without Noto)
/// → fall back to jian-skia's textlayout path so glyphs
/// don't drop. Still slow on that branch, but functional.

View file

@ -42,7 +42,7 @@ pub mod context;
// `widget_host` (NativeFrameBackend + WidgetHostNative) compile on
// every target where `skia-safe` + `jian-skia` compile — desktop
// trio + iOS + Android. Per the 2026-05-10 user directive
// ("extend, jian 最后也会需要 ios 和 android") these used to be
// (jian will eventually need iOS and Android) these used to be
// desktop-only; lifting the gate is the first half of the mobile
// extension. The other half (real `EaglProvider` / `AndroidEglProvider`
// impls + Metal/Vulkan integration) lands in Step 1f.

View file

@ -14,7 +14,7 @@
//! `widget_host` modules cfg-gated to `macos | linux | windows`).
//! Mobile widget rendering lands in Step 1f via `context::EaglProvider`
//! / `context::AndroidEglProvider`. Per the 2026-05-10 directive
//! ("安卓和ios 不需要 ipc / 本地 cli — 只需要 custom provider"):
//! (Android and iOS need no IPC / local CLI — only a custom provider):
//! mobile rendering is a custom-provider plugin point on the
//! `GlContextProvider` trait, not a separate IPC / CLI pipeline.
//!

View file

@ -8,7 +8,7 @@ use op_editor_ui::{Color, Point2D, Rect};
/// Small breathing room from the canvas corner so the chat pill
/// doesn't visually touch the canvas edge (per 2026-05-10 user
/// note "稍微加一点上下偶有的间距,一点点").
/// note to add just a little vertical spacing).
pub(in crate::widget_host) const AICHAT_INSET_BOTTOM: f32 = 12.0;
pub(in crate::widget_host) const AICHAT_INSET_LEFT: f32 = 12.0;

View file

@ -36,7 +36,7 @@ const ROBOTO_TTF: &[u8] = include_bytes!("../../assets/Roboto-Regular.ttf");
/// the rust-skia test resource at
/// `vendor/skia-safe-op/.../resources/fonts/NotoSansCJK-VF-subset.otf.ttc`).
/// Step 4 codex stop-hook fix: shell-core chrome strings include
/// CJK (`页面 / 图层 / 未命名 / 用 AI 开始设计` etc.) which Roboto
/// CJK (localized chrome strings) which Roboto
/// has no glyphs for, so the Roboto-only text path was rendering
/// `.notdef` boxes. The subset bundles enough Han / Latin coverage
/// to keep all chrome labels legible at <10 KB cost (bundle is
@ -389,7 +389,7 @@ impl RenderBackend for WebBackend {
}
if !self.cjk_typeface_tried {
// Step 4 codex stop-hook fix: chrome includes CJK
// labels (`页面`, `图层`, `未命名` etc.) so a
// labels (localized chrome strings) so a
// Roboto-only path produces `.notdef` boxes for every
// non-ASCII run. Build a second typeface from the
// embedded Noto Sans CJK subset.

View file

@ -3,9 +3,10 @@
[graph]
all-features = false
# 限定到实际发布目标macOS/Linux/Windows native + wasm32
# 不限定的话 cargo-deny 默认尝试所有 target含 Android/iOS
# 拉进 jni / android-activity 等 edition-2024 deps在 rustc 1.82 上 cargo metadata 失败。
# Scoped to the actual release targets (macOS/Linux/Windows native + wasm32).
# Without this, cargo-deny defaults to every target (including Android/iOS),
# pulling in edition-2024 deps like jni / android-activity, which makes
# `cargo metadata` fail on rustc 1.82.
targets = [
{ triple = "x86_64-unknown-linux-gnu" },
{ triple = "aarch64-unknown-linux-gnu" },
@ -37,27 +38,31 @@ ignore = []
[bans]
multiple-versions = "warn"
# workspace 内部 path 依赖不写 version标准实践避免每次 bump 都改两处)。
# 没有 crate 发布到 crates.iowildcard path deps 是预期的,故 allow。
# Workspace-internal path deps omit the version (standard practice — avoids
# editing two places on every bump). No crate ships to crates.io, so
# wildcard path deps are expected; hence allowed.
wildcards = "allow"
allow-wildcard-paths = true
deny = [
# WASM bundle 黑名单kickoff spec §1.2 invariant
# `agent` 不在此列:它是 op-host-desktop桌面二进制永不编译到 wasm
# native-only 依赖wasm 隔离是结构性的op-host-web 不依赖它)并由
# tools/check-wasm-bundle.sh 验证。
# WASM bundle blacklist (kickoff spec §1.2 invariant).
# `agent` is not listed: it is a native-only dependency of op-host-desktop
# (the desktop binary, never compiled to wasm); wasm isolation is
# structural (op-host-web does not depend on it) and verified by
# tools/check-wasm-bundle.sh.
"pen-agent-cli",
"pen-server",
"native-tls",
]
# 不再禁用 tokio 的 process / rt-multi-thread featureop-host-desktop
# 的原生 agent runtimeasync合法地需要它们。wasm 侧结构性安全——
# 这两个 feature 依赖 OS 线程/进程,无法编译到 wasm32——并由
# tools/check-wasm-bundle.sh 验证。
# tokio's process / rt-multi-thread features are no longer banned:
# op-host-desktop's native (async) agent runtime legitimately needs them.
# The wasm side is structurally safe — both features depend on OS
# threads/processes and cannot compile to wasm32 — and is verified by
# tools/check-wasm-bundle.sh.
[sources]
unknown-registry = "deny"
unknown-git = "deny"
# agent-rs 现在通过 vendor/agent submodule 以 path 依赖引入,不再是 git 依赖。
# agent-rs is now pulled in as a path dependency via the vendor/agent
# submodule, no longer a git dependency.
allow-git = []

View file

@ -14,8 +14,8 @@
# (`aarch64-linux-android`, `aarch64-apple-ios`) must NOT pull
# `jian-host-desktop` (desktop GUI host glue — winit / glutin /
# GLContextProvider impl that has no mobile equivalent). Per the
# 2026-05-10 user directive ("extend, jian 最后也会需要 ios 和
# android"), `jian-skia` is now ALLOWED on mobile targets — the
# 2026-05-10 user directive (jian will eventually need iOS and
# Android), `jian-skia` is now ALLOWED on mobile targets — the
# widget render stack (skia-safe + jian-skia + NativeBackend +
# widget_host) compiles for iOS / Android cargo check, leaving
# only the host-specific (Metal / Vulkan / event) integration to