use crate::registry::StaticFluentMessageKey;
use es_fluent_manager_core::FluentManager;
use std::sync::Arc;
use super::{FluentArgs, FluentLocalizerLookup, FluentMessageLookup};
const WITH_LOOKUP_CALLBACK_COUNT_ERROR: &str =
"FluentLocalizer::with_lookup must invoke its callback exactly once";
pub trait FluentMessage {
fn to_fluent_string_with(&self, localize: &mut FluentMessageLookup<'_>) -> String;
}
#[diagnostic::do_not_recommend]
impl<T: FluentMessage + ?Sized> FluentMessage for &T {
fn to_fluent_string_with(&self, localize: &mut FluentMessageLookup<'_>) -> String {
(**self).to_fluent_string_with(localize)
}
}
pub trait FluentLocalizer {
fn localize<'a>(
&self,
key: StaticFluentMessageKey,
args: Option<&'a FluentArgs<'a>>,
) -> Option<String>;
fn with_lookup(&self, f: &mut dyn FnMut(&mut FluentLocalizerLookup<'_>)) {
let mut lookup =
|key: StaticFluentMessageKey, args: Option<&FluentArgs<'_>>| self.localize(key, args);
f(&mut lookup);
}
}
impl FluentLocalizer for FluentManager {
fn localize<'a>(
&self,
key: StaticFluentMessageKey,
args: Option<&FluentArgs<'a>>,
) -> Option<String> {
FluentManager::localize(self, key, args.map(FluentArgs::as_raw))
}
fn with_lookup(&self, f: &mut dyn FnMut(&mut FluentLocalizerLookup<'_>)) {
FluentManager::with_lookup(self, &mut |lookup| {
let mut typed_lookup = |key: StaticFluentMessageKey, args: Option<&FluentArgs<'_>>| {
lookup(key, args.map(FluentArgs::as_raw))
};
f(&mut typed_lookup);
});
}
}
impl<T: FluentLocalizer + ?Sized> FluentLocalizer for &T {
fn localize<'a>(
&self,
key: StaticFluentMessageKey,
args: Option<&FluentArgs<'a>>,
) -> Option<String> {
(**self).localize(key, args)
}
fn with_lookup(&self, f: &mut dyn FnMut(&mut FluentLocalizerLookup<'_>)) {
(**self).with_lookup(f);
}
}
impl<T: FluentLocalizer + ?Sized> FluentLocalizer for Arc<T> {
fn localize<'a>(
&self,
key: StaticFluentMessageKey,
args: Option<&FluentArgs<'a>>,
) -> Option<String> {
(**self).localize(key, args)
}
fn with_lookup(&self, f: &mut dyn FnMut(&mut FluentLocalizerLookup<'_>)) {
(**self).with_lookup(f);
}
}
pub trait FluentLocalizerExt: FluentLocalizer {
fn try_localize_message<T>(&self, message: &T) -> Option<String>
where
T: FluentMessage + ?Sized,
{
let mut missing = false;
let mut value = None;
let mut callback_invocations = 0;
self.with_lookup(&mut |lookup| {
assert!(
callback_invocations == 0,
"{}",
WITH_LOOKUP_CALLBACK_COUNT_ERROR
);
callback_invocations = 1;
value = Some(message.to_fluent_string_with(&mut |key, args| {
lookup(key, args).unwrap_or_else(|| {
missing = true;
String::new()
})
}));
});
assert!(
callback_invocations == 1,
"{}",
WITH_LOOKUP_CALLBACK_COUNT_ERROR
);
let value = value.expect(WITH_LOOKUP_CALLBACK_COUNT_ERROR);
if missing { None } else { Some(value) }
}
fn localize_message<T>(&self, message: &T) -> String
where
T: FluentMessage + ?Sized,
{
let mut value = None;
let mut callback_invocations = 0;
self.with_lookup(&mut |lookup| {
assert!(
callback_invocations == 0,
"{}",
WITH_LOOKUP_CALLBACK_COUNT_ERROR
);
callback_invocations = 1;
value = Some(message.to_fluent_string_with(&mut |key, args| {
lookup(key, args)
.unwrap_or_else(|| super::super::missing_fluent_value(key, "message"))
}));
});
assert!(
callback_invocations == 1,
"{}",
WITH_LOOKUP_CALLBACK_COUNT_ERROR
);
value.expect(WITH_LOOKUP_CALLBACK_COUNT_ERROR)
}
}
impl<T: FluentLocalizer + ?Sized> FluentLocalizerExt for T {}