fluent_templates/loader/
static_loader.rs

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use std::borrow::Cow;
use std::collections::HashMap;

use crate::{error::LookupError, languages::negotiate_languages, FluentBundle};
use fluent_bundle::{FluentResource, FluentValue};

pub use unic_langid::LanguageIdentifier;

/// A simple Loader implementation, with statically-loaded fluent data.
/// Typically created with the [`static_loader!`] macro
///
/// [`static_loader!`]: ./macro.static_loader.html
pub struct StaticLoader {
    bundles: &'static HashMap<LanguageIdentifier, FluentBundle<&'static FluentResource>>,
    fallbacks: &'static HashMap<LanguageIdentifier, Vec<LanguageIdentifier>>,
    fallback: LanguageIdentifier,
}

impl StaticLoader {
    /// Construct a new `StaticLoader`.
    ///
    /// This is exposed as publicly so that it can be used inside the
    /// `static_loader!` macro. it's not meant to be called directly.
    #[doc(hidden)]
    pub fn new(
        bundles: &'static HashMap<LanguageIdentifier, FluentBundle<&'static FluentResource>>,
        fallbacks: &'static HashMap<LanguageIdentifier, Vec<LanguageIdentifier>>,
        fallback: LanguageIdentifier,
    ) -> Self {
        Self {
            bundles,
            fallbacks,
            fallback,
        }
    }

    /// Convenience function to look up a string for a single language
    pub fn lookup_single_language<S: AsRef<str>>(
        &self,
        lang: &LanguageIdentifier,
        text_id: &str,
        args: Option<&HashMap<S, FluentValue>>,
    ) -> Result<String, LookupError> {
        super::shared::lookup_single_language(self.bundles, lang, text_id, args)
    }

    /// Convenience function to look up a string without falling back to the
    /// default fallback language
    pub fn lookup_no_default_fallback<S: AsRef<str>>(
        &self,
        lang: &LanguageIdentifier,
        text_id: &str,
        args: Option<&HashMap<S, FluentValue>>,
    ) -> Option<String> {
        super::shared::lookup_no_default_fallback(self.bundles, self.fallbacks, lang, text_id, args)
    }

    /// Return the fallback language
    pub fn fallback(&self) -> &LanguageIdentifier {
        &self.fallback
    }
}

impl super::Loader for StaticLoader {
    // Traverse the fallback chain,
    fn lookup_complete(
        &self,
        lang: &LanguageIdentifier,
        text_id: &str,
        args: Option<&HashMap<Cow<'static, str>, FluentValue>>,
    ) -> String {
        for lang in negotiate_languages(&[lang], &self.bundles.keys().collect::<Vec<_>>(), None) {
            if let Ok(val) = self.lookup_single_language(lang, text_id, args) {
                return val;
            }
        }

        if *lang != self.fallback {
            if let Ok(val) = self.lookup_single_language(&self.fallback, text_id, args) {
                return val;
            }
        }
        format!("Unknown localization {text_id}")
    }

    // Traverse the fallback chain,
    fn try_lookup_complete(
        &self,
        lang: &LanguageIdentifier,
        text_id: &str,
        args: Option<&HashMap<Cow<'static, str>, FluentValue>>,
    ) -> Option<String> {
        for lang in negotiate_languages(&[lang], &self.bundles.keys().collect::<Vec<_>>(), None) {
            if let Ok(val) = self.lookup_single_language(lang, text_id, args) {
                return Some(val);
            }
        }

        if *lang != self.fallback {
            if let Ok(val) = self.lookup_single_language(&self.fallback, text_id, args) {
                return Some(val);
            }
        }
        None
    }

    fn locales(&self) -> Box<dyn Iterator<Item = &LanguageIdentifier> + '_> {
        Box::new(self.fallbacks.keys())
    }
}