Module icu_locale::preferences
Expand description
This API provides necessary functionality for building user preferences structs.
It includes the ability to merge information between the struct and a Locale
,
facilitating the resolution of attributes against default values.
Preferences struct serve as a composable argument to ICU4X
constructors, allowing
for ergonomic merging between information encoded in multiple sets of user inputs:
Locale, application preferences and operating system preferences.
The crate is intended primarily to be used by components constructors to normalize the format
of ingesting preferences across all of ICU4X
.
§Preferences vs Options
ICU4X introduces a separation between two classes of parameters that are used to adjust the behavior of a component.
Preferences
represent the user-driven preferences on how the given user wants the internationalization
to behave. Those are items like language, script, calendar and numbering systems etc.
Options
represent the developer-driven adjustments that affect how given information is presented
based on the requirements of the application like available space or intended tone.
§Options Division
The Options
themselves are also divided into options that are affecting data slicing, and ones that don’t.
This is necessary to allow for DCE and FFI to produce minimal outputs avoiding loading unnecessary data that
is never to be used by a given component.
The result is that some option keys affect specialized constructors such as try_new_short
, try_new_long
, which
result in data provider loading only data necessary to format short or long values respectively.
For options that are not affecting data slicing, an Options
struct is provided that the developer
can fill with selected key values, or use the defaults.
§Preferences Merging
In traditional internatonalization APIs, the argument passed to constructors is a locale.
ICU4X changes this paradigm by accepting a Preferences
, which can be extracted from a Locale
and combined with
other Preferences
s provided by the environment.
This approach makes it easy for developers to write code that takes just a locale, as in other systems, as well as handle more sophisticated cases where the application may receive, for example, a locale, a set of internationalization preferences specified within the application, and a third set extracted from the operating system’s preferences.
§ECMA-402 vs ICU4X
The result of the two paradigm shifts presented above is that the way constructors work is different.
§ECMA-402
let locale = new Locale("en-US-u-hc-h12");
let options = {
hourCycle: "h24", // user preference
timeStyle: "long", // developer option
};
let dtf = new DateTimeFormat(locale, options);
§ICU4X
let loc = locale!("en-US-u-hc-h12");
let prefs = DateTimeFormatterPreferences {
hour_cycle: HourCycle::H24,
};
let options = DateTimeFormatterOptions {
time_style: TimeStyle::Long,
};
let mut combined_prefs = DateTimeFormatterPreferences::from(loc);
combined_prefs.extend(prefs);
let dtf = DateTimeFormatter::try_new(combined_prefs, options);
This architecture allows for flexible composition of user and developer settings sourced from different locations in custom ways based on the needs of each deployment.
Below are some examples of how the Preferences
model can be used in different setups.
§Examples
use icu::locale::preferences::{
define_preferences,
extensions::unicode::keywords::HourCycle,
};
use icu::locale::locale;
define_preferences!(
// Name of the preferences struct
ExampleComponentPreferences,
{
// A preference relevant to the component
hour_cycle: HourCycle
}
);
pub struct ExampleComponent {
data: MyData,
}
impl ExampleComponent {
pub fn new(prefs: ExampleComponentPreferences) -> Self {
let locale = get_data_locale_from_prefs(prefs);
let data = load_data(locale);
Self { data }
}
}
Now we can use that component in multiple different ways,
§Scenario 1: Use Locale as the only input
let loc = locale!("en-US-u-hc-h23");
let tf = ExampleComponent::new(loc.into());
§Scenario 2: Compose Preferences and Locale
let loc = locale!("en-US-u-hc-h23");
let app_prefs = ExampleComponentPreferences {
hour_cycle: Some(HourCycle::H12),
..Default::default()
};
let mut combined_prefs = ExampleComponentPreferences::from(loc);
combined_prefs.extend(app_prefs);
// HourCycle is set from the prefs bag and override the value from the locale
assert_eq!(combined_prefs.hour_cycle, Some(HourCycle::H12));
let tf = ExampleComponent::new(combined_prefs);
§Scenario 3: Merge Preferences from Locale, OS, and Application
let loc = locale!("en-US-u-hc-h24");
// Simulate OS preferences
let os_prefs = ExampleComponentPreferences {
hour_cycle: Some(HourCycle::H23),
..Default::default()
};
// Application does not specify hour_cycle
let app_prefs = ExampleComponentPreferences {
hour_cycle: Some(HourCycle::H12),
..Default::default()
};
let mut combined_prefs = ExampleComponentPreferences::from(loc);
combined_prefs.extend(os_prefs);
combined_prefs.extend(app_prefs);
// HourCycle is set from the OS preferences since the application didn't specify it
assert_eq!(combined_prefs.hour_cycle, Some(HourCycle::H12));
let tf = ExampleComponent::new(combined_prefs);
§Scenario 4: Neither Application nor OS specify the preference
let loc = locale!("en-US-u-hc-h24");
// Simulate OS preferences
let os_prefs = ExampleComponentPreferences::default(); // OS does not specify hour_cycle
let app_prefs = ExampleComponentPreferences::default(); // Application does not specify hour_cycle
let mut combined_prefs = ExampleComponentPreferences::from(loc);
combined_prefs.extend(os_prefs);
combined_prefs.extend(app_prefs);
// HourCycle is taken from the locale
assert_eq!(combined_prefs.hour_cycle, Some(HourCycle::H24));
let tf = ExampleComponent::new(combined_prefs);
Modules§
- A set of extensions which correspond to preferences.
Structs§
- The structure storing locale subtags used in preferences.
Traits§
- A low-level trait implemented on each preference exposed in component preferences.