Replace localization of `Vec<Localize>` with `List` type

finchie
Aug 26, 2025, 7:30 AM
Q7LUHXXBN3ACNMGT4O2SKY5EGDEJQXMVJGYETTKNWIUAZCQV6HGAC

Dependencies

  • [2] 7M4UI3TW Update dependencies to latest versions
  • [3] RUCC2HKZ Rename from `fluent_embed` to `l10n_embed`
  • [4] USKESL6X Add examples for using common types in `l10n_embed`
  • [5] X6AMFX3N Temporarily remove automatic language detection
  • [6] 2HHBS7VW Add rudimentary support for localizing lists
  • [*] UKFEFT6L Create basic `Output` proc-macro
  • [*] VZYZRAO4 Move `output-macros` crate into workspace
  • [*] HHJDRLLN Create `fluent_embed_runtime` crate

Change contents

  • edit in Cargo.lock at line 740
    [3.3075]
    [3.3075]
    "icu_list",
  • edit in Cargo.toml at line 39
    [5.102]
    [5.102]
    icu_list = "2.0"
  • edit in l10n_embed/src/list.rs at line 2
    [6.90]
    [6.90]
    /// Re-export from [`icu_locale`] for convenience when constructing a [`List`]
    pub use icu_list::options::ListLength;
  • edit in l10n_embed/src/list.rs at line 8
    [6.113]
    [6.113]
    use icu_list::ListFormatter;
    use icu_list::options::ListFormatterOptions;
  • replacement in l10n_embed/src/list.rs at line 12
    [6.138][6.138:510]()
    macro_rules! impl_list {
    ($list_type:ty) => {
    impl<T: Localize> Localize for $list_type {
    fn localize_for(&self, locale: &Locale) -> String {
    let localized_items: Vec<String> =
    self.iter().map(|item| item.localize_for(locale)).collect();
    localized_items.join("\n")
    }
    }
    };
    [6.138]
    [6.510]
    pub trait Length {
    fn len(&self) -> usize;
    }
    pub struct List<L: Localize> {
    messages: Vec<L>,
    length: ListLength,
  • replacement in l10n_embed/src/list.rs at line 21
    [6.513][6.513:551]()
    impl_list!(Vec<T>);
    impl_list!(&[T]);
    [6.513]
    impl<L: Localize> List<L> {
    pub fn new(messages: Vec<L>, length: ListLength) -> Self {
    Self { messages, length }
    }
    }
    impl<L: Localize> Length for List<L> {
    fn len(&self) -> usize {
    self.messages.len()
    }
    }
    impl<L: Localize> Localize for List<L> {
    fn localize_for(&self, locale: &Locale) -> String {
    let list_formatter = ListFormatter::try_new_and(
    locale.into(),
    ListFormatterOptions::default().with_length(self.length),
    )
    .unwrap();
    let localized_messages = self
    .messages
    .iter()
    .map(|message| message.localize_for(locale));
    list_formatter.format(localized_messages).to_string()
    }
    }
  • edit in l10n_embed/Cargo.toml at line 23
    [2.5336]
    [2.5336]
    icu_list.workspace = true
  • file addition: list.rs (----------)
    [4.20]
    //! Example showing how to localize lists
    use icu_locale::{Locale, locale};
    use l10n_embed::Localize;
    use l10n_embed::list::{List, ListLength};
    const DEFAULT_LOCALE: Locale = locale!("en-US");
    fn main() {
    let items = vec!["item 1", "item 2", "item 3", "item 4"];
    // Create some lists of different lengths
    let narrow_list = List::new(items.clone(), ListLength::Narrow);
    let short_list = List::new(items.clone(), ListLength::Short);
    let wide_list = List::new(items.clone(), ListLength::Wide);
    // Localize these lists
    println!("Narrow list: {}", narrow_list.localize_for(&DEFAULT_LOCALE));
    println!("Short list: {}", short_list.localize_for(&DEFAULT_LOCALE));
    println!("Wide list: {}", wide_list.localize_for(&DEFAULT_LOCALE));
    }