Merge pull request #2427 from FeiLiuEM/i18n/preview-panel

i18n: the Preview panel's labels reach the catalog
This commit is contained in:
BFlat
2026-10-30 05:09:12 +07:00
committed by GitHub
2 changed files with 72 additions and 11 deletions
+63 -2
View File
@@ -1674,6 +1674,18 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
("Puppet Bend Pin Tool", "人偶弯曲控点工具"),
("Puppet Advanced Pin Tool", "人偶高级控点工具"),
("Puppet Overlap Pin Tool", "人偶重叠控点工具"),
("Shortcut", "快捷键"),
("Range", "范围"),
("Play From", "从以下位置播放"),
("Frame Rate", "帧速率"),
("Resolution", "分辨率"),
("Overlays", "叠加"),
("Layer Controls", "图层控制"),
("Loop", "循环"),
("Cache Before Playback", "播放前缓存"),
("Pre-roll", "预卷"),
("Post-roll", "后卷"),
("If caching, play cached frames", "缓存时播放已缓存帧"),
];
const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
@@ -2392,6 +2404,18 @@ const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
("Puppet Bend Pin Tool", "人偶彎曲控點工具"),
("Puppet Advanced Pin Tool", "人偶高級控點工具"),
("Puppet Overlap Pin Tool", "人偶重疊控點工具"),
("Shortcut", "快速鍵"),
("Range", "範圍"),
("Play From", "從下列位置播放"),
("Frame Rate", "影格速率"),
("Resolution", "解析度"),
("Overlays", "覆疊"),
("Layer Controls", "圖層控制"),
("Loop", "循環"),
("Cache Before Playback", "播放前快取"),
("Pre-roll", "預卷"),
("Post-roll", "後卷"),
("If caching, play cached frames", "快取時播放已快取影格"),
];
/// Ukrainian (uk): original translations of the same interface rows as the Chinese catalogs.
@@ -5885,8 +5909,6 @@ mod tests {
rows.iter().find(|(source, _)| *source == en).map_or(en, |(_, translated)| *translated)
}
/// A row that translates nothing, repeats a source string, or changes the number of values the
/// English source carries is a bug in the catalog itself.
#[test]
fn the_toolbar_asks_the_catalog_for_the_tool_names() {
let header = include_str!("../header.rs");
@@ -5899,6 +5921,45 @@ mod tests {
);
}
#[test]
fn the_preview_panel_labels_are_translated() {
// The Preview panel draws these from a local closure, a check table and a roll tuple, none of
// which the call-shape scan sees; they had no rows at all.
for key in [
"Shortcut",
"Range",
"Play From",
"Frame Rate",
"Resolution",
"Overlays",
"Layer Controls",
"Loop",
"Cache Before Playback",
"Pre-roll",
"Post-roll",
"If caching, play cached frames",
] {
for (name, table) in [("Simplified", SIMPLIFIED_CHINESE), ("Traditional", TRADITIONAL_CHINESE)] {
let value = table.iter().find(|(k, _)| *k == key).map(|(_, v)| *v);
assert!(value.is_some_and(|v| !v.is_empty()), "{key} has no {name} row");
}
}
// A row is not a translation until the panel asks for it: the labels drawn one by one carry
// `tr(..)`, and the table and the roll tuple wrap the text they read at the call.
let source = include_str!("../panels/misc.rs");
for literal in ["Shortcut", "Range", "Play From", "Frame Rate", "Resolution", "Full Screen", "If caching, play cached frames"] {
assert!(source.contains(&format!("tr(\"{literal}\")")), "{literal} is drawn without asking the catalog");
}
for call in ["check_row(app, ui, &p, pos2(cx, cy), key, tr(text), on)", "Align2::LEFT_CENTER, tr(text),"] {
assert!(source.contains(call), "{call} no longer asks the catalog");
}
for table in ["\"Overlays\"", "\"Layer Controls\"", "\"Loop\"", "\"Cache Before Playback\"", "\"Pre-roll\"", "\"Post-roll\""] {
assert!(source.contains(table), "{table} is not in the panel");
}
}
/// A row that translates nothing, repeats a source string, or changes the number of values the
/// English source carries is a bug in the catalog itself.
#[test]
fn catalogs_are_unique_and_keep_the_english_shape() {
// Grouped by language: a source listed in two tables of one language is still a repeat.
+9 -9
View File
@@ -61,7 +61,7 @@ pub fn preview(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
let mut yy = y + 46.0;
// Shortcut.
label(yy, "Shortcut");
label(yy, tr("Shortcut"));
let names: Vec<String> = PreviewShortcut::ALL.iter().map(|s| s.label().to_string()).collect();
if let Some(i) = dropdown_row(
app,
@@ -91,14 +91,14 @@ pub fn preview(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
let row = if i < 4 { i / 2 } else { i - 2 };
let cx = x0 + col as f32 * 110.0 - 2.0;
let cy = yy + row as f32 * 22.0;
if check_row(app, ui, &p, pos2(cx, cy), key, text, on) {
if check_row(app, ui, &p, pos2(cx, cy), key, tr(text), on) {
changes.push(json!({"shortcut": current.id(), key: !on}));
}
}
yy += 4.0 * 22.0 + 6.0;
// Range (and the pre/post-roll of Play Around Current Time).
label(yy, "Range");
label(yy, tr("Range"));
let ranges: Vec<String> = PreviewRange::ALL.iter().map(|r| r.label().to_string()).collect();
let range_ids = ["workArea", "workAreaExtended", "entireDuration", "aroundCurrentTime"];
if let Some(i) = dropdown_row(
@@ -116,7 +116,7 @@ pub fn preview(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
if o.range == PreviewRange::AroundCurrentTime {
for (k, (key, text, v)) in [("preRoll", "Pre-roll", o.pre_roll), ("postRoll", "Post-roll", o.post_roll)].into_iter().enumerate() {
let lx = xv + k as f32 * 100.0;
p.text(pos2(lx, yy), Align2::LEFT_CENTER, text, Tokens::ui(11.5), t.text_dim);
p.text(pos2(lx, yy), Align2::LEFT_CENTER, tr(text), Tokens::ui(11.5), t.text_dim);
let (r, nv, _) = widgets::hot_number_at(
ui,
pos2(lx + 52.0, yy - 9.0),
@@ -134,7 +134,7 @@ pub fn preview(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
}
// Play From.
label(yy, "Play From");
label(yy, tr("Play From"));
let froms: Vec<String> = PlayFrom::ALL.iter().map(|f| f.label().to_string()).collect();
if let Some(i) = dropdown_row(
app,
@@ -151,7 +151,7 @@ pub fn preview(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
// Frame Rate, Skip, Resolution.
let comp_fps = app.session.active_comp().map(|c| c.frame_rate.as_f64());
label(yy, "Frame Rate");
label(yy, tr("Frame Rate"));
const RATES: [f64; 12] = [8.0, 10.0, 12.0, 12.5, 15.0, 23.976, 24.0, 25.0, 29.97, 30.0, 50.0, 60.0];
let auto = format!("({:.2}) Auto", comp_fps.unwrap_or(0.0));
let mut rates = vec![auto.clone()];
@@ -180,7 +180,7 @@ pub fn preview(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
changes.push(json!({"shortcut": current.id(), "skip": nv.round() as u32}));
}
yy += 24.0;
label(yy, "Resolution");
label(yy, tr("Resolution"));
let ress: Vec<String> = PreviewResolution::ALL.iter().map(|r| r.label().to_string()).collect();
let res_ids = ["auto", "full", "half", "third", "quarter", "custom"];
if let Some(i) = dropdown_row(
@@ -209,7 +209,7 @@ pub fn preview(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
}
}
yy += 24.0;
if check_row(app, ui, &p, pos2(x0 - 2.0, yy), "fullScreen", "Full Screen", o.full_screen) {
if check_row(app, ui, &p, pos2(x0 - 2.0, yy), "fullScreen", tr("Full Screen"), o.full_screen) {
changes.push(json!({"shortcut": current.id(), "fullScreen": !o.full_screen}));
}
yy += 24.0;
@@ -217,7 +217,7 @@ pub fn preview(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
// What stopping does.
p.text(pos2(x0, yy), Align2::LEFT_CENTER, tr_args("On ({}) stop:", &[&(current.label())]), Tokens::ui(11.5), t.text_dim);
yy += 20.0;
if check_row(app, ui, &p, pos2(x0 - 2.0, yy), "playCachedFrames", "If caching, play cached frames", o.play_cached_frames) {
if check_row(app, ui, &p, pos2(x0 - 2.0, yy), "playCachedFrames", tr("If caching, play cached frames"), o.play_cached_frames) {
changes.push(json!({"shortcut": current.id(), "playCachedFrames": !o.play_cached_frames}));
}
yy += 22.0;