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); 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#[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}