i18n: a right-to-left message leads with its mark
gpui sets no paragraph direction, so CoreText took a Hebrew line whose first strong character was Latin, or the left-to-right mark of a signed number, as left to right and swapped its parts. I18n::text now leads a right-to-left message with U+200F; the number keeps CLDR's U+200E, so its sign stays at the digits' left. The demo adds a change that opens with a signed number, in every catalog; under Hebrew it lies at the line's right end. A test holds the marks on a message that starts with a number and one that starts with a Latin name.
This commit is contained in:
1 parent
83ecacde65
commit
451fdcc7c0
4 files changed
+40
-6
No files matched your search
+7
-4
@@ -71,7 +71,7 @@ impl I18n {
|
||||
cx.refresh_windows();
|
||||
}
|
||||
|
||||
/// The shown locale's message for `key`, each `{name}` filled from `args`; fails on a missing key or argument.
|
||||
/// The shown locale's message for `key`, each `{name}` filled from `args`; fails on a missing key or argument. gpui sets no paragraph direction, so a right-to-left message leads with a right-to-left mark: CoreText would lay out one that starts with Latin letters or a signed number left to right.
|
||||
pub fn text(&self, key: &str, args: &[(&str, &str)]) -> SharedString {
|
||||
let (_, catalog) = self
|
||||
.catalogs
|
||||
@@ -81,9 +81,12 @@ impl I18n {
|
||||
let message = catalog
|
||||
.get(key)
|
||||
.unwrap_or_else(|| panic!("no message {key:?} in {}", self.locale.tag));
|
||||
fill(message, args)
|
||||
.unwrap_or_else(|error| panic!("{key:?} in {}: {error}", self.locale.tag))
|
||||
.into()
|
||||
let text = fill(message, args)
|
||||
.unwrap_or_else(|error| panic!("{key:?} in {}: {error}", self.locale.tag));
|
||||
match self.locale.direction {
|
||||
Direction::Ltr => text.into(),
|
||||
Direction::Rtl => format!("\u{200f}{text}").into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-1
@@ -25,6 +25,26 @@ fn a_message_fills_its_arguments() {
|
||||
assert_eq!(fill("{b}", &[("a", "x")]), Err("no argument \"b\"".into()));
|
||||
}
|
||||
|
||||
/// A right-to-left message leads with its mark, so one that starts with Latin letters or a signed number still reads right to left.
|
||||
#[test]
|
||||
fn a_right_to_left_message_leads_with_its_mark() {
|
||||
let he = I18n::new("he-IL").catalog(
|
||||
"he-IL",
|
||||
&[("change", "{change}% מאז אתמול"), ("sent", "{name} שלח")],
|
||||
);
|
||||
let change = Locale::of("he-IL").number(-3.5, 1);
|
||||
assert_eq!(
|
||||
he.text("change", &[("change", &change)]),
|
||||
"\u{200f}\u{200e}−3.5% מאז אתמול"
|
||||
);
|
||||
assert_eq!(he.text("sent", &[("name", "Ada")]), "\u{200f}Ada שלח");
|
||||
assert_eq!(
|
||||
i18n().text("hi", &[]),
|
||||
"Hello",
|
||||
"a left-to-right message takes no mark"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "\"files\" in en-US: no argument \"folder\"")]
|
||||
fn a_missing_argument_fails() {
|
||||
@@ -160,7 +180,10 @@ mod shown {
|
||||
assert!(first.left() < second.left(), "left to right in en-US");
|
||||
cx.update(|_, cx| I18n::set_locale("he-IL", cx));
|
||||
cx.run_until_parked();
|
||||
assert_eq!(cx.read(|cx| cx.global::<I18n>().text("hi", &[])), "שלום");
|
||||
assert_eq!(
|
||||
cx.read(|cx| cx.global::<I18n>().text("hi", &[])),
|
||||
"\u{200f}שלום"
|
||||
);
|
||||
let first = cx.debug_bounds("first").expect("the first mark");
|
||||
let second = cx.debug_bounds("second").expect("the second mark");
|
||||
assert!(
|
||||
|
||||
Reference in new issue
Block a user