Add `layout` module for localizing with separators and vertical/horizontal padding
Dependencies
- [2]
HHJDRLLNCreate `fluent_embed_runtime` crate - [3]
C6W7N6N5Implement `Localize` for `FixedDecimal` and primitive number types - [4]
USKESL6XAdd examples for using common types in `l10n_embed` - [5]
2HHBS7VWAdd rudimentary support for localizing lists - [6]
XPGOKS6XAdd rudimentary support for built-in `LEN()` function - [7]
5TEX4MNUSplit `fluent_embed` into `group` and `parse` modules
Change contents
- edit in l10n_embed_derive/tests/functions.rs at line 7
use l10n_embed::layout::Lines; - replacement in l10n_embed_derive/tests/functions.rs at line 15
Length { items: Vec<String> },Numbers { items: Vec<String> },Plurals { items: Vec<String> },Length { items: Lines<String> },Numbers { items: Lines<String> },Plurals { items: Lines<String> }, - replacement in l10n_embed_derive/tests/functions.rs at line 22
items: Vec<String>,items: Lines<String>, - replacement in l10n_embed_derive/tests/functions.rs at line 27
items: Vec<String>,items: Lines<String>, - replacement in l10n_embed_derive/tests/functions.rs at line 32
items: Vec<String>,items: Lines<String>, - replacement in l10n_embed_derive/tests/functions.rs at line 46
items: items.clone(),items: Lines::new(items.clone()), - replacement in l10n_embed_derive/tests/functions.rs at line 52
Length { items },Length {items: Lines::new(items),}, - replacement in l10n_embed_derive/tests/functions.rs at line 71
items: items.clone(),items: Lines::new(items.clone()), - replacement in l10n_embed_derive/tests/functions.rs at line 76
compare_message(Numbers { items }, expected, DEFAULT_LOCALE);compare_message(Numbers {items: Lines::new(items),},expected,DEFAULT_LOCALE,); - replacement in l10n_embed_derive/tests/functions.rs at line 96
items: items.clone(),items: Lines::new(items.clone()),},expected,DEFAULT_LOCALE,);compare_message(Plurals {items: Lines::new(items), - edit in l10n_embed_derive/tests/functions.rs at line 108
compare_message(Plurals { items }, expected, DEFAULT_LOCALE); - replacement in l10n_embed_derive/src/fluent/ast.rs at line 326
parse_quote!(Vec::len(#vec_reference))parse_quote!(l10n_embed::list::Length::len(#vec_reference)) - edit in l10n_embed/src/lib.rs at line 2
pub mod layout; - file addition: layout.rs[2.49]
//! Implementations of `Localize` for various layout helpersuse icu_locale::Locale;use crate::Localize;use crate::list::Length;pub struct Lines<L: Localize, const SEPARATOR_COUNT: usize = 1> {messages: Vec<L>,}impl<L: Localize, const SEPARATOR_COUNT: usize> Lines<L, SEPARATOR_COUNT> {pub fn new(messages: Vec<L>) -> Self {Self { messages }}}impl<L: Localize, const SEPARATOR_COUNT: usize> Length for Lines<L, SEPARATOR_COUNT> {fn len(&self) -> usize {self.messages.len()}}impl<L: Localize, const SEPARATOR_COUNT: usize> Localize for Lines<L, SEPARATOR_COUNT> {fn localize_for(&self, locale: &Locale) -> String {let localized_items: Vec<String> = self.messages.iter().map(|item| item.localize_for(locale)).collect();localized_items.join(&"\n".repeat(SEPARATOR_COUNT))}}pub struct Padded<L: Localize, const VERTICAL_PADDING: usize, const HORIZONTAL_PADDING: usize> {message: L,}impl<L: Localize, const VERTICAL_PADDING: usize, const HORIZONTAL_PADDING: usize>Padded<L, VERTICAL_PADDING, HORIZONTAL_PADDING>{pub fn new(message: L) -> Self {Self { message }}}impl<L: Localize, const VERTICAL_PADDING: usize, const HORIZONTAL_PADDING: usize> Localizefor Padded<L, VERTICAL_PADDING, HORIZONTAL_PADDING>{fn canonical_locale(&self) -> Locale {self.message.canonical_locale()}fn available_locales(&self) -> Vec<Locale> {self.message.available_locales()}fn localize_for(&self, locale: &Locale) -> String {let mut output = String::new();// Only apply the vertical padding above the message, not belowoutput.push_str(&"\n".repeat(VERTICAL_PADDING));let localized_message = self.message.localize_for(locale);// Apply the horizontal padding to each linelet horizontal_padding = " ".repeat(HORIZONTAL_PADDING);for (index, line) in localized_message.lines().enumerate() {// Add a newline on every additional lineif index > 0 {output.push('\n');}output.push_str(&horizontal_padding);output.push_str(line);}output}} - file addition: layout.rs[4.20]
//! Example showing how to localize with various layoutsuse icu_locale::{Locale, locale};use l10n_embed::Localize;use l10n_embed::layout::{Lines, Padded};const DEFAULT_LOCALE: Locale = locale!("en-US");fn main() {let items = vec!["item 1", "item 2", "item 3", "item 4"];let message = "a secret message";// Create different layoutslet single_newline: Lines<&str, 1> = Lines::new(items.clone());let double_newlines: Lines<&str, 2> = Lines::new(items.clone());let vertical_padding: Padded<&str, 1, 0> = Padded::new(message);let horizontal_padding: Padded<&str, 0, 4> = Padded::new(message);let combined_padding: Padded<&str, 1, 4> = Padded::new(message);let padded_newlines: Lines<Padded<&str, 0, 4>, 1> =Lines::new(items.iter().map(|item| Padded::new(*item)).collect());// Localize these layoutslet layouts = [("Single newline",single_newline.localize_for(&DEFAULT_LOCALE),),("Double newlines",double_newlines.localize_for(&DEFAULT_LOCALE),),("Vertical padding",vertical_padding.localize_for(&DEFAULT_LOCALE),),("Horizontal padding",horizontal_padding.localize_for(&DEFAULT_LOCALE),),("Combined padding",combined_padding.localize_for(&DEFAULT_LOCALE),),("Padded newlines",padded_newlines.localize_for(&DEFAULT_LOCALE),),];// Print each layout with a separator to make things clearfor (name, layout) in layouts {println!("----- {name} -----");println!("{layout}");}}