Skip to content

Commit cdea5a6

Browse files
author
Roy Lin
committed
feat: add locale-aware formatting utilities
1 parent 61ab778 commit cdea5a6

13 files changed

Lines changed: 1062 additions & 22 deletions

File tree

Cargo.lock

Lines changed: 188 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,12 @@ gtk4 = []
116116
gtk4-native = ["gtk4", "dep:gtk4_crate"]
117117

118118
[dependencies]
119+
fixed_decimal = { version = "0.7.2", features = ["ryu"] }
119120
icu_collator = "2.2.1"
121+
icu_datetime = "2.2.0"
122+
icu_decimal = { version = "2.2.0", features = ["alloc"] }
120123
icu_locale_core = "2.2.0"
124+
icu_provider = { version = "2.2.0", features = ["sync"] }
121125
serde = { version = "1", features = ["derive"] }
122126
serde_json = "1"
123127
swc_atoms = { version = "9.0.3", optional = true }

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ object graph at the host boundary.
2525
touch/pen long-press selection entry, collection keyboard navigation,
2626
hierarchical tree expansion, activation-ordered overlay dismissal, modal
2727
background inertness, nested focus containment/restoration, typed anchored
28-
overlay placement, inherited locale/direction, versioned capability
29-
reporting, shared native event-source state machines, and accessibility
30-
conformance checks. Versioned native-input manifests expand every role marked
28+
overlay placement, inherited locale/direction, locale-aware collation and
29+
decimal/date/time formatting, versioned capability reporting, shared native
30+
event-source state machines, and accessibility conformance checks. Versioned
31+
native-input manifests expand every role marked
3132
native into strict OS-automation cases; adapter and headless traces cannot
3233
satisfy that evidence gate.
3334
A WinUI smoke runner records real XAML Button and list-item mouse and keyboard
@@ -40,8 +41,9 @@ object graph at the host boundary.
4041
Populating the AppKit and GTK4 manifests with real platform automation,
4142
role-edge input parity, real-platform layout-aware page-navigation fixtures,
4243
IME/dead-key conformance, measured overlay collision/arrow conformance and
43-
scroll locking, remaining native focus conformance, and locale formatting
44-
are still in progress.
44+
scroll locking, remaining native focus conformance, message catalogs,
45+
currency/percent/unit and date-range/time-zone formatting are still in
46+
progress.
4547
- `.rsx` component source modules with imports, local Rust types, hook
4648
registrations, Rust selector/reducer expressions, and a final `rsx!(...)`
4749
view.

docs/architecture.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,17 @@ prefers the GDK Unicode scalar over its symbolic key name, and WinUI uses
452452
`ToUnicode` with the active keyboard layout and the non-mutating flag before
453453
falling back to a stable virtual-key name. Full IME and dead-key composition
454454
remains an adapter conformance gap.
455+
`I18nManager` also resolves that inherited locale for reusable
456+
`LocaleCollator`, `LocaleNumberFormatter`, and `LocaleDateFormatter` objects.
457+
The public collator exposes search/sort usage, ECMA-402 sensitivity,
458+
case-first, and numeric ordering. Decimal formatting exposes grouping,
459+
sign-display, and bounded fraction digits with half-expand rounding. Date and
460+
time formatting exposes short through full styles, optional seconds, calendar
461+
selection, numbering systems, and hour-cycle overrides through BCP 47 Unicode
462+
extensions. These formatters use compiled ICU4X data, are `Send + Sync`, and
463+
perform no platform, file, or network I/O. The collection typeahead path uses
464+
the same public collator implementation so interactive search and application
465+
sorting cannot drift to separate locale rules.
455466
AppKit keeps logical item identity separate from the collection selection
456467
target: a row button is registered as the ListBoxItem or TreeItem responder,
457468
while activation reports the selected value to the owning collection.

docs/react-aria-native.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,13 @@ The first shared interaction milestone is available in the portable runtime:
256256
- `I18nManager` projects inherited locale and writing direction through the
257257
keyed native tree. Scoped overrides and default locale changes are preserved
258258
across rerenders, and BCP 47 language/script subtags provide deterministic
259-
RTL inference.
259+
RTL inference. It creates reusable, thread-safe `LocaleCollator`,
260+
`LocaleNumberFormatter`, and `LocaleDateFormatter` values from the effective
261+
node locale. Collation covers search/sort sensitivity, case-first, and
262+
numeric ordering; stable ICU4X decimal formatting covers grouping, signs,
263+
and fraction digits; date/time formatting covers localized short through
264+
full styles, seconds, calendar, numbering-system, and hour-cycle locale
265+
extensions. Collection typeahead reuses this public collator.
260266
- Native IR capabilities are versioned. Every host exposes a feature manifest
261267
with unsupported, portable, or native support levels, role-specific
262268
overrides, and auditable capability issues. Protocol render responses carry
@@ -375,7 +381,7 @@ props:
375381
| P1 | Event propagation | Add platform-run conformance fixtures for conditional `Stop`/`Continue` across nested native controls. |
376382
| P1 | Focus management | Add platform-run conformance fixtures for post-mount `autoFocus`, nested containment, and restoration. |
377383
| P1 | Collections and selection | Complete IME/dead-key typeahead conformance and add real-platform fixtures for layout-aware page navigation. |
378-
| P1 | Internationalization | Add message formatting, number/date formatting, locale-aware collation, and localized interaction behavior on top of inherited locale/direction. |
384+
| P1 | Internationalization | Add message formatting, currency/percent/unit number styles, date ranges/time zones, and localized input behavior. Reusable decimal/date/time formatting and locale-aware collation now build on inherited locale/direction. |
379385
| P1 | Accessibility conformance | Complete OS accessibility API projection, relationships, live regions, value announcements, and role-specific native adapter coverage. |
380386
| P2 | Overlays | Complete measured boundary-driven collision and arrow projection, native scroll locking, configurable outside-interaction filters, multi-window layer coordination, and real-platform positioning conformance fixtures. |
381387
| P2 | Capability enforcement | Turn reported capability gaps into adapter policy and conformance gates where portable fallback is not sufficient. |

src/error.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ pub enum GuiError {
1919
InvalidTree {
2020
message: String,
2121
},
22+
Internationalization {
23+
message: String,
24+
},
2225
Host {
2326
message: String,
2427
},
@@ -41,6 +44,9 @@ impl Display for GuiError {
4144
write!(f, "missing required prop {prop:?} on component {component}")
4245
}
4346
GuiError::InvalidTree { message } => write!(f, "invalid native UI tree: {message}"),
47+
GuiError::Internationalization { message } => {
48+
write!(f, "internationalization error: {message}")
49+
}
4450
GuiError::Host { message } => write!(f, "native host error: {message}"),
4551
}
4652
}
@@ -60,4 +66,10 @@ impl GuiError {
6066
message: message.into(),
6167
}
6268
}
69+
70+
pub fn internationalization(message: impl Into<String>) -> Self {
71+
GuiError::Internationalization {
72+
message: message.into(),
73+
}
74+
}
6375
}

0 commit comments

Comments
 (0)