i18n: the find box, sort and filter builders and password toggle in Chinese
CI / platforms (windows-latest) (push) Failing after 18s
CI / site (push) Successful in 23s
CI / crate (push) Failing after 13m36s
CI / platforms (ubuntu-24.04) (push) Canceled after 0s

The find counts, toggles, replace buttons, the builders' add, join and
direction labels, the filter tests and the password tooltip read the
builtin catalog. Test::label becomes Test::key, the choice's value; its
label is the catalog's. The shipped-copy scan checks button, segment and
match-arm text on every match, and zh-CN render tests cover both.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-14 20:41:47 -04:00
1 parent 79e94f7e24
commit a4bf6965f9
11 files changed
+303 -79

No files matched your search

+45 -31
View File
@@ -152,7 +152,7 @@ impl RenderOnce for FilterBuilder {
let emit = Rc::new(emit);
let tests: Vec<Choice> = Test::ALL
.iter()
.map(|test| Choice::new(test.label(), test.label()))
.map(|test| Choice::new(test.key(), i18n::text(cx, test.key(), &[])))
.collect();
let theme = cx.theme();
let (rules, any, id) = (self.rules.clone(), self.any, self.id.clone());
@@ -187,13 +187,13 @@ impl RenderOnce for FilterBuilder {
.child(
div().w(theme.label_width() * 0.75).child(
Select::new((id.clone(), format!("test-{ix}")), tests.clone())
.selected(rule.test.label())
.selected(rule.test.key())
.size(ControlSize::Sm)
.on_change(move |label, window, cx| {
let mut next = for_test.clone();
next[ix].test = *Test::ALL
.iter()
.find(|test| test.label() == label.as_ref())
.find(|test| test.key() == label.as_ref())
.expect("a listed test");
test(next, any, window, cx)
}),
@@ -224,18 +224,21 @@ impl RenderOnce for FilterBuilder {
.items_center()
.justify_between()
.child(
Button::new((self.id.clone(), "add"), "Add rule")
.icon(IconName::Plus)
.variant(ButtonVariant::Ghost)
.size(ControlSize::Sm)
.on_click(move |_, window, cx| {
let mut next = to_add.clone();
next.push(FilterRule {
column: first.clone(),
..FilterRule::default()
});
add(next, any, window, cx)
}),
Button::new(
(self.id.clone(), "add"),
i18n::text(cx, "builder.add_rule", &[]),
)
.icon(IconName::Plus)
.variant(ButtonVariant::Ghost)
.size(ControlSize::Sm)
.on_click(move |_, window, cx| {
let mut next = to_add.clone();
next.push(FilterRule {
column: first.clone(),
..FilterRule::default()
});
add(next, any, window, cx)
}),
)
.when(self.rules.len() > 1, |footer| {
footer.child(
@@ -243,8 +246,8 @@ impl RenderOnce for FilterBuilder {
(self.id.clone(), "join"),
if any { "any" } else { "all" },
)
.segment("all", "Match all", None)
.segment("any", "Match any", None)
.segment("all", i18n::text(cx, "builder.all", &[]), None)
.segment("any", i18n::text(cx, "builder.any", &[]), None)
.size(ControlSize::Sm)
.on_change(move |value, window, cx| {
join(to_join.clone(), value.as_ref() == "any", window, cx)
@@ -365,8 +368,16 @@ impl RenderOnce for SortBuilder {
(id.clone(), format!("sort-way-{ix}")),
if sort.rising { "up" } else { "down" },
)
.segment("up", "Ascending", Some(IconName::ArrowUp))
.segment("down", "Descending", Some(IconName::ArrowDown))
.segment(
"up",
i18n::text(cx, "builder.up", &[]),
Some(IconName::ArrowUp),
)
.segment(
"down",
i18n::text(cx, "builder.down", &[]),
Some(IconName::ArrowDown),
)
.size(ControlSize::Sm)
.on_change(move |way, window, cx| {
let mut next = for_flip.clone();
@@ -395,18 +406,21 @@ impl RenderOnce for SortBuilder {
.gap_1()
.child(list)
.children(unused.map(|column| {
Button::new((self.id.clone(), "add"), "Add sort")
.icon(IconName::Plus)
.variant(ButtonVariant::Ghost)
.size(ControlSize::Sm)
.on_click(move |_, window, cx| {
let mut next = add.1.clone();
next.push(SortKey {
column: column.clone(),
rising: true,
});
(add.0)(&next, window, cx)
})
Button::new(
(self.id.clone(), "add"),
i18n::text(cx, "builder.add_sort", &[]),
)
.icon(IconName::Plus)
.variant(ButtonVariant::Ghost)
.size(ControlSize::Sm)
.on_click(move |_, window, cx| {
let mut next = add.1.clone();
next.push(SortKey {
column: column.clone(),
rising: true,
});
(add.0)(&next, window, cx)
})
}))
}
}
+8 -7
View File
@@ -26,14 +26,15 @@ impl Test {
Test::Empty,
];
pub fn label(self) -> &'static str {
/// Its catalog key, which also names it.
pub fn key(self) -> &'static str {
match self {
Self::Contains => "contains",
Self::Equals => "is",
Self::NotEquals => "is not",
Self::Above => "is above",
Self::Below => "is below",
Self::Empty => "is empty",
Self::Contains => "builder.test.contains",
Self::Equals => "builder.test.equals",
Self::NotEquals => "builder.test.not_equals",
Self::Above => "builder.test.above",
Self::Below => "builder.test.below",
Self::Empty => "builder.test.empty",
}
}
+62
View File
@@ -0,0 +1,62 @@
//! The sort and filter builders read in Chinese under zh-CN.
use gpui::{IntoElement, Render, TestAppContext, Window, div, prelude::*};
use crate::{
i18n::{self, I18n},
tables::{FilterBuilder, FilterRule, SortBuilder, SortKey, Test},
theme::Theme,
};
struct Builders;
impl Render for Builders {
fn render(&mut self, _: &mut Window, _: &mut gpui::Context<Self>) -> impl IntoElement {
let columns = [("a", "第一列"), ("b", "第二列")];
let rule = FilterRule {
column: "a".into(),
..FilterRule::default()
};
let key = SortKey {
column: "a".into(),
rising: true,
};
div()
.size_full()
.child(FilterBuilder::new("filter", columns).rules([rule.clone(), rule], true))
.child(SortBuilder::new("sort", columns).keys([key]))
}
}
#[gpui::test]
fn the_builders_read_in_chinese(cx: &mut TestAppContext) {
cx.update(|cx| {
Theme::init(cx);
cx.set_global(I18n::new("zh-CN").catalog("zh-CN", &[]));
});
cx.update(|cx| {
for test in Test::ALL {
let shown = i18n::text(cx, test.key(), &[]);
assert!(
!shown.chars().any(|ch| ch.is_ascii_alphabetic()),
"{test:?}: {shown}"
);
}
for key in [
"builder.add_rule",
"builder.all",
"builder.any",
"builder.add_sort",
"builder.up",
"builder.down",
] {
let shown = i18n::text(cx, key, &[]);
assert!(
!shown.chars().any(|ch| ch.is_ascii_alphabetic()),
"{key}: {shown}"
);
}
});
let (_, cx) = cx.add_window_view(|_, _| Builders);
cx.run_until_parked();
}
+1
View File
@@ -9,6 +9,7 @@ use gpui::{
Styled, TestAppContext, VisualTestContext, Window, div, point, px,
};
mod chinese;
mod clipboard;
mod columns;
mod stale;