1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use std::borrow::Borrow;
use std::borrow::Cow;

use fluent_bundle::FluentResource;
use fluent_bundle::{FluentArgs, FluentBundle};

use reiterate::Reiterate;

struct FluentBundleIterator<'loc, R> {
    iter: Box<dyn Iterator<Item = FluentBundle<R>> + 'loc>,
}

impl<'loc, R> Iterator for FluentBundleIterator<'loc, R> {
    type Item = Box<FluentBundle<R>>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(Box::new)
    }
}

pub struct Localization<'loc, R> {
    pub resource_ids: Vec<String>,
    bundles: Reiterate<FluentBundleIterator<'loc, R>>,
    generate_bundles: Box<dyn FnMut(&[String]) -> FluentBundleIterator<'loc, R> + 'loc>,
}

impl<'loc, R> Localization<'loc, R> {
    pub fn new<F, I>(resource_ids: Vec<String>, mut generate_bundles: F) -> Self
    where
        F: FnMut(&[String]) -> I + 'loc,
        I: Iterator<Item = FluentBundle<R>> + 'loc,
    {
        let mut generate2 = move |x: &[String]| FluentBundleIterator {
            iter: Box::new(generate_bundles(x)),
        };
        let bundles = Reiterate::new(generate2(&resource_ids));
        Localization {
            resource_ids,
            bundles,
            generate_bundles: Box::new(generate2),
        }
    }

    pub fn on_change(&mut self) {
        self.bundles = Reiterate::new((self.generate_bundles)(&self.resource_ids));
    }

    pub fn format_value<'l>(&'l mut self, id: &'l str, args: Option<&'l FluentArgs>) -> Cow<'l, str>
    where
        R: Borrow<FluentResource>,
    {
        for bundle in &self.bundles {
            if let Some(msg) = bundle.get_message(id) {
                if let Some(pattern) = msg.value {
                    let mut errors = vec![];
                    return bundle.format_pattern(pattern, args, &mut errors);
                }
            }
        }
        id.into()
    }
}