host_info is a library providing functionality to retrieve regional preferences from host environments - primarily the operating system the program is running in.
The library is designed to bind the different host environment preference architectures to the icu model.
use icu_host_info::icu_host_info; use icu::calendar::Date; use icu::datetime::{fieldsets, DateTimeFormatter}; let date = Date::try_new_gregorian(2025, 10, 10) .expect("Failed to create date"); // requires feature `datetime` let prefs = icu_host_info::datetime_preferences() .expect("Failed to retrieve host info"); let dtf = DateTimeFormatter::try_new(prefs, fieldsets::YMD::long()) .expect("Failed to create datetime formatter."); let formatted_dt = dtf.format(&date); assert_eq!(formatted_dt.to_string(), "October 10, 2025");
The library intends to provide means to retrieve regional preferences to icu preferences with a focus on Unicode Extensions, but allow for propagation of preferences offered by the host environments which may not have a representation in Unicode Extensions (for example: date format pattern).
Legend:
host_info supporthost_info doesn't| Feature | Android | iOS | Linux (1) | macOS | Windows |
|---|---|---|---|---|---|
| Requested Locales | ✅ | ✅ | ✅ | ✅ | ✅ |
| Calendar | 🚧 | 🚧 | 🚧 | ✅ | ✅ |
| Region | 🚧 | 🚧 | 🚧 | ✅ | ✅ |
| Hour cycle | 🚧 | 🚧 | ✅ | ✅ | 🚧 |
| Measurement System | 🚧 | 🚧 | 🚧 | ✅ | 🚧 |
| Measurement Override | 🚧 | 🚧 | 🚧 | ✅ | 🚧 |
| First Day of week | 🚧 | 🚧 | 🚧 | ✅ | ✅ |
| Collation | 🚧 | 🚧 | 🚧 | ✅ | ❌ |
| Date format | 🚧 | 🚧 | 🚧 | 🚧 | 🚧 |
| Number format | 🚧 | 🚧 | 🚧 | 🚧 | 🚧 |
(1) In the case of Linux, different desktop environments such as Gnome and KDE are supported together.
The library provides three ways of injecting retrieved values into formatters:
For most common components, such as DateTimeFormatter, the library exposes a direct getter that retrieves a Preferences struct for that component. This getter is located behind a flag to allow for control over which dependencies are being pulled.
use icu_host_info::icu_host_info; use icu::datetime::{fieldsets, DateTimeFormatter}; // requires feature `datetime` let prefs = icu_host_info::datetime_preferences() .expect("Failed to retrieve host info"); let dtf = DateTimeFormatter::try_new(prefs, fieldsets::YMD::long()) .expect("Failed to create datetime formatter.");
For all components that icu_host_info does not have special preference getter for, and for cases where the user prefers to avoid pulling extra dependencies at the cost of narrowing down the retrieved values to just ones encoded in Unicode Extensions, the library provides an ergonomic getter:
use icu::{ datetime::{fieldsets, DateTimeFormatter}, locale::Locale, }; let mut locale = icu_host_info::requested_locales() .expect("Failed to retrieve locales") .first() .cloned() .unwrap_or(Locale::UNKNOWN); locale.extensions.unicode = icu_host_info::unicode_extensions() .expect("Failed to retrieve host info"); let dtf = DateTimeFormatter::try_new(locale.into(), fieldsets::YMD::long()) .expect("Failed to create datetime formatter.");
Notice that the regional preferences encoded in Unicode Extensions are retrieved separately from the list of requested locales. There are two reasons for this design:
For each preference the library also attempts to provide a direct getter allowing the user to retrieve just that preference and use it as they see fit.
use icu::locale::preferences::extensions::unicode::keywords::HourCycle; let mut calendar: Option<HourCycle> = icu_host_info::hour_cycle() .expect("Failed to retrieve hour_cycle preference");
Locale Negotiation is an upcoming feature in ICU4X which will enable the system integrating ICU to perform a negotiation between requested locales, and locales for which the data is available in the system. The output of icu_host_info will be utilized in that negotiation allowing the deployment to 1) select the most appropriate locales for the given user and target modality, 2) apply regional preferences onto that locale.
The need to allow icu_host_info to be pluggable into locale negotiation and multi source merging (see next section) guided many design choices in this library. This section will be extended once locale negotiation is implemented.
In simple systems the user will most often use ICU to format some information in a selected locale, and use this library to augment the formatting with regional preferences set by the user in the host environment.
In more complex systems, the user may also want to introduce a second source of regional preferences and mix the values set in the host environment with those set in the program itself.
For example, a web browser may offer some regional preferences set in the browser itself, or even set separate for some contexts of the browser.
In those cases, the deployment requires merging of the preferences. ICU exposes an extend method on both Preferences and Unicode extensions struct.
This allows the system to retrieve Preferences or Unicode, and the application's equivalent, and merge them.
Preferences Exampleuse icu_host_info::icu_host_info; use icu::datetime::{fieldsets, DateTimeFormatter}; let app_prefs = app.datetime_preferences(); // requires feature `datetime` let mut combined_prefs = icu_host_info::datetime_preferences() .expect("Failed to retrieve host info"); combined_prefs.extend(app_prefs); let dtf = DateTimeFormatter::try_new(combined_prefs, fieldsets::YMD::long()) .expect("Failed to create datetime formatter.");
Unicode Extensions Exampleuse icu_host_info::icu_host_info; use icu::{ datetime::{fieldsets, DateTimeFormatter}, locale::locale, }; let mut locale = locale!("fr-CA"); let app_ue = app.unicode_extensions(); let mut combined_ue = icu_host_info::unicode_extensions() .expect("Failed to retrieve host info"); combined_ue.extend(app_ue); locale.extensions.unicode = combined_ue; let dtf = DateTimeFormatter::try_new(locale.into(), fieldsets::YMD::long()) .expect("Failed to create datetime formatter.");
The library operates on a boundary of diverse set of host environments and uniform ICU design derived from Unicode LDML. It requires a number of design tradeoffs that had to be made in order to achieve the uniformity and scale over time as the host platforms design evolves.
The library is designed to handle retrieval of data from the direct host environment. This usually means an operating system, but it can mean a virtual environment, sandbox or runtime. In such a case it is the responsibility of the execution logic setting up such environment to ensure propagation of customer preferences.
The library makes best-effort to retrieve the values that can be directly used in ICU. As the operating systems, runtimes and ICU evolve, there's always a risk of a mismatch. This library makes a design decision to be lossy-by-default.
Any value that cannot be directly mapped onto a valid value is ignored and indistinguishable in the ergonomic API from a missing value.
Similarly, the API does not distinguish between missing binding logic and unknown value. The assumption is that users of this library are aiming to respect user choices encoded in host environment regional preferences, but are not in a position to act differently on a failed attempt to retrieve them from a missing attempt. Therefore errors in this library are very rare and only related to catastrophic cases like memory corruption or OS API errors propagation.
The library provides methods that return normalized values, often directly taken from icu::locale_core::preferences. Per-host backends provide additional trait implementation that returns raw values, allowing the user to handle or introspect those values manually. When using icu_host_info, the library performs best-effort to normalize and parse those raw values into canonical Unicode ICU representation, often discarding unknown values and values that fail to parse.
Those raw backends are not exposed in the main documentation.
use icu_host_info::backends::{ RawHostInfoBackend, macos::MacOSHostInfoBackend, }; let raw_cal: Option<String> = MacOSHostInfoBackend::raw_calendar() .expect("Failed to retrieve raw calendar");
The library attempts to use host APIs in a way that allows distinguishing between preference values that represent defaults for a given locale, from ones manually set by the user. In some cases, the host API does not allow for distinguishing of that, which may result in overly expressive locales such as en-US-ca-gregory (gregory being already a default calendar for en-US).
This, like other aspects of the library, operates on best-effort basis and may be further improved in the future releases as better bindings become available.
A note for host API designers - it is useful for foundational libraries such as this to expose APIs that enable us to distinguish between regional preferences values derived by the host from defaults of a locale, from cases when the value is explicitly set by the user. This distinction allows ICU to better serve in locale negotiations scenario where other-than-first locale may be used and the deployment should respect whether the user set a given preference explicitly or left it to the per-locale default.
For more information on development, authorship, contributing etc. please visit ICU4X home page.