diff --git a/crates/openpencil-shell-core/src/widgets/ai_chat_panel.rs b/crates/openpencil-shell-core/src/widgets/ai_chat_panel.rs index 0a8cddd9a..b95090925 100644 --- a/crates/openpencil-shell-core/src/widgets/ai_chat_panel.rs +++ b/crates/openpencil-shell-core/src/widgets/ai_chat_panel.rs @@ -88,6 +88,12 @@ pub struct AIChatPlaceholder<'a> { /// [`jian_core::anim::blink_visible`]. `0` = host hasn't /// installed a clock yet (caret stays solid). pub now_ms: u64, + /// Localised chrome strings — resolved at construction time + /// from `Document::t` so the panel reflows when the user + /// flips the TopBar Globe icon. + pub label_new_chat: String, + pub label_start_with_ai: String, + pub label_input_placeholder: String, } impl<'a> AIChatPlaceholder<'a> { @@ -103,6 +109,9 @@ impl<'a> AIChatPlaceholder<'a> { theme: doc.theme(), state: &doc.chat, now_ms, + label_new_chat: doc.t("chat.new_chat").to_string(), + label_start_with_ai: doc.t("chat.start_with_ai").to_string(), + label_input_placeholder: doc.t("chat.input_placeholder").to_string(), } } @@ -207,7 +216,7 @@ impl<'a> Widget for AIChatPlaceholder<'a> { ); // "New Chat" label. let title = TextLayout::single_run( - "New Chat", + &self.label_new_chat, "system-ui", 13.0, to_jian_color(self.theme.foreground), @@ -246,7 +255,7 @@ impl<'a> Widget for AIChatPlaceholder<'a> { 1.4, ); let title = TextLayout::single_run( - "New Chat", + &self.label_new_chat, "system-ui", 14.0, to_jian_color(self.theme.foreground), @@ -282,7 +291,7 @@ impl<'a> Widget for AIChatPlaceholder<'a> { }; if self.state.messages.is_empty() { - paint_examples(cx, &self.theme, rect); + paint_examples(cx, &self.theme, rect, &self.label_start_with_ai); } else { paint_messages(cx, &self.theme, body_rect, &self.state.messages); } @@ -311,7 +320,10 @@ impl<'a> Widget for AIChatPlaceholder<'a> { // Input text — buffer if non-empty, placeholder otherwise. let (text, color) = if self.state.input.is_empty() { - ("用 Agent 设计…", self.theme.muted_foreground) + ( + self.label_input_placeholder.as_str(), + self.theme.muted_foreground, + ) } else { (self.state.input.as_str(), self.theme.foreground) }; @@ -400,9 +412,9 @@ impl<'a> Widget for AIChatPlaceholder<'a> { } } -fn paint_examples(cx: &mut PaintCx<'_>, theme: &Theme, rect: Rect) { +fn paint_examples(cx: &mut PaintCx<'_>, theme: &Theme, rect: Rect, hint_label: &str) { let hint = TextLayout::single_run( - "用 AI 开始设计", + hint_label, "system-ui", 12.0, to_jian_color(theme.muted_foreground), diff --git a/crates/openpencil-shell-core/src/widgets/layer_panel.rs b/crates/openpencil-shell-core/src/widgets/layer_panel.rs index a5cd4195f..f1695b5d6 100644 --- a/crates/openpencil-shell-core/src/widgets/layer_panel.rs +++ b/crates/openpencil-shell-core/src/widgets/layer_panel.rs @@ -49,6 +49,8 @@ pub struct LayerPanel { pub pages: Vec, pub items: Vec, pub theme: Theme, + pub pages_label: String, + pub layers_label: String, } impl LayerPanel { @@ -77,6 +79,8 @@ impl LayerPanel { pages, items, theme: doc.theme(), + pages_label: doc.t("layer_panel.pages").to_string(), + layers_label: doc.t("layer_panel.layers").to_string(), } } @@ -86,6 +90,8 @@ impl LayerPanel { pages: Vec::new(), items: Vec::new(), theme: Theme::dark(), + pages_label: "Pages".to_string(), + layers_label: "Layers".to_string(), } } @@ -187,7 +193,7 @@ impl Widget for LayerPanel { let mut y = rect.origin.y + 8.0; // Pages section header. - paint_section_header(cx, &self.theme, rect.origin.x, y, rect.size.x, "页面"); + paint_section_header(cx, &self.theme, rect.origin.x, y, rect.size.x, &self.pages_label); // "+" add-page affordance, top-right of header row. let plus_x = rect.origin.x + rect.size.x - ROW_PAD_X - 12.0; let plus_y = y + (SECTION_HEADER_HEIGHT - 14.0) / 2.0; @@ -232,7 +238,7 @@ impl Widget for LayerPanel { y += SECTION_GAP; // Layers section header. - paint_section_header(cx, &self.theme, rect.origin.x, y, rect.size.x, "图层"); + paint_section_header(cx, &self.theme, rect.origin.x, y, rect.size.x, &self.layers_label); y += SECTION_HEADER_HEIGHT; // Layer rows.