#[cfg(feature = "handlebars")]
mod handlebars;
#[cfg(feature = "tera")]
mod tera;
mod multi_loader;
mod shared;
use std::borrow::Cow;
use std::collections::HashMap;
use crate::FluentBundle;
use fluent_bundle::{FluentArgs, FluentResource, FluentValue};
use fluent_langneg::negotiate_languages;
pub use unic_langid::{langid, langids, LanguageIdentifier};
mod arc_loader;
mod static_loader;
pub use arc_loader::{ArcLoader, ArcLoaderBuilder};
pub use multi_loader::MultiLoader;
pub use static_loader::StaticLoader;
pub trait Loader {
fn lookup(&self, lang: &LanguageIdentifier, text_id: &str) -> String {
self.lookup_complete(lang, text_id, None)
}
fn lookup_with_args(
&self,
lang: &LanguageIdentifier,
text_id: &str,
args: &HashMap<Cow<'static, str>, FluentValue>,
) -> String {
self.lookup_complete(lang, text_id, Some(args))
}
fn lookup_complete(
&self,
lang: &LanguageIdentifier,
text_id: &str,
args: Option<&HashMap<Cow<'static, str>, FluentValue>>,
) -> String;
fn try_lookup(&self, lang: &LanguageIdentifier, text_id: &str) -> Option<String> {
self.try_lookup_complete(lang, text_id, None)
}
fn try_lookup_with_args(
&self,
lang: &LanguageIdentifier,
text_id: &str,
args: &HashMap<Cow<'static, str>, FluentValue>,
) -> Option<String> {
self.try_lookup_complete(lang, text_id, Some(args))
}
fn try_lookup_complete(
&self,
lang: &LanguageIdentifier,
text_id: &str,
args: Option<&HashMap<Cow<'static, str>, FluentValue>>,
) -> Option<String>;
fn locales(&self) -> Box<dyn Iterator<Item = &LanguageIdentifier> + '_>;
}
impl<L> Loader for std::sync::Arc<L>
where
L: Loader,
{
fn lookup_complete(
&self,
lang: &LanguageIdentifier,
text_id: &str,
args: Option<&HashMap<Cow<'static, str>, FluentValue>>,
) -> String {
L::lookup_complete(self, lang, text_id, args)
}
fn try_lookup_complete(
&self,
lang: &LanguageIdentifier,
text_id: &str,
args: Option<&HashMap<Cow<'static, str>, FluentValue>>,
) -> Option<String> {
L::try_lookup_complete(self, lang, text_id, args)
}
fn locales(&self) -> Box<dyn Iterator<Item = &LanguageIdentifier> + '_> {
L::locales(self)
}
}
impl<'a, L> Loader for &'a L
where
L: Loader,
{
fn lookup_complete(
&self,
lang: &LanguageIdentifier,
text_id: &str,
args: Option<&HashMap<Cow<'static, str>, FluentValue>>,
) -> String {
L::lookup_complete(self, lang, text_id, args)
}
fn try_lookup_complete(
&self,
lang: &LanguageIdentifier,
text_id: &str,
args: Option<&HashMap<Cow<'static, str>, FluentValue>>,
) -> Option<String> {
L::try_lookup_complete(self, lang, text_id, args)
}
fn locales(&self) -> Box<dyn Iterator<Item = &LanguageIdentifier> + '_> {
L::locales(self)
}
}
pub struct FluentLoader<L> {
loader: L,
#[allow(unused)]
default_lang: Option<LanguageIdentifier>,
}
impl<L> FluentLoader<L> {
pub fn new(loader: L) -> Self {
Self {
loader,
default_lang: None,
}
}
pub fn with_default_lang(self, lang: LanguageIdentifier) -> Self {
Self {
loader: self.loader,
default_lang: Some(lang),
}
}
}
pub fn build_fallbacks(
locales: &[LanguageIdentifier],
) -> HashMap<LanguageIdentifier, Vec<LanguageIdentifier>> {
let mut map = HashMap::new();
for locale in locales.iter() {
map.insert(
locale.to_owned(),
negotiate_languages(
&[locale],
locales,
None,
fluent_langneg::NegotiationStrategy::Filtering,
)
.into_iter()
.cloned()
.collect::<Vec<_>>(),
);
}
map
}
fn create_bundle(
lang: LanguageIdentifier,
resources: &'static [FluentResource],
core_resource: Option<&'static FluentResource>,
customizer: &impl Fn(&mut FluentBundle<&'static FluentResource>),
) -> FluentBundle<&'static FluentResource> {
let mut bundle: FluentBundle<&'static FluentResource> =
FluentBundle::new_concurrent(vec![lang]);
if let Some(core) = core_resource {
bundle
.add_resource(core)
.expect("Failed to add core resource to bundle");
}
for res in resources {
bundle
.add_resource(res)
.expect("Failed to add FTL resources to the bundle.");
}
customizer(&mut bundle);
bundle
}
pub fn build_bundles(
resources: &'static HashMap<LanguageIdentifier, Vec<FluentResource>>,
core_resource: Option<&'static FluentResource>,
customizer: impl Fn(&mut FluentBundle<&'static FluentResource>),
) -> HashMap<LanguageIdentifier, FluentBundle<&'static FluentResource>> {
let mut bundles = HashMap::new();
for (k, v) in resources.iter() {
bundles.insert(
k.clone(),
create_bundle(k.clone(), v, core_resource, &customizer),
);
}
bundles
}
fn map_to_fluent_args<'map, T: AsRef<str>>(map: &'map HashMap<T, FluentValue>) -> FluentArgs<'map> {
map.iter()
.map(|(key, value)| (key.as_ref(), value.clone()))
.collect()
}