1use sofie_core::Show;
2
3use crate::Mailer;
4
5#[cfg(feature = "i18n")]
6pub(crate) use spoken::{Language, Spoken, rendered};
7
8#[cfg(feature = "i18n")]
9pub use spoken::translations;
10
11#[cfg(not(feature = "i18n"))]
12pub(crate) use plain::{Language, rendered};
13
14#[cfg(feature = "i18n")]
15mod spoken {
16 use std::sync::Arc;
17
18 use sofie_core::Show;
19 use sofie_db::Db;
20 use sofie_engine::rendering::Rendering;
21 use sofie_engine::{Template, TemplateError, Translations};
22
23 pub(crate) type Language<'a> = sofie_engine::Language<'a>;
24
25 pub(crate) struct Spoken(pub(crate) Arc<Translations>);
26
27 pub fn translations(db: &Db, translations: Arc<Translations>) {
28 sofie_db::extend(db, Arc::new(Spoken(translations)));
29 }
30
31 pub(crate) fn rendered(
32 template: &Template,
33 data: &(impl Show + ?Sized),
34 language: Language<'_>,
35 ) -> Result<String, TemplateError> {
36 Rendering::new(template).language(language).render(data)
37 }
38}
39
40#[cfg(not(feature = "i18n"))]
41mod plain {
42 use std::marker::PhantomData;
43
44 use sofie_core::Show;
45 use sofie_engine::{Template, TemplateError};
46
47 #[derive(Clone, Copy)]
48 pub(crate) struct Language<'a>(PhantomData<&'a ()>);
49
50 impl Language<'_> {
51 pub(crate) fn plain() -> Self {
52 Self(PhantomData)
53 }
54 }
55
56 pub(crate) fn rendered(
57 template: &Template,
58 data: &(impl Show + ?Sized),
59 _language: Language<'_>,
60 ) -> Result<String, TemplateError> {
61 template.render(data)
62 }
63}
64
65impl Mailer {
66 #[cfg(feature = "i18n")]
68 #[must_use]
69 pub fn in_language(mut self, locale: Option<sofie_values::Locale>) -> Self {
70 self.locale = locale;
71 self
72 }
73
74 #[must_use]
76 pub fn text(&self, key: &str, arguments: &[(&str, String)], fallback: &str) -> String {
77 #[cfg(feature = "i18n")]
78 return self.language().field_error(key, arguments, fallback);
79 #[cfg(not(feature = "i18n"))]
80 {
81 let _ = (key, arguments);
82 fallback.to_owned()
83 }
84 }
85
86 #[cfg(feature = "i18n")]
87 pub(crate) fn language(&self) -> Language<'_> {
88 match &self.translations {
89 Some(translations) => translations.negotiate(self.locale.as_ref(), None),
90 None => Language::plain(),
91 }
92 }
93
94 #[cfg(not(feature = "i18n"))]
95 #[expect(
96 clippy::unused_self,
97 reason = "under the `i18n` feature the mailer holds the translations"
98 )]
99 pub(crate) fn language(&self) -> Language<'_> {
100 Language::plain()
101 }
102
103 pub(crate) fn render(
104 &self,
105 template: &crate::Template,
106 data: &(impl Show + ?Sized),
107 ) -> sofie_core::Result<crate::Body> {
108 template.render(data, self.language())
109 }
110}