use std::path::{Path, PathBuf}; pub(crate) const LANG_MANIFEST_FILE: &str = "_manifest"; pub(crate) const LANG_EXTENSION: &str = "ron"; #[derive(Clone)] pub struct BasePath { ///repo part, git main folder root_path: PathBuf, ///relative path to i18n path which contains, currently /// 'assets/voxygen/i18n' relative_i18n_root_path: PathBuf, ///i18n_root_folder cache: PathBuf, } impl BasePath { pub fn new(root_path: &Path) -> Self { let relative_i18n_root_path = Path::new("assets/voxygen/i18n").to_path_buf(); let cache = root_path.join(&relative_i18n_root_path); assert!( cache.is_dir(), "i18n_root_path folder doesn't exist, something is wrong!" ); Self { root_path: root_path.to_path_buf(), relative_i18n_root_path, cache, } } pub fn root_path(&self) -> &Path { &self.root_path } pub fn relative_i18n_root_path(&self) -> &Path { &self.relative_i18n_root_path } /// absolute path to `relative_i18n_root_path` pub fn i18n_root_path(&self) -> &Path { &self.cache } pub fn i18n_path(&self, language_identifier: &str) -> LangPath { LangPath::new(self, language_identifier) } /// List localization directories pub fn i18n_directories(&self) -> Vec { std::fs::read_dir(&self.cache) .unwrap() .map(|res| res.unwrap()) .filter(|e| e.file_type().unwrap().is_dir()) .map(|e| LangPath::new(self, e.file_name().to_str().unwrap())) .collect() } } impl core::fmt::Debug for BasePath { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{:?}", &self.cache) } } #[derive(Clone)] pub struct LangPath { base: BasePath, /// `en`, `de_DE`, `fr_FR`, etc.. language_identifier: String, /// i18n_path cache: PathBuf, } impl LangPath { fn new(base: &BasePath, language_identifier: &str) -> Self { let cache = base.i18n_root_path().join(language_identifier); if !cache.is_dir() { panic!("language folder '{}' doesn't exist", language_identifier); } Self { base: base.clone(), language_identifier: language_identifier.to_owned(), cache, } } pub fn base(&self) -> &BasePath { &self.base } pub fn language_identifier(&self) -> &str { &self.language_identifier } ///absolute path to `i18n_root_path` + `language_identifier` pub fn i18n_path(&self) -> &Path { &self.cache } /// fragment or manifest file, based on a path pub fn sub_path(&self, sub_path: &Path) -> PathBuf { self.cache.join(sub_path) } /// fragment or manifest file, based on a string without extension pub fn file(&self, name_without_extension: &str) -> PathBuf { self.cache .join(format!("{}.{}", name_without_extension, LANG_EXTENSION)) } /// return all fragments sub_pathes pub(crate) fn fragments(&self) -> Result, std::io::Error> { let mut result = vec![]; recursive_fragments_paths_in_language(self, Path::new(""), &mut result)?; Ok(result) } } //unwraps cant fail as they are in same Path fn recursive_fragments_paths_in_language( lpath: &LangPath, subfolder: &Path, result: &mut Vec, ) -> Result<(), std::io::Error> { let manifest_path = PathBuf::from(&format!("{}.{}", LANG_MANIFEST_FILE, LANG_EXTENSION)); let template_path = PathBuf::from(&format!("{}.{}", "template", LANG_EXTENSION)); let search_dir = lpath.sub_path(subfolder); for fragment_file in search_dir.read_dir()?.flatten() { let file_type = fragment_file.file_type()?; let full_path = fragment_file.path(); let relative_path = full_path.strip_prefix(lpath.i18n_path()).unwrap(); if file_type.is_dir() { recursive_fragments_paths_in_language(lpath, relative_path, result)?; } else if file_type.is_file() && relative_path != manifest_path && relative_path != template_path { result.push(relative_path.to_path_buf()); } } Ok(()) } impl core::fmt::Debug for LangPath { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!( f, "{:?}", self.base .relative_i18n_root_path .join(&self.language_identifier) ) } }