cloudpub_client/
i18n.rs

1use fluent::{FluentBundle, FluentResource};
2use fluent_bundle::FluentArgs;
3use std::sync::Mutex;
4use unic_langid::LanguageIdentifier;
5
6pub struct Localizer {
7    bundle: Mutex<FluentBundle<FluentResource>>,
8}
9
10unsafe impl Sync for Localizer {}
11unsafe impl Send for Localizer {}
12
13impl Default for Localizer {
14    fn default() -> Self {
15        Self::new()
16    }
17}
18
19impl Localizer {
20    pub fn new() -> Self {
21        let locale_content = include_str!(concat!(env!("OUT_DIR"), "/locale.ftl"));
22        let resource = FluentResource::try_new(locale_content.to_string())
23            .expect("Failed to parse locale resource");
24
25        let langid: LanguageIdentifier = if cfg!(locale = "ru") {
26            "ru".parse().expect("Failed to parse language identifier")
27        } else {
28            "en".parse().expect("Failed to parse language identifier")
29        };
30
31        let mut bundle = FluentBundle::new(vec![langid]);
32        bundle.set_use_isolating(false); // Disable BiDi isolation
33        bundle
34            .add_resource(resource)
35            .expect("Failed to add resource to bundle");
36
37        Self {
38            bundle: Mutex::new(bundle),
39        }
40    }
41
42    pub fn get(&self, key: &str) -> String {
43        self.get_with_args(key, None)
44    }
45
46    pub fn get_with_args(&self, key: &str, args: Option<&FluentArgs>) -> String {
47        let bundle = self.bundle.lock().unwrap();
48        let msg = bundle
49            .get_message(key)
50            .unwrap_or_else(|| panic!("Message '{}' not found", key));
51
52        let pattern = msg
53            .value()
54            .unwrap_or_else(|| panic!("Message '{}' has no value", key));
55
56        let mut errors = vec![];
57        let formatted = bundle.format_pattern(pattern, args, &mut errors);
58
59        if !errors.is_empty() {
60            eprintln!("Localization errors for key '{}': {:?}", key, errors);
61        }
62
63        formatted.to_string()
64    }
65}
66
67lazy_static::lazy_static! {
68    pub static ref LOCALIZER: Localizer = Localizer::new();
69}
70
71// Convenience macros for localization
72#[macro_export]
73macro_rules! t {
74    ($key:expr) => {
75        $crate::i18n::LOCALIZER.get($key)
76    };
77    ($key:expr, $($arg_key:expr => $arg_value:expr),*) => {{
78        let mut args = fluent_bundle::FluentArgs::new();
79        $(
80            args.set($arg_key, $arg_value);
81        )*
82        $crate::i18n::LOCALIZER.get_with_args($key, Some(&args))
83    }};
84}