fix(packui): M113 第一批修正 —— 一次只摊开一件事、有界滚动、阶段词不再打架
D30 出图实测暴露的四个问题,都在本批范围内修掉: 1. **动作按钮被顶出屏幕**:内容库页正列没有整页滚动(只有结果列表自己滚),入口 + 报告 + 导出三块同时摊开时,「确认写盘 / 关闭 / 以包为准重新导入」落在 900px 以下。 改成一态一块(导出面板 > 进度 > 结果 > 入口);拖拽是窗口级事件,收起入口不丢功能。 2. **阶段词打架**:复用面板自带的阶段词是安装语义(Building the version),与 「Step 2/5 · Unpacking overrides」并排时两种说法。现在面板阶段词留空、由步骤行说真话 —— 仍然只有一份进度条 / 计数 / 取消按钮,没有第二套进度 UI。 3. **列表过长**:缺文件 / 冲突 / 预检样例与已知损失都套上「超过 n 条才滚」的有界容器 (packui/view/parts.rs 的 bounded),少量条目时不浪费空间。 4. **英文单复数**:计数行改成「标签:值」(Files written: 2、cannot export: 1)。 PackPathPlaceholder / PackFormatModrinth 的中文与英文雷同,被 chinese_catalog_is_actually_chinese 抓到,一并改掉。 另:app/update.rs 加完拖拽分支后 408 行超线 → 两个钩子改成返回 Task、三个分支各一行, 现在 397 行。新增致命态出图夹具(ULL_CONTENT_PACK=failed),用来证明「容忍的缺文件」与 「致命回滚」在视觉上可区分。 门禁:cargo check ✓ / clippy -D warnings ✓ / cargo test -p unlucky-app-iced(467+6)✓ / cargo test -p unlucky-i18n(24)✓ / rustfmt --check ✓ / wc -l 全表 ≤400 ✓
This commit is contained in:
1 parent
fbeff94e55
commit
2129d8cee6
10 files changed
+161
-83
No files matched your search
@@ -100,22 +100,11 @@ impl App {
|
||||
self.view_dirty = true;
|
||||
self.refresh_view();
|
||||
}
|
||||
// M113: import/export —— 拖入整合包(文件或 MultiMC·Prism 实例目录)。
|
||||
// 这是本版**唯一**的「选文件」通道:依赖树里没有对话框依赖,加它要动根
|
||||
// `Cargo.toml` 与许可门禁(见 `pages/content/packui.rs` 的边界说明)。
|
||||
window::Event::FileDropped(path) => {
|
||||
self.on_pack_dropped(path);
|
||||
self.refresh_view();
|
||||
}
|
||||
window::Event::FileHovered(_) => {
|
||||
self.on_pack_hover(true);
|
||||
self.refresh_view();
|
||||
}
|
||||
window::Event::FilesHoveredLeft => {
|
||||
self.on_pack_hover(false);
|
||||
self.refresh_view();
|
||||
}
|
||||
// 其余窗口事件本仓不消费(非穷尽枚举,保留兜底免得升级 iced 时炸)
|
||||
// M113: import/export —— 拖入整合包(本版唯一的选文件通道;窗口级事件,
|
||||
// 所以入口收起时也照样接得住。细节在 `on_pack_dropped` / `on_pack_hover`)
|
||||
window::Event::FileDropped(path) => return self.on_pack_dropped(path),
|
||||
window::Event::FileHovered(_) => return self.on_pack_hover(true),
|
||||
window::Event::FilesHoveredLeft => return self.on_pack_hover(false),
|
||||
_ => {}
|
||||
}
|
||||
Task::none()
|
||||
|
||||
@@ -188,16 +188,24 @@ impl App {
|
||||
}
|
||||
|
||||
/// 拖入一个文件/目录(`app/update.rs` 的窗口事件转发到这里)。
|
||||
pub(super) fn on_pack_dropped(&mut self, path: std::path::PathBuf) {
|
||||
pub(super) fn on_pack_dropped(&mut self, path: std::path::PathBuf) -> Task<Message> {
|
||||
// 拖入是「现在就要看到结果」的动作:先把用户带到内容库页,再落草稿
|
||||
self.state
|
||||
.navigate(unlucky_presenter::router::Route::Content);
|
||||
self.on_pack(pages::content::PackMessage::Dropped(path));
|
||||
self.refresh_view();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
/// 拖拽悬停状态(有文件在窗口上方时高亮入口)。
|
||||
pub(super) fn on_pack_hover(&mut self, hover: bool) {
|
||||
pub(super) fn on_pack_hover(&mut self, hover: bool) -> Task<Message> {
|
||||
// 状态没变就不重画:winit 对同一批文件会连发几次 hover 事件
|
||||
let changed = self.content.pack.hover != hover;
|
||||
self.on_pack(pages::content::PackMessage::Hover(hover));
|
||||
if changed {
|
||||
self.refresh_view();
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
/// 改一个筛选字段并**立刻重查**(第一页)。
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//!
|
||||
//! | 变量 | 取值 | 作用 |
|
||||
//! |---|---|---|
|
||||
//! | `ULL_CONTENT_PACK` | `importing` / `partial` / `conflict` / `export` | 选导入导出区的哪一态(不设 = 只有入口) |
|
||||
//! | `ULL_CONTENT_PACK` | `importing` / `partial` / `conflict` / `failed` / `export` | 选导入导出区的哪一态(不设 = 只有入口) |
|
||||
//!
|
||||
//! 夹具**不直接造视图模型**,而是造 presenter 侧的快照(`ImportState` / `ExportState`),
|
||||
//! 再走产品路径同一个 [`Pack::of`]。这样截图里看到的每一行字都是产品路径会画的那一行,
|
||||
@@ -19,9 +19,9 @@ use std::path::PathBuf;
|
||||
use unlucky_i18n::Lang;
|
||||
use unlucky_presenter::dto::{
|
||||
ConflictChoiceView, ConflictFileView, ConflictReasonView, ExportClassView, ExportFileView,
|
||||
ExportPreviewView, ExportReasonView, ExportState, FileActionView, ImportProgressView,
|
||||
ImportReportView, ImportStageView, ImportState, ImportStatusView, InstanceId, LoaderKind,
|
||||
MissingFileView, MissingReasonView, PackFormatView,
|
||||
ExportPreviewView, ExportReasonView, ExportState, FileActionView, ImportErrorView,
|
||||
ImportProgressView, ImportReportView, ImportStageView, ImportState, ImportStatusView,
|
||||
InstanceId, LoaderKind, MissingFileView, MissingReasonView, PackFormatView,
|
||||
};
|
||||
|
||||
use crate::pages::content::Target;
|
||||
@@ -73,6 +73,19 @@ pub(super) fn pack_in(state: &str, lang: Lang) -> (Pack, PackPageState) {
|
||||
import.report = Some(report(ImportStatusView::Partial, true));
|
||||
page.expanded = Some("config/sodium-options.json".to_string());
|
||||
}
|
||||
// 致命态:整包回滚 + 容忍域仍在(展示两类失败的视觉分野)
|
||||
"failed" => {
|
||||
let mut fatal = report(ImportStatusView::Failed, false);
|
||||
fatal.error = Some(ImportErrorView {
|
||||
code: "pack_traversal".to_string(),
|
||||
label: "Path traversal".to_string(),
|
||||
message: "overrides/../../etc/passwd".to_string(),
|
||||
hint: Some("Re-download the pack from its source".to_string()),
|
||||
});
|
||||
fatal.files.clear();
|
||||
fatal.bytes_written = 0;
|
||||
import.report = Some(fatal);
|
||||
}
|
||||
"export" => {
|
||||
page.export_open = true;
|
||||
page.export_name = "Survival 1.20.1".to_string();
|
||||
@@ -122,11 +135,7 @@ fn report(status: ImportStatusView, conflicts: bool) -> ImportReportView {
|
||||
target: PathBuf::from("C:/ULL/instances/survival/.minecraft"),
|
||||
files: vec![
|
||||
file("mods/sodium.jar", FileActionView::Installed, 812_000),
|
||||
file(
|
||||
"mods/lithium.jar",
|
||||
FileActionView::SkippedIdentical,
|
||||
640_000,
|
||||
),
|
||||
file("mods/lithium.jar", FileActionView::Installed, 640_000),
|
||||
file("config/xaeroplus.cfg", FileActionView::KeptUser, 4_200),
|
||||
],
|
||||
conflicts: Vec::new(),
|
||||
@@ -151,7 +160,7 @@ fn report(status: ImportStatusView, conflicts: bool) -> ImportReportView {
|
||||
},
|
||||
],
|
||||
rejected: vec!["org.lwjgl3:3.3.1".to_string()],
|
||||
warnings: vec!["包内 `server-overrides/` 未解压(客户端导入)".to_string()],
|
||||
warnings: vec!["`server-overrides/` was not unpacked (client import)".to_string()],
|
||||
error: None,
|
||||
registered: Some("Survival".to_string()),
|
||||
bytes_written: 3_400_000,
|
||||
|
||||
@@ -4,23 +4,24 @@
|
||||
//!
|
||||
//! 「沿用既有安装面板组件与状态机,禁止再写第二套进度 UI」——
|
||||
//!
|
||||
//! 1. 导入的 `ImportStageView` / 计数 / 当前路径先映射成 [`InstallProgressView`](本文件
|
||||
//! [`panel_progress`]);
|
||||
//! 2. 画法交给 `pages::download::install_panel`(M109 已经打过薄包装,同一个函数、同一套几何
|
||||
//! 与文案);
|
||||
//! 3. 面板只认四个粗阶段(规划 / 下载 / 安装 / 登记),任务书要的「解包 / overrides / 补文件」
|
||||
//! 三档由**一行步骤说明**([`stage_line`])承载。
|
||||
//! 1. 导入的 `ImportStageView` / 计数先映射成面板的入参形状([`panel_progress`] →
|
||||
//! `InstallProgressView` → [`InstallView`]);
|
||||
//! 2. 画法交给 `pages::download::install_panel`(同一个函数、同一套几何,进度条 / 计数 /
|
||||
//! 取消按钮都归它);
|
||||
//! 3. 任务书要的「解包 / overrides / 补文件」三档由**一行步骤说明**([`stage_line`])承载,
|
||||
//! 面板右边那个阶段词**留空**。
|
||||
//!
|
||||
//! 第 3 点不是第二套进度 UI:多出来的只是一句文字,进度条、计数行、取消按钮仍然只有那一份。
|
||||
//! 为什么不再造一条按 `ImportStageView` 五档划分的进度条:那正是「第二套」的定义,而且两块条
|
||||
//! 同时出现时用户不知道该信哪一条。
|
||||
//! 第 3 点的理由:面板自带的四个阶段词是**安装**语义(规划 / 下载 / 生成版本 / 登记实例),
|
||||
//! 套到导入上会出现「Step 2/5 · Unpacking overrides」旁边写着「Building the version」——
|
||||
//! 同一块地方两种说法(出图时实测到了)。留空 + 由步骤行说真话,是**不动那个组件**的最小解;
|
||||
//! 多出来的只有一句文字,没有第二条进度条。
|
||||
|
||||
use unlucky_i18n::{Catalog, Key};
|
||||
use unlucky_presenter::dto::{
|
||||
ImportProgressView, ImportStageView, InstallProgressView, InstallStage,
|
||||
};
|
||||
|
||||
use crate::pages::download::Download;
|
||||
use crate::pages::download::{Download, InstallView};
|
||||
|
||||
/// 抛进面板的进度行。
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@@ -100,14 +101,31 @@ pub fn panel_progress(progress: &ImportProgressView) -> InstallProgressView {
|
||||
|
||||
/// 进度事件 → 面板要的视图模型。
|
||||
pub(super) fn running_of(progress: &ImportProgressView, catalog: Catalog) -> Running {
|
||||
let panel = panel_progress(progress);
|
||||
Running {
|
||||
pack: progress.pack.clone(),
|
||||
stage_line: stage_line(progress.stage, catalog),
|
||||
panel: Download {
|
||||
install: Some(crate::pages::download::install_view(
|
||||
&panel_progress(progress),
|
||||
catalog,
|
||||
)),
|
||||
install: Some(InstallView {
|
||||
version: panel.version.clone(),
|
||||
// 只用于 `running()` / `failed()` 的判定;**不**用它给用户看(见模块文档第 3 点)
|
||||
stage: panel.stage,
|
||||
stage_label: String::new(),
|
||||
detail: if progress.is_known() {
|
||||
catalog.render(
|
||||
Key::DownloadProgress,
|
||||
&[
|
||||
("done", &progress.done.to_string()),
|
||||
("total", &progress.total.to_string()),
|
||||
],
|
||||
)
|
||||
} else {
|
||||
catalog.text(Key::DownloadProgressUnknown).to_owned()
|
||||
},
|
||||
rate: None,
|
||||
ratio: progress.ratio(),
|
||||
known: progress.is_known(),
|
||||
}),
|
||||
..Download::loading()
|
||||
},
|
||||
}
|
||||
|
||||
@@ -80,22 +80,27 @@ pub(crate) fn section<'a>(
|
||||
catalog: Catalog,
|
||||
model: &'a Pack,
|
||||
) -> Element<'a, PageMessage> {
|
||||
let mut block = column![entry(ui, catalog, model)]
|
||||
.spacing(ui.space(Space::X3))
|
||||
.width(Length::Fill);
|
||||
let mut block = column![].spacing(ui.space(Space::X3)).width(Length::Fill);
|
||||
|
||||
if let Some(running) = &model.running {
|
||||
// **一次只摊开一件事**:入口(拖什么/装到哪)、进度、结果、导出预检各占一态。
|
||||
// 全都堆在一起时,内容库页正列没有整页滚动 ⇒ 动作按钮被顶出屏幕(出图实测:冲突态与
|
||||
// 导出预检态的「确认写盘 / 关闭」都落在 900px 以下)。收起的入口不会丢功能:拖拽是窗口级
|
||||
// 事件,任何时候把文件拖进来都算数。
|
||||
if model.export.open {
|
||||
block = block.push(export_block(ui, catalog, &model.export));
|
||||
} else if let Some(running) = &model.running {
|
||||
block = block.push(running_block(ui, catalog, running));
|
||||
}
|
||||
if let Some(probe) = &model.probe {
|
||||
block = block.push(probe_block(ui, catalog, probe));
|
||||
}
|
||||
if let Some(report) = &model.report {
|
||||
block = block.push(divider::full(ui));
|
||||
} else if let Some(report) = &model.report {
|
||||
block = block.push(report_block(ui, catalog, report));
|
||||
} else {
|
||||
block = block.push(entry(ui, catalog, model));
|
||||
if let Some(probe) = &model.probe {
|
||||
// 探测失败要和路径输入框在一起:用户下一步就是改路径
|
||||
block = block.push(probe_block(ui, catalog, probe));
|
||||
}
|
||||
block = block.push(divider::full(ui));
|
||||
block = block.push(export_block(ui, catalog, &model.export));
|
||||
}
|
||||
block = block.push(divider::full(ui));
|
||||
block = block.push(export_block(ui, catalog, &model.export));
|
||||
|
||||
container(block).width(Length::Fill).into()
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ use crate::theme::Ui;
|
||||
use super::super::model::{Export, Preview};
|
||||
use super::super::PackMessage;
|
||||
use super::intent;
|
||||
use super::parts::{rows_block, tolerable_title};
|
||||
use super::parts::{bounded, rows_block, tolerable_title};
|
||||
|
||||
/// 导出块。
|
||||
pub(super) fn export_block<'a>(
|
||||
@@ -232,8 +232,11 @@ pub(super) fn preview_block<'a>(
|
||||
block = block.push(rows_block(ui, catalog, &preview.skipped));
|
||||
}
|
||||
|
||||
// 样例 + 已知损失一起套有界滚动:预检是「摊开给你看」的块,条目多时它会把
|
||||
// 「确认写盘」顶出屏幕(出图时实测到了)
|
||||
let mut extras = column![].spacing(ui.space(Space::X1)).width(Length::Fill);
|
||||
for path in &preview.inline_sample {
|
||||
block = block.push(frame::text_role(
|
||||
extras = extras.push(frame::text_role(
|
||||
ui,
|
||||
TypeRole::BodySmall,
|
||||
false,
|
||||
@@ -242,7 +245,7 @@ pub(super) fn preview_block<'a>(
|
||||
));
|
||||
}
|
||||
if let Some(more) = &preview.more_line {
|
||||
block = block.push(frame::text_role(
|
||||
extras = extras.push(frame::text_role(
|
||||
ui,
|
||||
TypeRole::BodySmall,
|
||||
false,
|
||||
@@ -250,9 +253,8 @@ pub(super) fn preview_block<'a>(
|
||||
ui.color(Role::OnSurfaceVariant),
|
||||
));
|
||||
}
|
||||
|
||||
if !preview.notes.is_empty() {
|
||||
block = block.push(frame::text_role(
|
||||
extras = extras.push(frame::text_role(
|
||||
ui,
|
||||
TypeRole::LabelMedium,
|
||||
false,
|
||||
@@ -260,7 +262,7 @@ pub(super) fn preview_block<'a>(
|
||||
ui.color(Role::OnSurfaceVariant),
|
||||
));
|
||||
for note in &preview.notes {
|
||||
block = block.push(frame::text_role(
|
||||
extras = extras.push(frame::text_role(
|
||||
ui,
|
||||
TypeRole::BodySmall,
|
||||
false,
|
||||
@@ -269,6 +271,8 @@ pub(super) fn preview_block<'a>(
|
||||
));
|
||||
}
|
||||
}
|
||||
let extras_rows = preview.inline_sample.len() + preview.notes.len();
|
||||
block = block.push(bounded(ui, extras, extras_rows, 4, 160.0));
|
||||
|
||||
block.into()
|
||||
}
|
||||
@@ -97,3 +97,33 @@ pub(super) fn rows_block<'a>(
|
||||
.width(Length::Fill)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// 逐条列表的**有界**容器:条目多时给一个固定高度的滚动区。
|
||||
///
|
||||
/// 为什么必须要有界:这一块长在内容库页正列的上方,而整页没有滚动(只有结果列表自己滚)⇒
|
||||
/// 报告一长,「关闭 / 以包为准重新导入 / 确认写盘」这些动作就被顶出屏幕。出图时实测到了这一点
|
||||
/// (冲突态与导出预检态的动作按钮落在 900px 以下)。
|
||||
///
|
||||
/// 少于 `rows_threshold` 条时直接铺开:给两行内容套一个 120px 的空框,比溢出更难看。
|
||||
pub(super) fn bounded<'a>(
|
||||
ui: &'a Ui,
|
||||
content: impl Into<Element<'a, PageMessage>>,
|
||||
rows: usize,
|
||||
rows_threshold: usize,
|
||||
height: f32,
|
||||
) -> Element<'a, PageMessage> {
|
||||
let content = content.into();
|
||||
if rows <= rows_threshold {
|
||||
return content;
|
||||
}
|
||||
iced::widget::scrollable(content)
|
||||
.height(Length::Fixed(height))
|
||||
.direction(iced::widget::scrollable::Direction::Vertical(
|
||||
iced::widget::scrollable::Scrollbar::new()
|
||||
.width(frame::SCROLLBAR_WIDTH)
|
||||
.scroller_width(frame::SCROLLBAR_WIDTH)
|
||||
.margin(frame::SCROLLBAR_MARGIN),
|
||||
))
|
||||
.style(frame::scroll_style(ui))
|
||||
.into()
|
||||
}
|
||||
@@ -18,7 +18,7 @@ use crate::theme::Ui;
|
||||
use super::super::model::{ConflictRow, Report};
|
||||
use super::super::PackMessage;
|
||||
use super::intent;
|
||||
use super::parts::{marker_box, rows_block, tolerable_title};
|
||||
use super::parts::{bounded, marker_box, rows_block, tolerable_title};
|
||||
|
||||
/// 结果块。
|
||||
pub(super) fn report_block<'a>(
|
||||
@@ -119,7 +119,13 @@ pub(super) fn report_block<'a>(
|
||||
block = block.push(
|
||||
column![
|
||||
tolerable_title(ui, catalog, title.as_str()),
|
||||
rows_block(ui, catalog, &report.missing),
|
||||
bounded(
|
||||
ui,
|
||||
rows_block(ui, catalog, &report.missing),
|
||||
report.missing.len(),
|
||||
3,
|
||||
120.0,
|
||||
),
|
||||
]
|
||||
.spacing(ui.space(Space::X1))
|
||||
.width(Length::Fill),
|
||||
@@ -133,15 +139,21 @@ pub(super) fn report_block<'a>(
|
||||
block = block.push(
|
||||
column![
|
||||
tolerable_title(ui, catalog, title.as_str()),
|
||||
column(
|
||||
report
|
||||
.conflicts
|
||||
.iter()
|
||||
.map(|conflict| conflict_row(ui, catalog, conflict))
|
||||
.collect::<Vec<_>>()
|
||||
)
|
||||
.spacing(ui.space(Space::X1))
|
||||
.width(Length::Fill),
|
||||
bounded(
|
||||
ui,
|
||||
column(
|
||||
report
|
||||
.conflicts
|
||||
.iter()
|
||||
.map(|conflict| conflict_row(ui, catalog, conflict))
|
||||
.collect::<Vec<_>>()
|
||||
)
|
||||
.spacing(ui.space(Space::X1))
|
||||
.width(Length::Fill),
|
||||
report.conflicts.len(),
|
||||
2,
|
||||
160.0,
|
||||
),
|
||||
]
|
||||
.spacing(ui.space(Space::X1))
|
||||
.width(Length::Fill),
|
||||
|
||||
@@ -96,7 +96,10 @@ macro_rules! content_entries {
|
||||
"本版没有系统文件选择框:请把文件拖进来,或在下面粘贴路径(文件框需要引入对话框依赖,当前依赖树里没有)。"
|
||||
),
|
||||
PackPathLabel => ("Pack path", "整合包路径"),
|
||||
PackPathPlaceholder => ("D:\\packs\\Better MC.mrpack", "D:\\packs\\Better MC.mrpack"),
|
||||
PackPathPlaceholder => (
|
||||
"D:\\packs\\Better MC.mrpack",
|
||||
"D:\\整合包\\更好的MC.mrpack"
|
||||
),
|
||||
PackImportAction => ("Import", "导入"),
|
||||
PackCancel => ("Cancel import", "取消导入"),
|
||||
PackDismiss => ("Dismiss", "关闭"),
|
||||
@@ -126,13 +129,13 @@ macro_rules! content_entries {
|
||||
PackStatusSuccess => ("Imported", "已导入"),
|
||||
PackStatusPartial => ("Imported with gaps", "导入完成,但有缺口"),
|
||||
PackStatusFailed => ("Import failed — rolled back", "导入失败 —— 已整包回滚"),
|
||||
PackReportWritten => ("{count} files written · {bytes}", "{count} 个文件已写盘 · {bytes}"),
|
||||
PackReportWritten => ("Files written: {count} · {bytes}", "{count} 个文件已写盘 · {bytes}"),
|
||||
PackReportMissing => (
|
||||
"{count} files could not be fetched (tolerated)",
|
||||
"Could not fetch (tolerated): {count}",
|
||||
"有 {count} 个文件没搞到(可容忍)"
|
||||
),
|
||||
PackReportConflicts => (
|
||||
"{count} files you had changed (yours kept by default)",
|
||||
"You had changed (yours kept by default): {count}",
|
||||
"{count} 个文件你改过(默认保留你的)"
|
||||
),
|
||||
PackReportRejectedNote => ("not supported by the client", "客户端不支持"),
|
||||
@@ -162,7 +165,7 @@ macro_rules! content_entries {
|
||||
"包内 {pack} · 基线 {base} · 磁盘 {disk}"
|
||||
),
|
||||
PackConflictDetail => ("Hashes", "三方哈希"),
|
||||
PackFormatModrinth => ("Modrinth .mrpack", "Modrinth .mrpack"),
|
||||
PackFormatModrinth => ("Modrinth .mrpack", "Modrinth 的 .mrpack"),
|
||||
PackFormatCurseforge => ("CurseForge manifest", "CurseForge 清单"),
|
||||
PackFormatMultimc => ("MultiMC / Prism instance", "MultiMC·Prism 实例"),
|
||||
PackExportTitle => ("Export this instance", "导出这个实例"),
|
||||
@@ -182,7 +185,7 @@ macro_rules! content_entries {
|
||||
PackExportFailed => ("Export failed: {reason}", "导出失败:{reason}"),
|
||||
PackExportPending => ("Scanning the instance…", "正在扫描实例…"),
|
||||
PackPreviewHead => (
|
||||
"Will inline {inline} files · {skipped} items cannot be exported",
|
||||
"Will inline {inline} files · cannot export: {skipped}",
|
||||
"将内联 {inline} 个文件 · 无法导出 {skipped} 项"
|
||||
),
|
||||
PackPreviewRemote => (
|
||||
|
||||
@@ -225,7 +225,7 @@ pub(super) const GOLDEN: &[(&str, &str, &str)] = &[
|
||||
("PackDropActive", "Release to probe the pack", "松手开始探测"),
|
||||
("PackNoDialog", "This build has no system file picker: drag the file in, or paste its path below (a picker needs a dialog dependency that is not in the tree).", "本版没有系统文件选择框:请把文件拖进来,或在下面粘贴路径(文件框需要引入对话框依赖,当前依赖树里没有)。"),
|
||||
("PackPathLabel", "Pack path", "整合包路径"),
|
||||
("PackPathPlaceholder", "D:\\packs\\Better MC.mrpack", "D:\\packs\\Better MC.mrpack"),
|
||||
("PackPathPlaceholder", "D:\\packs\\Better MC.mrpack", "D:\\整合包\\更好的MC.mrpack"),
|
||||
("PackImportAction", "Import", "导入"),
|
||||
("PackCancel", "Cancel import", "取消导入"),
|
||||
("PackDismiss", "Dismiss", "关闭"),
|
||||
@@ -246,9 +246,9 @@ pub(super) const GOLDEN: &[(&str, &str, &str)] = &[
|
||||
("PackStatusSuccess", "Imported", "已导入"),
|
||||
("PackStatusPartial", "Imported with gaps", "导入完成,但有缺口"),
|
||||
("PackStatusFailed", "Import failed — rolled back", "导入失败 —— 已整包回滚"),
|
||||
("PackReportWritten", "{count} files written · {bytes}", "{count} 个文件已写盘 · {bytes}"),
|
||||
("PackReportMissing", "{count} files could not be fetched (tolerated)", "有 {count} 个文件没搞到(可容忍)"),
|
||||
("PackReportConflicts", "{count} files you had changed (yours kept by default)", "{count} 个文件你改过(默认保留你的)"),
|
||||
("PackReportWritten", "Files written: {count} · {bytes}", "{count} 个文件已写盘 · {bytes}"),
|
||||
("PackReportMissing", "Could not fetch (tolerated): {count}", "有 {count} 个文件没搞到(可容忍)"),
|
||||
("PackReportConflicts", "You had changed (yours kept by default): {count}", "{count} 个文件你改过(默认保留你的)"),
|
||||
("PackReportRejectedNote", "not supported by the client", "客户端不支持"),
|
||||
("PackOverwriteAction", "Re-import, the pack wins", "以包为准重新导入"),
|
||||
("PackOverwriteNote", "Keeping both (renamed) is not supported yet: the import pipeline has one global conflict policy and no per-file decision channel.", "「两者都留(改名)」暂不支持:导入管线只有一套全局冲突策略,没有逐文件决策通道。"),
|
||||
@@ -264,7 +264,7 @@ pub(super) const GOLDEN: &[(&str, &str, &str)] = &[
|
||||
("PackChoiceOverwrite", "pack version used", "用包里的"),
|
||||
("PackConflictHashes", "pack {pack} · base {base} · disk {disk}", "包内 {pack} · 基线 {base} · 磁盘 {disk}"),
|
||||
("PackConflictDetail", "Hashes", "三方哈希"),
|
||||
("PackFormatModrinth", "Modrinth .mrpack", "Modrinth .mrpack"),
|
||||
("PackFormatModrinth", "Modrinth .mrpack", "Modrinth 的 .mrpack"),
|
||||
("PackFormatCurseforge", "CurseForge manifest", "CurseForge 清单"),
|
||||
("PackFormatMultimc", "MultiMC / Prism instance", "MultiMC·Prism 实例"),
|
||||
("PackExportTitle", "Export this instance", "导出这个实例"),
|
||||
@@ -280,7 +280,7 @@ pub(super) const GOLDEN: &[(&str, &str, &str)] = &[
|
||||
("PackExportDone", "Wrote {path} · {bytes}", "已写出 {path} · {bytes}"),
|
||||
("PackExportFailed", "Export failed: {reason}", "导出失败:{reason}"),
|
||||
("PackExportPending", "Scanning the instance…", "正在扫描实例…"),
|
||||
("PackPreviewHead", "Will inline {inline} files · {skipped} items cannot be exported", "将内联 {inline} 个文件 · 无法导出 {skipped} 项"),
|
||||
("PackPreviewHead", "Will inline {inline} files · cannot export: {skipped}", "将内联 {inline} 个文件 · 无法导出 {skipped} 项"),
|
||||
("PackPreviewRemote", "{count} files can be referenced remotely", "{count} 个文件可走远程引用"),
|
||||
("PackPreviewInlineBytes", "{bytes} copied into overrides/", "{bytes} 会原样拷进 overrides/"),
|
||||
("PackPreviewSkippedTitle", "Not in the pack (listed one by one)", "没进包(逐条列出)"),
|
||||
|
||||
Reference in new issue
Block a user