rs_i18n/core/
load.rs

1use super::common::names::I18ns;
2use super::constants::{TARGET_CONFIG_NAME, TARGET_DIR};
3use serde_json::{self, Value};
4use std::fs;
5use std::sync::{Arc, Mutex};
6use std::{
7    env::{self, current_dir},
8    fs::{read_dir, File},
9    io::Read,
10    path::{Path, PathBuf},
11    str::FromStr,
12};
13
14/// I18n Loader
15/// It will load the configuration and i18n json files
16/// you can know target and sys language in this struct
17#[derive(Debug, Clone)]
18pub struct Loader {
19    sources: Vec<PathBuf>,
20    target: Arc<Mutex<I18ns>>,
21    sys_lang: I18ns,
22}
23
24impl Default for Loader {
25    fn default() -> Self {
26        Self {
27            sources: Default::default(),
28            target: Default::default(),
29            sys_lang: Default::default(),
30        }
31    }
32}
33
34impl Loader {
35    /// Build a new Loader with configurations
36    /// ## params
37    /// 1. path - `Option<&str>` : path to load i18n json files (absolute path see following)
38    /// ## absoulte path
39    /// if use absolute path, you should pay attention that the path should write from root
40    ///
41    /// means :
42    ///
43    /// It is an absolute path based on the root directory as the standard
44    ///
45    /// ````
46    /// -- your project
47    /// |---- src
48    /// |       |-- main.rs (write Loader::new(Some("./i18n")))
49    /// |---- i18n
50    /// |       |-- en_US.json
51    /// |       |-- zh_CN.json
52    /// ````
53    pub fn new(path: Option<&str>) -> Self {
54        let path = match path {
55            Some(p) => PathBuf::from(p),
56            None => Loader::get_configuration(),
57        };
58        Loader::load(path.as_path())
59    }
60    /// Build a new Loader with specified target source path
61    pub fn load(source: &Path) -> Self {
62        let sources = read_dir(source)
63            .unwrap()
64            .into_iter()
65            .map(|dir| dir.unwrap().path())
66            .collect::<Vec<PathBuf>>();
67        let sys_lang = Loader::get_sys_lang();
68        Loader {
69            sources,
70            target: Arc::new(Mutex::new(sys_lang.clone())),
71            sys_lang,
72        }
73    }
74    /// get system language from current system
75    pub fn get_sys_lang() -> I18ns {
76        // such as zh_CN.UTF-8
77        let lang = env::var("LANG").unwrap();
78        //get 5 char
79        let lang_spl = lang.split_at(5).0;
80        I18ns::from_str(lang_spl).unwrap()
81    }
82    /// get configuration and return source dir path
83    pub fn get_configuration() -> PathBuf {
84        let mut config_path = current_dir().unwrap();
85        config_path.push(TARGET_CONFIG_NAME);
86        match File::open(config_path.as_path()) {
87            Ok(mut file) => {
88                let mut buffer = String::new();
89                let _ = file.read_to_string(&mut buffer);
90                //parse config source path
91                let json_value: Value = serde_json::from_str(&buffer).unwrap();
92                let mut i18n_path = current_dir().unwrap();
93                match json_value.get("source") {
94                    Some(f_path) => {
95                        let f_path = fs::canonicalize(f_path.as_str().unwrap());
96                        i18n_path.push(f_path.unwrap().as_path())
97                    }
98                    None => i18n_path.push(TARGET_DIR),
99                };
100                i18n_path
101            }
102            Err(e) => panic!("{}", e),
103        }
104    }
105    pub fn set_target(&self, target: I18ns) {
106        let mut target_lock = self.target.lock().unwrap();
107        *target_lock = target;
108    }
109    pub fn target(&self) -> Arc<Mutex<I18ns>> {
110        Arc::clone(&self.target)
111    }
112    pub fn sources(&self) -> &Vec<PathBuf> {
113        &self.sources
114    }
115    pub fn sys_lang(&self) -> &I18ns {
116        &self.sys_lang
117    }
118}
119
120#[cfg(test)]
121mod test_loader {
122    use super::*;
123    #[test]
124    fn test_get_sys_lang() {
125        let lang = Loader::get_sys_lang();
126        dbg!(lang.to_string());
127    }
128    #[test]
129    fn test_new_loader() {
130        let loader = Loader::new(None);
131        dbg!(loader);
132    }
133    #[test]
134    fn test_load_loader() {
135        let loader = Loader::load(Path::new("E:\\Rust\\try\\rs-i18n-all\\i18n-test\\i18n"));
136        dbg!(loader);
137    }
138    #[test]
139    fn test_get_configuration() {
140        let loader = Loader::get_configuration();
141        dbg!(loader);
142    }
143}