The intl-memoizer crate is designed to manage the memoization of expensive, read-only internationalization (intl) formatters like PluralRules or DateTimeFormat.
Mental Model
- Cost Assumption: Creating a new formatter instance is assumed to be expensive, while calling its
format or select methods is cheap. - Hierarchy:
IntlMemoizer: A main memoizer that holds weak references to per-language memoizers. It acts as a singleton to manage instances across all FluentBundle instances.IntlLangMemoizer: A per-locale memoizer that manages the actual instances for a specific language.
- Workflow:
- Implement the
Memoizable trait for your formatter type. - Use
IntlMemoizer::default() to create the main memoizer. - Use
get_for_lang(lang) to retrieve an Rc<IntlLangMemoizer> for a specific locale. - Use
with_try_get::<FormatterType, _, _>(options, closure) to lazily construct and run the formatter. Subsequent calls with the same options will reuse the existing instance.
/// Internationalization formatter should implement the Memoizable trait.
impl Memoizable for NumberFormat {
...
}
// The main memoizer has weak references to all of the per-language memoizers.
let mut memoizer = IntlMemoizer::default();
// The formatter memoization happens per-locale.
let lang = "en-US".parse().expect("Failed to parse.");
let lang_memoizer: Rc<IntlLangMemoizer> = memoizer.get_for_lang(lang);
// Run the formatter
let options: NumberFormatOptions = NumberFormatOptions {
minimum_fraction_digits: 3,
maximum_fraction_digits: 5,
};
// Format pi with the options. This will lazily construct the NumberFormat.
let pi = lang_memoizer
.with_try_get::<NumberFormat, _, _>((options,), |nf| nf.format(3.141592653))
.unwrap();
// Running it again with the same options will use the previous formatter.
let two = lang_memoizer
.with_try_get::<NumberFormat, _, _>((options,), |nf| nf.format(2.0))
.unwrap();