M92 只建地基、不接页面(页面接线是后续 mission,避免「先硬编码再全量重写」)。
新建的 crates/i18n 是**零依赖** crate:`cargo tree -p unlucky-i18n --edges normal`
只打印它自己,所以 iced 版、将来的别的壳、presenter 都能依赖它而不锁死渲染框架。
- lang:`Lang::{En, ZhCn}` + 可注入的 `LocaleSource`(`EnvLocale` 按 POSIX 优先级读
LC_ALL > LC_MESSAGES > LANG)。未知语种一律英文——把 ja/fr 猜成中文会连带触发中文字体
下载,比英文界面更糟。配置值(`ui.language` 的 zh_cn/en_us)走严格解析,locale 走宽松
解析,两条路刻意分开。**已知缺口**:Windows 上这三个变量通常都不存在,
`GetUserDefaultLocaleName` 属于 platform 的 FFI(后续 mission)。
- catalog:`Key` 枚举(拼错的 key = 编译错误,附 compile_fail 文档测试守着)
+ `catalog!` 宏「一行 = 一个 key 的全部语言」⇒ 内置两套目录缺译在结构上不可能发生。
缺译诊断(`Catalog::diagnose`)留给注入目录与回归守门:`get` 严格返回 None、
`text` 返回 ⟪missing⟫、`render` 返回 ⟪missing:KeyName⟫——**不回落**到另一种语言。
带变量的句子走 `{name}` 占位符,缺参时占位符原样留在文案里(可见,不静默变空)。
- font:`decide(lang, installed)` 是纯函数。英文环境恒 `NotNeeded`(D28 的零字体/零网络);
中文环境按候选族名单命中系统字体,扫不到就发 `NeedsDownload(Noto Sans SC)` 信号,
**本 crate 不联网**;`Fetcher` 是注入式接口,网络实现留给后续 mission。
URL/哈希显式留白(`Source::PendingPin`)——不编造 CDN 路径,猜错的地址会被后面所有人当事实用。
- bridge:文案边界规则全文(R1 不许拼句 / R2 core 中文串不进 UI / R3 未知串不许画原文)
+ `classify()` 示例契约:过渡表把已知漏到界面的中文串映射到 key,品牌专名显式放行,
其余一律 `Untranslated`(UI 只许显示兜底 key)。
- app-iced/fonts:新增 `fonts/cjk.rs` 适配层,把系统字面表喂给 `decide`;读不到字体库时给
`Unprobeable` 而不是「需下载」(否则会误触发一次 CDN 下载)。结论并入同一行启动日志:
`[font] … | lang=zh-CN locale=zh_CN.UTF-8 cjk=system:"Microsoft YaHei"`。
测试:26 条(i18n 22 + app-iced fonts/cjk 4),每条断言都写了「抓得住什么 / 抓不住什么」。
78 lines
3.8 KiB
TOML
78 lines
3.8 KiB
TOML
[package]
|
||
name = "unlucky-app-iced"
|
||
description = "Unlucky-Launcher 桌面壳(iced 0.14 重写版):M3 Expressive 骨架 / 令牌适配 / 截图通道"
|
||
version.workspace = true
|
||
edition.workspace = true
|
||
license.workspace = true
|
||
authors.workspace = true
|
||
repository.workspace = true
|
||
rust-version.workspace = true
|
||
publish.workspace = true
|
||
|
||
# 并存期(D26):Slint 版仍是 `crates/app` 的 `unlucky-launcher`,本 crate 出
|
||
# `unlucky-launcher-iced`。两个 package 在同一 target 目录产出同名 bin 会冲突,
|
||
# 所以**翻牌前不许改回 `unlucky-launcher`**(步骤见 SubAgentsTalk/app-iced-骨架与翻牌.md)。
|
||
[[bin]]
|
||
name = "unlucky-launcher-iced"
|
||
path = "src/main.rs"
|
||
|
||
[lib]
|
||
name = "unlucky_app_iced"
|
||
path = "src/lib.rs"
|
||
|
||
[dependencies]
|
||
# 令牌唯一真源(M61):颜色/排版/形状/间距/图标几何全部只从这里取。
|
||
unlucky-design = { path = "../design", version = "0.1" }
|
||
|
||
# M85:UI 框架无关的宿主层(DTO / 状态 reducer / host)。**只登记依赖,本 mission 不接线**——
|
||
# 页面用它的时机由后续 iced 页面 mission 决定(接线流程见 crates/presenter/src/lib.rs 的 crate 文档)。
|
||
# 与 Slint 版共用同一套 host 与状态语义,这是 D26「重写只换渲染」的落点。
|
||
unlucky-presenter = { path = "../presenter", version = "0.1" }
|
||
|
||
# UI 框架(D26 锁定 iced 0.14)。**不得依赖 slint**。
|
||
# 关掉默认 features 后必须显式给执行器(M60 踩坑 Q2:否则 `No futures executor has been enabled`),
|
||
# 这里给 `thread-pool`(iced 自己的默认执行器,不额外引 tokio 运行时)。
|
||
# `wgpu` 由本 crate 的 `gpu` feature 打开,于是「仅 CPU」体积基线用 `--no-default-features` 就能量到。
|
||
iced = { version = "=0.14.0", default-features = false, features = [
|
||
"tiny-skia",
|
||
"crisp",
|
||
"advanced",
|
||
"svg",
|
||
"thread-pool",
|
||
] }
|
||
|
||
# 截图落 PNG。只开 png 编码器,不要默认全套 codec(体积)。
|
||
image = { version = "0.25", default-features = false, features = ["png"] }
|
||
|
||
# M82:同一个二进制也带 CLI 子命令(`unlucky-launcher-iced instances list` …),
|
||
# 进 UI 之前分发,命中就把控制权交给 `unlucky_cli::run`。依赖方向 app-iced → cli →
|
||
# core/agent 不违反 core 零 UI 铁律(core 的依赖树里没有 cli)。零 UI 依赖的 `ull`
|
||
# 仍在 `crates/cli`,给没有图形库的机器用——两者不是重复品。
|
||
unlucky-cli = { path = "../cli", version = "0.1" }
|
||
|
||
# M92(D28):国际化地基(语言探测 / 消息目录 / 中文字体策略)。零依赖 crate——它拿不到 iced,
|
||
# 所以系统字体扫描留在这里(`src/fonts/cjk.rs`),本 crate 只把族名喂给它的纯函数。
|
||
unlucky-i18n = { path = "../i18n", version = "0.1" }
|
||
|
||
# X11 / Wayland 后端与 Linux 主题检测只在 Linux 上启用:macOS 没有 X11/Wayland(走 Metal +
|
||
# 系统外观),Windows 走 DX12,这三个 feature 在那边没有意义。同一个包在两处写 features 是
|
||
# **取并集**(Cargo 的 feature 解析是加法),所以 Linux 上拿到的仍是上面 5 个 + 这 3 个,
|
||
# Windows / macOS 只拿上面那 5 个(`cargo tree --target` 可复核)。
|
||
# 诚实边界:这**不**解决「iced 版至今没在 macOS 上编过」这件事——`iced_winit` 已把 `mundy`
|
||
# 放在 `cfg(target_os = "linux")` 段里,这三个 feature 在非 Linux 上本来就不拉依赖,这里只是
|
||
# 让本仓库的依赖图按平台自述清楚,不再把 Linux 专属能力写成全平台事实。
|
||
[target.'cfg(target_os = "linux")'.dependencies]
|
||
iced = { version = "=0.14.0", default-features = false, features = [
|
||
"x11",
|
||
"wayland",
|
||
"linux-theme-detection",
|
||
] }
|
||
|
||
[features]
|
||
default = ["gpu"]
|
||
# 硬件渲染后端(wgpu→Vulkan/DX12)。关闭后只剩 tiny-skia(CPU),用于体积基线与无 GPU 机器。
|
||
gpu = ["iced/wgpu"]
|
||
|
||
[lints]
|
||
workspace = true
|