Counts read in the singular for one thing; parts build two-count messages (R2.11)

This commit is contained in:
ZacharyZhang-NY committed 2026-10-09 03:07:13 -04:00
1 parent d4c5f90c87
commit 6f90a7dc53
22 files changed
+130 -49

No files matched your search

+9 -8
View File
@@ -24,17 +24,18 @@ impl Docs {
let Some(counts) = self.active_tab().and_then(|tab| tab.extra.counts) else {
return status.when_some(zoom, |status, zoom| status.right(zoom));
};
let (words, characters) = (counts.words.to_string(), counts.characters.to_string());
let count = |key, n: u64| ely_ui::i18n::counted(cx, key, n, &[("n", &n.to_string())]);
let label = match counts.selected_words {
0 => Self::text(
cx,
"doc.count.words",
&[("words", &words), ("characters", &characters)],
),
selected => Self::text(
0 => {
let words = count("doc.count.word", counts.words);
let characters = count("doc.count.character", counts.characters);
Self::text(cx, "doc.count.words", &[("words", &words), ("characters", &characters)])
}
selected => ely_ui::i18n::counted(
cx,
"doc.count.selected",
&[("selected", &selected.to_string()), ("words", &words)],
counts.words,
&[("selected", &selected.to_string()), ("words", &counts.words.to_string())],
),
};
status.right(StatusBarItem::new("doc-count").label(label)).when_some(zoom, |status, zoom| status.right(zoom))
+2 -3
View File
@@ -260,9 +260,8 @@ impl Docs {
let folder = folder.display().to_string();
let text = match written {
Ok(count) => {
let count = count.to_string();
let text =
Docs::text(cx, "doc.merge.done", &[("n", &count), ("folder", &folder)]);
let n = count.to_string();
let text = ely_ui::i18n::counted(cx, "doc.merge.done", count as u64, &[("n", &n), ("folder", &folder)]);
return docs.toast(text, Severity::Success, cx);
}
Err((n, error)) => Docs::text(
+2 -3
View File
@@ -183,7 +183,7 @@ impl Viewer {
written.map(|()| targets.len())
},
move |viewer, done, _, cx| match done {
Ok(count) => viewer.toast_output(Self::text(cx, "pdf.split.done", &[("count", &count.to_string())]), opened.clone(), cx),
Ok(count) => viewer.toast_output(ely_ui::i18n::counted(cx, "pdf.split.done", count as u64, &[("count", &count.to_string())]), opened.clone(), cx),
Err(error) => viewer.failed_write(&stem, &error, cx),
},
cx,
@@ -205,8 +205,7 @@ impl Viewer {
};
let card = match self.ask.as_ref()? {
Ask::Crop { pages, margins, .. } => {
let count = pages.len().to_string();
let title = Self::text(cx, "pdf.crop.title", &[("count", &count)]);
let title = ely_ui::i18n::counted(cx, "pdf.crop.title", pages.len() as u64, &[("count", &pages.len().to_string())]);
let sides = ["top", "right", "bottom", "left"];
let rows = sides.iter().enumerate().fold(DescriptionList::new(), |rows, (at, side)| {
let name = label(&format!("pdf.crop.{side}"));
+1 -1
View File
@@ -161,7 +161,7 @@ impl Viewer {
cx.notify();
let pages: Vec<(usize, Vec<OcrLine>)> = run.read.into_iter().filter(|(_, lines)| replace || !lines.is_empty()).collect();
let (read, skipped) = (pages.len().to_string(), run.skipped.to_string());
let summary = Self::text(cx, "pdf.ocr.done", &[("read", &read), ("skipped", &skipped)]);
let summary = ely_ui::i18n::counted(cx, "pdf.ocr.done", pages.len() as u64, &[("read", &read), ("skipped", &skipped)]);
let Some(view) = self.tab(tab).map(|tab| tab.view.clone()).filter(|_| !pages.is_empty()) else {
return self.toast(summary, Severity::Info, cx);
};
+1 -1
View File
@@ -177,7 +177,7 @@ impl Viewer {
},
move |viewer, done, _, cx| match done {
Ok(count) => {
let text = Self::text(cx, "pdf.export.images_done", &[("count", &count.to_string())]);
let text = ely_ui::i18n::counted(cx, "pdf.export.images_done", count as u64, &[("count", &count.to_string())]);
match folder.clone() {
Some(folder) => viewer.toast_output(text, folder, cx),
None => viewer.toast(text, Severity::Success, cx),
+3 -3
View File
@@ -185,7 +185,7 @@ impl Viewer {
},
move |viewer, done, _, cx| match done {
Ok(0) => viewer.toast_output(Self::text(cx, "pdf.clean.done", &[("name", &shown)]), opened.clone(), cx),
Ok(n) => viewer.toast_output(Self::text(cx, "pdf.redact.done", &[("name", &shown), ("count", &n.to_string())]), opened.clone(), cx),
Ok(n) => viewer.toast_output(ely_ui::i18n::counted(cx, "pdf.redact.done", n as u64, &[("name", &shown), ("count", &n.to_string())]), opened.clone(), cx),
Err(error) => viewer.failed(&error, cx),
},
cx,
@@ -200,8 +200,8 @@ impl Viewer {
let (title, body) = match removal {
Removal::Clean { reach, what, .. } => ("pdf.clean.title", self.clean_rows(reach, *what, &this, cx)),
Removal::Redact { regions, .. } => {
let count = regions.len().to_string();
("pdf.redact.title", div().child(Self::text(cx, "pdf.redact.count", &[("count", &count)])).into_any_element())
let count = ely_ui::i18n::counted(cx, "pdf.redact.count", regions.len() as u64, &[("count", &regions.len().to_string())]);
("pdf.redact.title", div().child(count).into_any_element())
}
};
let title = Self::text(cx, title, &[("name", &name)]);
+2 -2
View File
@@ -292,8 +292,8 @@ impl Deck {
},
move |deck, written, _, cx| match written {
Ok(count) => {
let count = count.to_string();
let text = Deck::text(cx, "show.output.pictures_done", &[("n", &count), ("folder", &shown)]);
let n = count.to_string();
let text = ely_ui::i18n::counted(cx, "show.output.pictures_done", count as u64, &[("n", &n), ("folder", &shown)]);
deck.toast_output(text, opened.clone(), cx);
}
Err(error) if error.kind() == io::ErrorKind::AlreadyExists => {
+1 -1
View File
@@ -311,7 +311,7 @@ impl Book {
move |book, picked, _, window, cx| {
let (c1, _, c2, _) = picked.area.expect("a data area");
if c1 != c2 {
return book.warn_key("table.columns.one", cx);
return book.warn_key("table.columns.same", cx);
}
let other = cx.new(|cx| TextInput::new(window, cx));
book.dialog = Some(Dialog::Columns {
+6 -10
View File
@@ -114,19 +114,15 @@ pub(crate) fn delete(
let mut detail = if references.formulas + references.names == 0 {
Book::text(cx, "table.delete.alone", &[])
} else {
Book::text(
cx,
"table.delete.refs",
&[
("formulas", &references.formulas.to_string()),
("first", &references.first),
("names", &references.names.to_string()),
],
)
let count = |key, n: u64| ely_ui::i18n::counted(cx, key, n, &[("n", &n.to_string())]);
let formulas = count("table.delete.formulas", references.formulas);
let names = count("table.delete.names", references.names);
let args = [("formulas", formulas.as_ref()), ("first", &references.first), ("names", &names)];
Book::text(cx, "table.delete.refs", &args)
};
if references.dynamic > 0 {
let count = references.dynamic.to_string();
let dynamic = Book::text(cx, "table.delete.dynamic", &[("count", &count)]);
let dynamic = ely_ui::i18n::counted(cx, "table.delete.dynamic", references.dynamic, &[("count", &count)]);
detail = format!("{detail} {dynamic}").into();
}
let label = Book::text(cx, "table.delete.go", &[]);
+2 -1
View File
@@ -95,9 +95,10 @@ impl Tree {
Ask::Force { repo, plan } => {
let lost = match plan.lost.len() {
0 => label("tree.force.nothing"),
n => text(
n => ely_ui::i18n::counted(
cx,
"tree.force.lost",
n as u64,
&[("n", &n.to_string()), ("commits", &plan.lost.join("\n"))],
),
};
+2 -2
View File
@@ -101,8 +101,8 @@ impl Tree {
};
let lines = (!shown.picked.is_empty() && self.partial(shown)).then(|| {
let this = this.clone();
let n = shown.picked.len().to_string();
Button::new("tree-lines", text(cx, key, &[("n", &n)]))
let n = shown.picked.len();
Button::new("tree-lines", ely_ui::i18n::counted(cx, key, n as u64, &[("n", &n.to_string())]))
.variant(ButtonVariant::Primary)
.size(ControlSize::Sm)
.on_click(move |_, _, cx| {
+2 -1
View File
@@ -205,9 +205,10 @@ impl Tree {
let short = |oid: &str| oid[..oid.len().min(7)].to_string();
let left = match plan.left.len() {
0 => label("tree.move.nothing"),
n => text(
n => ely_ui::i18n::counted(
cx,
"tree.move.left",
n as u64,
&[("n", &n.to_string()), ("commits", &plan.left.join("\n"))],
),
};
+1 -1
View File
@@ -213,7 +213,7 @@ impl Tree {
0 => (IconName::CircleCheck, text(cx, "tree.clean", &[])),
n => (
IconName::GitBranch,
text(cx, "tree.changed", &[("n", &n.to_string())]),
ely_ui::i18n::counted(cx, "tree.changed", n as u64, &[("n", &n.to_string())]),
),
};
EmptyState::new(("tree-summary", opened.id), icon, title).into_any_element()
+44 -6
View File
@@ -134,6 +134,16 @@ pub fn install(cx: &mut App) {
let tag = locale_tag(cx);
let locale = resolve(&tag);
log::info!("i18n: locale {tag} -> {locale}");
let (en, zh) = catalogs();
cx.set_global(
I18n::new(locale)
.catalog("en-US", &en)
.catalog("zh-CN", &zh),
);
}
/// The English and Chinese catalogs, every module's messages.
fn catalogs() -> (Vec<(&'static str, &'static str)>, Vec<(&'static str, &'static str)>) {
let en: Vec<_> = EN
.iter()
.chain(office::EN)
@@ -182,11 +192,7 @@ pub fn install(cx: &mut App) {
.chain(settings::ZH_CN)
.copied()
.collect();
cx.set_global(
I18n::new(locale)
.catalog("en-US", &en)
.catalog("zh-CN", &zh),
);
(en, zh)
}
/// `ELY_LOCALE`, then the language setting, then the system's.
@@ -203,9 +209,41 @@ pub fn text(cx: &App, key: &str, args: &[(&str, &str)]) -> SharedString {
cx.global::<I18n>().text(key, args)
}
/// The message for `n` things: `key.one` when one, else `key`.
pub fn counted(cx: &App, key: &str, n: u64, args: &[(&str, &str)]) -> SharedString {
text(cx, &count_key(key, n), args)
}
fn count_key(key: &str, n: u64) -> String {
match n {
1 => format!("{key}.one"),
_ => key.to_string(),
}
}
#[cfg(test)]
mod tests {
use super::resolve;
use super::{catalogs, count_key, resolve};
use std::collections::BTreeSet;
#[test]
fn one_thing_takes_the_singular() {
assert_eq!(count_key("tree.changed", 1), "tree.changed.one");
for n in [0, 2, 21] {
assert_eq!(count_key("tree.changed", n), "tree.changed", "{n}");
}
}
#[test]
fn both_catalogs_hold_the_same_keys_and_singulars() {
let (en, zh) = catalogs();
let keys = |list: &[(&str, &str)]| list.iter().map(|(key, _)| key.to_string()).collect::<BTreeSet<_>>();
let (en, zh) = (keys(&en), keys(&zh));
assert_eq!(en.symmetric_difference(&zh).collect::<Vec<_>>(), Vec::<&String>::new());
for key in en.iter().filter_map(|key| key.strip_suffix(".one")) {
assert!(en.contains(key), "{key}.one has no plural");
}
}
#[test]
fn zh_variants_pick_zh_cn_others_pick_en() {
+2 -2
View File
@@ -70,7 +70,7 @@ pub(super) const EN: &[(&str, &str)] = &[
("table.columns.space", "Space"),
("table.columns.other", "Other"),
("table.columns.go", "Split"),
("table.columns.one", "Select cells in one column."),
("table.columns.same", "Select cells in one column."),
("table.filter.title", "Column {column}"),
("table.filter.up", "Sort A to Z"),
("table.filter.down", "Sort Z to A"),
@@ -230,7 +230,7 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
("table.columns.space", "空格"),
("table.columns.other", "其他"),
("table.columns.go", "分列"),
("table.columns.one", "请选同一列中的单元格。"),
("table.columns.same", "请选同一列中的单元格。"),
("table.filter.title", "{column} 列"),
("table.filter.up", "升序排序"),
("table.filter.down", "降序排序"),
+10
View File
@@ -36,6 +36,7 @@ pub(super) const EN: &[(&str, &str)] = &[
("pdf.side.marks", "Bookmarks"),
("pdf.page.label", "Page {n}"),
("pdf.crop.title", "Crop {count} pages"),
("pdf.crop.title.one", "Crop 1 page"),
("pdf.crop.top", "Top"),
("pdf.crop.right", "Right"),
("pdf.crop.bottom", "Bottom"),
@@ -45,6 +46,7 @@ pub(super) const EN: &[(&str, &str)] = &[
("pdf.split.every", "Pages per file"),
("pdf.split.go", "Choose Folder…"),
("pdf.split.done", "{count} files written"),
("pdf.split.done.one", "1 file written"),
("pdf.extract.taken", "{name} is open; choose another name"),
("pdf.extract.done", "Pages written to {name}"),
("pdf.font.original", "The document's font"),
@@ -167,6 +169,7 @@ pub(super) const EN: &[(&str, &str)] = &[
"pdf.ocr.done",
"Recognized {read} pages; skipped {skipped}.",
),
("pdf.ocr.done.one", "Recognized 1 page; skipped {skipped}."),
("pdf.mark.add", "Add Bookmark"),
("pdf.mark.rename", "Rename Bookmark"),
("pdf.mark.delete", "Delete Bookmark"),
@@ -195,11 +198,13 @@ pub(super) const EN: &[(&str, &str)] = &[
"pdf.redact.count",
"{count} marked regions are removed for good.",
),
("pdf.redact.count.one", "1 marked region is removed for good."),
("pdf.redact.tail", "redacted"),
(
"pdf.redact.done",
"Saved {name}: {count} regions removed and checked.",
),
("pdf.redact.done.one", "Saved {name}: 1 region removed and checked."),
("pdf.clean.open", "Clean Document…"),
("pdf.clean.title", "Clean {name}"),
("pdf.clean.meta", "Properties and metadata ({count})"),
@@ -254,6 +259,7 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
("pdf.side.marks", "书签"),
("pdf.page.label", "第 {n} 页"),
("pdf.crop.title", "裁剪 {count} 页"),
("pdf.crop.title.one", "裁剪 1 页"),
("pdf.crop.top", "上"),
("pdf.crop.right", "右"),
("pdf.crop.bottom", "下"),
@@ -263,6 +269,7 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
("pdf.split.every", "每个文件的页数"),
("pdf.split.go", "选择文件夹…"),
("pdf.split.done", "已写入 {count} 个文件"),
("pdf.split.done.one", "已写入 1 个文件"),
("pdf.extract.taken", "{name} 已打开,请换一个名称"),
("pdf.extract.done", "页面已写入 {name}"),
("pdf.font.original", "文档自带字体"),
@@ -370,6 +377,7 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
("pdf.ocr.replace", "重新识别,替换 Ely 此前的文字层"),
("pdf.ocr.reading", "正在识别第 {n} 页,共 {count} 页"),
("pdf.ocr.done", "识别了 {read} 页,跳过 {skipped} 页。"),
("pdf.ocr.done.one", "识别了 1 页,跳过 {skipped} 页。"),
("pdf.mark.add", "添加书签"),
("pdf.mark.rename", "重命名书签"),
("pdf.mark.delete", "删除书签"),
@@ -392,11 +400,13 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
("pdf.redact.title", "删除 {name} 中标记的内容"),
("pdf.redact.none", "请先标记要删除的文字或区域。"),
("pdf.redact.count", "将彻底删除 {count} 处标记。"),
("pdf.redact.count.one", "将彻底删除 1 处标记。"),
("pdf.redact.tail", "已删除"),
(
"pdf.redact.done",
"已保存 {name}:删除并核对了 {count} 处。",
),
("pdf.redact.done.one", "已保存 {name}:删除并核对了 1 处。"),
("pdf.clean.open", "清理文档…"),
("pdf.clean.title", "清理 {name}"),
("pdf.clean.meta", "属性与元数据({count})"),
+2
View File
@@ -44,6 +44,7 @@ pub(super) const EN: &[(&str, &str)] = &[
"show.output.pictures_done",
"Wrote {n} pictures to {folder}",
),
("show.output.pictures_done.one", "Wrote 1 picture to {folder}"),
("show.output.failed", "Output failed: {error}"),
("show.check.menu", "Check Presentation…"),
("show.check.title", "Presentation Check"),
@@ -97,6 +98,7 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
("show.output.taken", "{name} 已存在,未写入任何文件"),
("show.output.done", "已导出 {name}"),
("show.output.pictures_done", "已写入 {n} 张图片到 {folder}"),
("show.output.pictures_done.one", "已写入 1 张图片到 {folder}"),
("show.output.failed", "输出失败:{error}"),
("show.check.menu", "检查演示…"),
("show.check.title", "演示检查"),
+2
View File
@@ -126,6 +126,7 @@ pub(super) const EN: &[(&str, &str)] = &[
("pdf.export.tail", "optimized"),
("pdf.export.done", "Saved {name}."),
("pdf.export.images_done", "Saved {count} page images."),
("pdf.export.images_done.one", "Saved 1 page image."),
(
"pdf.export.optimized_done",
"Saved {name}: {before} → {after}.",
@@ -246,6 +247,7 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
("pdf.export.tail", "已优化"),
("pdf.export.done", "已保存 {name}。"),
("pdf.export.images_done", "已保存 {count} 张页面图片。"),
("pdf.export.images_done.one", "已保存 1 张页面图片。"),
(
"pdf.export.optimized_done",
"已保存 {name}:{before} → {after}。",
+12 -2
View File
@@ -33,12 +33,17 @@ pub(super) const EN: &[(&str, &str)] = &[
),
(
"table.delete.refs",
"{formulas} formulas on other sheets, first {first}, and {names} named ranges refer to it; they will show #REF!.",
"{formulas} on other sheets, first {first}, and {names} refer to it; they will show #REF!.",
),
("table.delete.formulas", "{n} formulas"),
("table.delete.formulas.one", "1 formula"),
("table.delete.names", "{n} named ranges"),
("table.delete.names.one", "1 named range"),
(
"table.delete.dynamic",
"{count} formulas or names use INDIRECT; what they point to is known only when they run, so they may break too.",
),
("table.delete.dynamic.one", "1 formula or name uses INDIRECT; what it points to is known only when it runs, so it may break too."),
("table.delete.go", "Delete"),
("table.cells.rows_above", "Insert Rows Above"),
("table.cells.rows_below", "Insert Rows Below"),
@@ -119,12 +124,17 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
),
(
"table.delete.refs",
"其他工作表上有 {formulas} 个公式(第一个在 {first})和 {names} 个命名区域引用它;删除后它们显示 #REF!。",
"其他工作表上有 {formulas}(第一个在 {first})和 {names}引用它;删除后它们显示 #REF!。",
),
("table.delete.formulas", "{n} 个公式"),
("table.delete.formulas.one", "1 个公式"),
("table.delete.names", "{n} 个命名区域"),
("table.delete.names.one", "1 个命名区域"),
(
"table.delete.dynamic",
"另有 {count} 个公式或名称用 INDIRECT,指向何处要运行时才知道,删除后也可能出错。",
),
("table.delete.dynamic.one", "另有 1 个公式或名称用 INDIRECT,指向何处要运行时才知道,删除后也可能出错。"),
("table.delete.go", "删除"),
("table.cells.rows_above", "在上方插入行"),
("table.cells.rows_below", "在下方插入行"),
+14 -2
View File
@@ -2,8 +2,13 @@
pub(super) const EN: &[(&str, &str)] = &[
("menu.tools", "Tools"),
("doc.count.words", "{words} words, {characters} characters"),
("doc.count.words", "{words}, {characters}"),
("doc.count.selected", "{selected} of {words} words"),
("doc.count.selected.one", "{selected} of 1 word"),
("doc.count.word", "{n} words"),
("doc.count.word.one", "1 word"),
("doc.count.character", "{n} characters"),
("doc.count.character.one", "1 character"),
("office.find.open", "Find and Replace"),
("office.find.stale", "Edited. Enter counts again."),
("doc.spell.ignore_all", "Ignore All"),
@@ -50,6 +55,7 @@ pub(super) const EN: &[(&str, &str)] = &[
("doc.merge.unreadable", "{name} cannot be read: {error}"),
("doc.merge.exists", "{name} exists. Nothing was written."),
("doc.merge.done", "Wrote {n} files to {folder}"),
("doc.merge.done.one", "Wrote 1 file to {folder}"),
(
"doc.merge.failed",
"The merge stopped at record {n}: {error}",
@@ -58,8 +64,13 @@ pub(super) const EN: &[(&str, &str)] = &[
pub(super) const ZH_CN: &[(&str, &str)] = &[
("menu.tools", "工具"),
("doc.count.words", "{words} 字,{characters} 字符"),
("doc.count.words", "{words},{characters}"),
("doc.count.selected", "已选 {selected} / {words} 字"),
("doc.count.selected.one", "已选 {selected} / 1 字"),
("doc.count.word", "{n} 字"),
("doc.count.word.one", "1 字"),
("doc.count.character", "{n} 字符"),
("doc.count.character.one", "1 字符"),
("office.find.open", "查找和替换"),
("office.find.stale", "已改动,回车重新计数"),
("doc.spell.ignore_all", "全部忽略"),
@@ -103,5 +114,6 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
("doc.merge.unreadable", "无法读取 {name}:{error}"),
("doc.merge.exists", "{name} 已存在,未写入任何文件。"),
("doc.merge.done", "已写入 {n} 个文件到 {folder}"),
("doc.merge.done.one", "已写入 1 个文件到 {folder}"),
("doc.merge.failed", "合并在第 {n} 条停止:{error}"),
];
+6
View File
@@ -17,6 +17,7 @@ pub(super) const EN: &[(&str, &str)] = &[
("tree.clone.busy", "A clone is already running."),
("tree.clean", "Nothing to commit"),
("tree.changed", "{n} files changed"),
("tree.changed.one", "1 file changed"),
("tree.no_git", "Git is not available"),
("tree.unreadable", "This repository could not be read"),
("tree.branch.detached", "Detached at {oid}"),
@@ -62,7 +63,9 @@ pub(super) const EN: &[(&str, &str)] = &[
("tree.layout.unified", "Unified"),
("tree.layout.split", "Side by Side"),
("tree.lines.stage", "Stage {n} Lines"),
("tree.lines.stage.one", "Stage 1 Line"),
("tree.lines.unstage", "Unstage {n} Lines"),
("tree.lines.unstage.one", "Unstage 1 Line"),
("tree.hunk.stage", "Stage Hunk"),
("tree.hunk.unstage", "Unstage Hunk"),
("tree.open_file", "Open File"),
@@ -144,6 +147,7 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
("tree.clone.busy", "已有克隆正在进行。"),
("tree.clean", "没有要提交的改动"),
("tree.changed", "{n} 个文件有改动"),
("tree.changed.one", "1 个文件有改动"),
("tree.no_git", "Git 不可用"),
("tree.unreadable", "无法读取此仓库"),
("tree.branch.detached", "游离于 {oid}"),
@@ -183,7 +187,9 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
("tree.layout.unified", "行内"),
("tree.layout.split", "并排"),
("tree.lines.stage", "暂存 {n} 行"),
("tree.lines.stage.one", "暂存 1 行"),
("tree.lines.unstage", "取消暂存 {n} 行"),
("tree.lines.unstage.one", "取消暂存 1 行"),
("tree.hunk.stage", "暂存此块"),
("tree.hunk.unstage", "取消暂存此块"),
("tree.open_file", "打开文件"),
+4
View File
@@ -46,6 +46,7 @@ pub(super) const EN: &[(&str, &str)] = &[
"tree.force.lost",
"These {n} commits on the remote would be overwritten:\n{commits}",
),
("tree.force.lost.one", "This commit on the remote would be overwritten:\n{commits}"),
("tree.stash.open", "Stash Changes…"),
("tree.stash.title", "Stash changes"),
("tree.stash.message", "Message"),
@@ -131,6 +132,7 @@ pub(super) const EN: &[(&str, &str)] = &[
"tree.move.left",
"These {n} commits leave it; the reflog still finds them:\n{commits}",
),
("tree.move.left.one", "This commit leaves it; the reflog still finds it:\n{commits}"),
("tree.clean.open", "Clean Untracked Files…"),
("tree.clean.title", "Clean untracked files"),
("tree.clean.ignored", "Include ignored files"),
@@ -186,6 +188,7 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
),
("tree.force.nothing", "远端没有本分支缺少的提交。"),
("tree.force.lost", "远端这 {n} 个提交会被覆盖:\n{commits}"),
("tree.force.lost.one", "远端这 1 个提交会被覆盖:\n{commits}"),
("tree.stash.open", "储藏改动…"),
("tree.stash.title", "储藏改动"),
("tree.stash.message", "说明"),
@@ -265,6 +268,7 @@ pub(super) const ZH_CN: &[(&str, &str)] = &[
"tree.move.left",
"这 {n} 个提交将离开该分支,引用日志里仍可找回:\n{commits}",
),
("tree.move.left.one", "这 1 个提交将离开该分支,引用日志里仍可找回:\n{commits}"),
("tree.clean.open", "清理未跟踪的文件…"),
("tree.clean.title", "清理未跟踪的文件"),
("tree.clean.ignored", "包括被忽略的文件"),