es_fluent_manager_core/
localization.rs1use es_fluent_derive_core::EsFluentError;
4use fluent_bundle::FluentValue;
5use std::collections::HashMap;
6use unic_langid::LanguageIdentifier;
7
8pub type LocalizationError = EsFluentError;
9
10pub trait Localizer: Send + Sync {
11 fn select_language(
13 &self,
14 lang: &LanguageIdentifier,
15 ) -> es_fluent_derive_core::EsFluentResult<()>;
16 fn localize<'a>(
18 &self,
19 id: &str,
20 args: Option<&HashMap<&str, FluentValue<'a>>>,
21 ) -> Option<String>;
22}
23
24pub trait I18nModule: Send + Sync {
25 fn name(&self) -> &'static str;
27 fn create_localizer(&self) -> Box<dyn Localizer>;
29}
30
31inventory::collect!(&'static dyn I18nModule);
32
33#[derive(Default)]
35pub struct FluentManager {
36 localizers: Vec<Box<dyn Localizer>>,
37}
38
39impl Clone for FluentManager {
40 fn clone(&self) -> Self {
41 Self::new_with_discovered_modules()
42 }
43}
44
45impl FluentManager {
46 pub fn new_with_discovered_modules() -> Self {
48 let mut manager = Self::default();
49 for module in inventory::iter::<&'static dyn I18nModule>() {
50 tracing::info!("Discovered and loading i18n module: {}", module.name());
51 manager.localizers.push(module.create_localizer());
52 }
53 manager
54 }
55
56 pub fn select_language(&self, lang: &LanguageIdentifier) {
58 for localizer in &self.localizers {
59 if let Err(e) = localizer.select_language(lang) {
60 tracing::warn!("Module failed to set language '{}': {}", lang, e);
61 }
62 }
63 }
64
65 pub fn localize<'a>(
67 &self,
68 id: &str,
69 args: Option<&HashMap<&str, FluentValue<'a>>>,
70 ) -> Option<String> {
71 for localizer in &self.localizers {
72 if let Some(message) = localizer.localize(id, args) {
73 return Some(message);
74 }
75 }
76 None
77 }
78}