feat(i18n): 外观页 40 条文案进词表(M180 I18NAPPEAR)
- 卡片内 22 处硬编码英文(整窗/面板透明度、背景图开关+路径、填充、暗化、配色来源)全部改走 Key
- 运行时诊断改成 key + 参数:`background::Note`(读盘/解码/过大/小图平铺)、`state::backend_note`、
`palette::note` 全部返回 Key;`state.rs` 只留 key、不放文案表(390 → 391 行)
- 上限/下限常量走占位符 `{floor}` / `{max}` / `{limit}` / `{requested}`;`{:.2}` 在 Rust 侧格式化好
再套模板(`Catalog::render` 只认 `{name}`)
- 新增 40 条 key(中英各一条),按装配链锚点插在 `SettingsAppearanceCornerSuspended` 之后,
金表 `golden/tail.rs` 同位置插入 40 行(`rows() == len() == Key::ALL.len()`)
- 守卫三条:中文渲染全非 ASCII、卡片 key 全覆盖(改回写死英文即红)、外观 key 逐条真翻过
- probe 加第二条取证路(`record_rendered`),`take()` 签名不动(M179 的守卫在 scope 外)
This commit is contained in:
1 parent
65e7ccc3bf
commit
c4c3c15285
14 files changed
+858
-184
No files matched your search
@@ -8,6 +8,8 @@ use iced::{Element, Length};
|
||||
|
||||
use unlucky_design::color::Role;
|
||||
use unlucky_design::spacing::Space;
|
||||
use unlucky_i18n::catalog::Key;
|
||||
use unlucky_i18n::Lang;
|
||||
use unlucky_presenter::prefs::BgFill;
|
||||
|
||||
use crate::app::components::inputs::{slider, text_field, Field, Slider};
|
||||
@@ -17,17 +19,32 @@ use crate::theme::Ui;
|
||||
use super::super::background::{self, BG_DIM_MAX};
|
||||
use super::super::state::State;
|
||||
use super::super::Change;
|
||||
use super::{choice, choice_row, label, note_line, slider_row};
|
||||
use super::{choice, choice_row, fixed2, label, note_line, slider_row, t, tr, tr_note};
|
||||
|
||||
/// 把 ④ 开关、⑤ 路径、⑥ 诊断、⑦ 填充、⑧ 暗化按视觉顺序推进 `rows`。
|
||||
pub(super) fn push<'a>(ui: &'a Ui, state: &'a State, rows: &mut Vec<Element<'a, Message>>) {
|
||||
pub(super) fn push<'a>(
|
||||
ui: &'a Ui,
|
||||
state: &'a State,
|
||||
lang: Lang,
|
||||
rows: &mut Vec<Element<'a, Message>>,
|
||||
) {
|
||||
// ④ 背景图开关
|
||||
rows.push(choice_row(
|
||||
ui,
|
||||
"Background image",
|
||||
t(Key::SettingsAppearanceBackgroundImage, lang),
|
||||
vec![
|
||||
choice(ui, "Off", !state.bg_enabled, Change::BgEnabled(false)),
|
||||
choice(ui, "On", state.bg_enabled, Change::BgEnabled(true)),
|
||||
choice(
|
||||
ui,
|
||||
t(Key::SettingsAppearanceOff, lang),
|
||||
!state.bg_enabled,
|
||||
Change::BgEnabled(false),
|
||||
),
|
||||
choice(
|
||||
ui,
|
||||
t(Key::SettingsAppearanceOn, lang),
|
||||
state.bg_enabled,
|
||||
Change::BgEnabled(true),
|
||||
),
|
||||
],
|
||||
));
|
||||
|
||||
@@ -35,57 +52,74 @@ pub(super) fn push<'a>(ui: &'a Ui, state: &'a State, rows: &mut Vec<Element<'a,
|
||||
let path_field: Element<'a, Message> = text_field(
|
||||
ui,
|
||||
Field::new(&state.bg_path)
|
||||
.label("Image path")
|
||||
.label(t(Key::SettingsAppearanceImagePath, lang))
|
||||
.placeholder("D:/Pictures/background.png"),
|
||||
|value| Message::Appearance(Change::BgImage(value)),
|
||||
);
|
||||
rows.push(
|
||||
column![label(ui, "Image path"), path_field]
|
||||
.spacing(ui.space(Space::X1))
|
||||
.width(Length::Fill)
|
||||
.into(),
|
||||
column![
|
||||
label(ui, t(Key::SettingsAppearanceImagePath, lang)),
|
||||
path_field
|
||||
]
|
||||
.spacing(ui.space(Space::X1))
|
||||
.width(Length::Fill)
|
||||
.into(),
|
||||
);
|
||||
|
||||
// ⑥ 诊断(读盘失败 / CPU 降级 / 配色回落)——**不许静默**,且必须在**首屏可见处**
|
||||
// (复审 r1 P2-3:文案落在折叠线以下等于没提示)。位置就在背景图那两行的紧下方。
|
||||
for note in state.diagnostics() {
|
||||
rows.push(note_line(ui, note, ui.color(Role::Error)));
|
||||
let text = tr_note(lang, note);
|
||||
rows.push(note_line(ui, &text, ui.color(Role::Error)));
|
||||
}
|
||||
if let Some(note) = state.backend_note() {
|
||||
rows.push(note_line(ui, note, ui.color(Role::OnSurfaceVariant)));
|
||||
if let Some(key) = state.backend_note() {
|
||||
rows.push(note_line(
|
||||
ui,
|
||||
t(key, lang),
|
||||
ui.color(Role::OnSurfaceVariant),
|
||||
));
|
||||
}
|
||||
if let Some(note) = state
|
||||
.image()
|
||||
.and_then(|image| background::small_tile_note(image, state.bg_fill))
|
||||
{
|
||||
rows.push(note_line(ui, ¬e, ui.color(Role::OnSurfaceVariant)));
|
||||
let text = tr_note(lang, ¬e);
|
||||
rows.push(note_line(ui, &text, ui.color(Role::OnSurfaceVariant)));
|
||||
}
|
||||
if let Some(note) = state.palette_note() {
|
||||
rows.push(note_line(ui, note, ui.color(Role::OnSurfaceVariant)));
|
||||
if let Some(key) = state.palette_note() {
|
||||
rows.push(note_line(
|
||||
ui,
|
||||
t(key, lang),
|
||||
ui.color(Role::OnSurfaceVariant),
|
||||
));
|
||||
}
|
||||
let resolved = format!("Colours: {}", state.palette_level());
|
||||
rows.push(note_line(ui, &resolved, ui.color(Role::OnSurfaceVariant)));
|
||||
let level = tr(
|
||||
lang,
|
||||
Key::SettingsAppearancePaletteLevel,
|
||||
&[("level", state.palette_level())],
|
||||
);
|
||||
rows.push(note_line(ui, &level, ui.color(Role::OnSurfaceVariant)));
|
||||
|
||||
// ⑦ 填充
|
||||
rows.push(choice_row(
|
||||
ui,
|
||||
"Fill",
|
||||
t(Key::SettingsAppearanceBgFill, lang),
|
||||
vec![
|
||||
choice(
|
||||
ui,
|
||||
"Cover",
|
||||
t(Key::SettingsAppearanceBgFillCover, lang),
|
||||
state.bg_fill == BgFill::Cover,
|
||||
Change::BgFill(BgFill::Cover),
|
||||
),
|
||||
choice(
|
||||
ui,
|
||||
"Contain",
|
||||
t(Key::SettingsAppearanceBgFillContain, lang),
|
||||
state.bg_fill == BgFill::Contain,
|
||||
Change::BgFill(BgFill::Contain),
|
||||
),
|
||||
choice(
|
||||
ui,
|
||||
"Tile",
|
||||
t(Key::SettingsAppearanceBgFillTile, lang),
|
||||
state.bg_fill == BgFill::Tile,
|
||||
Change::BgFill(BgFill::Tile),
|
||||
),
|
||||
@@ -95,10 +129,12 @@ pub(super) fn push<'a>(ui: &'a Ui, state: &'a State, rows: &mut Vec<Element<'a,
|
||||
// ⑧ 暗化
|
||||
rows.push(slider_row(
|
||||
ui,
|
||||
"Dim",
|
||||
t(Key::SettingsAppearanceBgDim, lang),
|
||||
format!("{:.0}%", state.bg_dim * 100.0),
|
||||
format!(
|
||||
"Blends the image toward the panel colour so text stays readable. Max {BG_DIM_MAX:.2}."
|
||||
tr(
|
||||
lang,
|
||||
Key::SettingsAppearanceBgDimHint,
|
||||
&[("max", &fixed2(BG_DIM_MAX))],
|
||||
),
|
||||
state.bg_dim > 0.0,
|
||||
slider(
|
||||
|
||||
Reference in new issue
Block a user