fluent_fallback/
env.rs

1//! Traits required to provide environment driven data for [`Localization`](crate::Localization).
2//!
3//! Since [`Localization`](crate::Localization) is a long-lived structure,
4//! the model in which the user provides ability for the system to react to changes
5//! is by implementing the given environmental trait and triggering
6//! [`Localization::on_change`](crate::Localization::on_change) method.
7//!
8//! At the moment just a single trait is provided, which allows the
9//! environment to feed a selection of locales to be provided to the instance.
10//!
11//! The locales provided to [`Localization`](crate::Localization) should be
12//! already negotiated to ensure that the resources in those locales
13//! are available. The list should also be sorted according to the user
14//! preference, as the order is significant for how [`Localization`](crate::Localization) performs
15//! fallbacking.
16use unic_langid::LanguageIdentifier;
17
18/// A trait used to provide a selection of locales to be used by the
19/// [`Localization`](crate::Localization) instance for runtime
20/// locale fallbacking.
21///
22/// # Example
23/// ```
24/// use fluent_fallback::{Localization, env::LocalesProvider};
25/// use fluent_resmgr::ResourceManager;
26/// use unic_langid::LanguageIdentifier;
27/// use std::{
28///     rc::Rc,
29///     cell::RefCell
30/// };
31///
32/// #[derive(Clone)]
33/// struct Env {
34///     locales: Rc<RefCell<Vec<LanguageIdentifier>>>,
35/// }
36///
37/// impl Env {
38///     pub fn new(locales: Vec<LanguageIdentifier>) -> Self {
39///         Self { locales: Rc::new(RefCell::new(locales)) }
40///     }
41///
42///     pub fn set_locales(&mut self, new_locales: Vec<LanguageIdentifier>) {
43///         let mut locales = self.locales.borrow_mut();
44///         locales.clear();
45///         locales.extend(new_locales);
46///     }
47/// }
48///
49/// impl LocalesProvider for Env {
50///     type Iter = <Vec<LanguageIdentifier> as IntoIterator>::IntoIter;
51///     fn locales(&self) -> Self::Iter {
52///         self.locales.borrow().clone().into_iter()
53///     }
54/// }
55///
56/// let res_mgr = ResourceManager::new("./path/{locale}/".to_string());
57///
58/// let mut env = Env::new(vec![
59///     "en-GB".parse().unwrap()
60/// ]);
61///
62/// let mut loc = Localization::with_env(vec![], true, env.clone(), res_mgr);
63///
64/// env.set_locales(vec![
65///     "de".parse().unwrap(),
66///     "en-GB".parse().unwrap(),
67/// ]);
68///
69/// loc.on_change();
70///
71/// // The next format call will attempt to localize to `de` first and
72/// // fallback on `en-GB`.
73/// ```
74pub trait LocalesProvider {
75    type Iter: Iterator<Item = LanguageIdentifier>;
76    fn locales(&self) -> Self::Iter;
77}
78
79impl LocalesProvider for Vec<LanguageIdentifier> {
80    type Iter = <Vec<LanguageIdentifier> as IntoIterator>::IntoIter;
81    fn locales(&self) -> Self::Iter {
82        self.clone().into_iter()
83    }
84}