day_localization/
collate.rs1use std::cell::RefCell;
11use std::cmp::Ordering;
12use std::collections::HashMap;
13
14use icu_collator::options::CollatorOptions;
15use icu_collator::{Collator, CollatorBorrowed};
16
17day_reactive::tls_slots! {
18 collate;
19 static COLLATORS: RefCell<HashMap<String, Option<CollatorBorrowed<'static>>>> =
21 RefCell::new(HashMap::new());
22
23}
24
25fn with_collator<R>(locale: &str, f: impl FnOnce(Option<&CollatorBorrowed<'static>>) -> R) -> R {
26 COLLATORS.with(|c| {
27 let mut map = c.borrow_mut();
28 let entry = map.entry(locale.to_string()).or_insert_with(|| {
29 let parsed: icu_locale_core::Locale = locale.parse().ok()?;
30 Collator::try_new((&parsed).into(), CollatorOptions::default()).ok()
31 });
32 f(entry.as_ref())
33 })
34}
35
36pub fn compare_in(locale: &str, a: &str, b: &str) -> Ordering {
39 with_collator(locale, |c| match c {
40 Some(c) => c.compare(a, b),
41 None => a.cmp(b),
42 })
43}
44
45pub fn compare(a: &str, b: &str) -> Ordering {
48 let locale = crate::locale().get();
49 compare_in(&locale, a, b)
50}
51
52pub fn sort_localized<T: AsRef<str>>(items: &mut [T]) {
54 let locale = crate::locale().get();
55 with_collator(&locale, |c| match c {
56 Some(c) => items.sort_by(|a, b| c.compare(a.as_ref(), b.as_ref())),
57 None => items.sort_by(|a, b| a.as_ref().cmp(b.as_ref())),
58 });
59}