use std::process::exit; use mingling::{ macros::{gen_program, help, r_println, renderer}, res::ResExitCode, }; pub mod output; pub mod res; pub mod tokio_wrapper; mod bucket_mgr; use bucket_mgr::*; mod error; use error::*; use crate::output::display::markdown; pub const EC_COMMAND_NOT_FOUND: i32 = 1000; #[help] fn help_global(_err: ErrorDispatcherNotFound) { let help = locale::helps::Basic::help().trim(); // Print directly to stderr and exit with code 0 eprintln!("{}", markdown(help)); exit(0) } #[renderer] fn render_error_dispatch_not_found(err: ErrorDispatcherNotFound, ec: &mut ResExitCode) { if !err.inner.is_empty() { let cmd_str = err.inner.join(" "); r_println!( "{}", markdown(locale::errors::Common::command_not_found(cmd_str).trim()) ); ec.exit_code = EC_COMMAND_NOT_FOUND; } } gen_program!(); pub mod locale { shakehand::locale!("locales"); /// Determines the current locale string used by the application. /// /// The locale is resolved by checking environment variables in the following /// priority order: /// 1. `JV_LANG` — application-specific variable. /// 2. `APP_LANG` — general application language override. /// 3. `LANG` — system locale (e.g. `en_US.UTF-8`). If this variable contains a /// character encoding suffix (e.g. `.UTF-8`), only the base part is kept, /// and underscores (`_`) are replaced with hyphens (`-`) to form a /// language tag (e.g. `en-US`). /// 4. Falls back to `"en"` if none of the above are set. pub fn current_locales() -> String { if let Ok(lang) = std::env::var("JV_LANG") { return lang; } if let Ok(lang) = std::env::var("APP_LANG") { return lang; } if let Ok(lang) = std::env::var("LANG") { if let Some(base_lang) = lang.split('.').next() { return base_lang.replace('_', "-"); } return lang; } "en".to_string() } }