intl_rs/
lib.rs

1use lazy_static::lazy_static;
2use serde_json::Value;
3use std::sync::Arc;
4use std::{collections::HashMap, env};
5use string_template::Template;
6use structs::I18n;
7
8pub use structs::TranslationConfig;
9
10mod structs;
11
12static RESOURCES_KEY: &'static str = "INTL_RS_RESOURCES";
13
14static DEFAULT_LANGUAGE: &'static str = "INTL_RS_LANG";
15
16lazy_static! {
17    pub static ref I18N: Arc<I18n> = {
18        let resources_path = env::var(RESOURCES_KEY).unwrap_or("src/i18n".to_owned());
19        let default_language = env::var(DEFAULT_LANGUAGE).unwrap_or("en".to_owned());
20        let inner = I18n::init(resources_path, default_language);
21        Arc::new(inner)
22    };
23}
24
25pub fn format_message<S: Into<String>>(key: S, config: Option<&TranslationConfig>) -> String {
26    let key = key.into();
27    let default_config = TranslationConfig::default();
28    let TranslationConfig {
29        accept_language,
30        default_message,
31        args,
32    } = config.unwrap_or(&default_config);
33    let common_languages = accept_language::intersection(
34        accept_language.as_ref().unwrap_or(&I18N.default_language),
35        I18N.supported_languages.iter().map(|s| s as &str).collect(),
36    );
37    let language = common_languages
38        .first()
39        .expect("No supported language can be found");
40    let configs: &Value = &I18N.inner[language];
41
42    let template_string = match key
43        .split('.')
44        .fold(configs, |result: &Value, k| &result[&k])
45    {
46        Value::Null => default_message.clone(),
47        message => message.as_str().map(|other_str| other_str.to_string()),
48    }
49    .unwrap_or(key.to_string());
50    let template = Template::new(&template_string);
51    template.render(
52        &args
53            .as_ref()
54            .unwrap_or(&HashMap::new())
55            .iter()
56            .map(|(a, b)| (a.as_str(), b.as_str()))
57            .collect(),
58    )
59}
60
61#[macro_export]
62macro_rules! t {
63    ($key:expr) => {
64        $crate::format_message($key, None)
65    };
66    ($key:expr,accept_language:$accept_language:expr) => {
67        $crate::format_message(
68            $key,
69            Some(&$crate::TranslationConfig {
70                accept_language: Some($accept_language.into()),
71                ..Default::default()
72            }),
73        )
74    };
75    ($key:expr,accept_language:$accept_language:expr,args:$args:expr) => {
76        $crate::format_message(
77            $key,
78            Some(&$crate::TranslationConfig {
79                accept_language: Some($accept_language.into()),
80                args: Some($args),
81                ..Default::default()
82            }),
83        )
84    };
85    ($key:expr,config:$config:expr) => {
86        $crate::format_message($key, Some($config))
87    };
88}