use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct SimpleTranslationConfig {
pub enabled: bool,
pub target_lang: String,
pub source_lang: String,
pub api_url: String,
pub requests_per_second: f64,
pub max_text_length: usize,
pub cache_enabled: bool,
pub cache_ttl_seconds: u64,
}
impl Default for SimpleTranslationConfig {
fn default() -> Self {
Self {
enabled: true,
target_lang: "zh".to_string(),
source_lang: "auto".to_string(),
api_url: "http://localhost:1188/translate".to_string(),
requests_per_second: 1.0,
max_text_length: 3000,
cache_enabled: true,
cache_ttl_seconds: 3600,
}
}
}
impl SimpleTranslationConfig {
pub fn builder() -> ConfigBuilder {
ConfigBuilder::new()
}
pub fn from_env() -> Self {
let mut config = Self::default();
if let Ok(enabled) = std::env::var("TRANSLATION_ENABLED") {
config.enabled = enabled.parse().unwrap_or(true);
}
if let Ok(target_lang) = std::env::var("TRANSLATION_TARGET_LANG") {
config.target_lang = target_lang;
}
if let Ok(source_lang) = std::env::var("TRANSLATION_SOURCE_LANG") {
config.source_lang = source_lang;
}
if let Ok(api_url) = std::env::var("TRANSLATION_API_URL") {
config.api_url = api_url;
}
if let Ok(rate) = std::env::var("TRANSLATION_REQUESTS_PER_SECOND") {
config.requests_per_second = rate.parse().unwrap_or(1.0);
}
if let Ok(max_len) = std::env::var("TRANSLATION_MAX_TEXT_LENGTH") {
config.max_text_length = max_len.parse().unwrap_or(3000);
}
if let Ok(cache_enabled) = std::env::var("TRANSLATION_CACHE_ENABLED") {
config.cache_enabled = cache_enabled.parse().unwrap_or(true);
}
if let Ok(cache_ttl) = std::env::var("TRANSLATION_CACHE_TTL_SECONDS") {
config.cache_ttl_seconds = cache_ttl.parse().unwrap_or(3600);
}
config
}
pub fn quick(target_lang: &str, api_url: Option<&str>) -> Self {
Self {
target_lang: target_lang.to_string(),
api_url: api_url.unwrap_or("http://localhost:1188/translate").to_string(),
..Default::default()
}
}
pub fn validate(&self) -> Result<(), String> {
if self.target_lang.is_empty() {
return Err("Target language cannot be empty".to_string());
}
if self.api_url.is_empty() {
return Err("API URL cannot be empty".to_string());
}
if self.requests_per_second <= 0.0 {
return Err("Requests per second must be positive".to_string());
}
if self.max_text_length == 0 {
return Err("Max text length must be positive".to_string());
}
Ok(())
}
pub fn request_interval(&self) -> Duration {
Duration::from_secs_f64(1.0 / self.requests_per_second)
}
pub fn cache_ttl(&self) -> Duration {
Duration::from_secs(self.cache_ttl_seconds)
}
}
#[derive(Debug)]
pub struct ConfigBuilder {
config: SimpleTranslationConfig,
}
impl ConfigBuilder {
pub fn new() -> Self {
Self {
config: SimpleTranslationConfig::default(),
}
}
pub fn enabled(mut self, enabled: bool) -> Self {
self.config.enabled = enabled;
self
}
pub fn target_lang<S: Into<String>>(mut self, lang: S) -> Self {
self.config.target_lang = lang.into();
self
}
pub fn source_lang<S: Into<String>>(mut self, lang: S) -> Self {
self.config.source_lang = lang.into();
self
}
pub fn api_url<S: Into<String>>(mut self, url: S) -> Self {
self.config.api_url = url.into();
self
}
pub fn requests_per_second(mut self, rate: f64) -> Self {
self.config.requests_per_second = rate;
self
}
pub fn max_text_length(mut self, length: usize) -> Self {
self.config.max_text_length = length;
self
}
pub fn cache_enabled(mut self, enabled: bool) -> Self {
self.config.cache_enabled = enabled;
self
}
pub fn cache_ttl_seconds(mut self, seconds: u64) -> Self {
self.config.cache_ttl_seconds = seconds;
self
}
pub fn build(self) -> Result<SimpleTranslationConfig, String> {
self.config.validate()?;
Ok(self.config)
}
pub fn build_unchecked(self) -> SimpleTranslationConfig {
self.config
}
}
impl Default for ConfigBuilder {
fn default() -> Self {
Self::new()
}
}
pub struct SimpleConfigManager {
config: SimpleTranslationConfig,
}
impl SimpleConfigManager {
pub fn new() -> Self {
Self {
config: SimpleTranslationConfig::default(),
}
}
pub fn with_config(config: SimpleTranslationConfig) -> Self {
Self { config }
}
pub fn from_env() -> Self {
Self {
config: SimpleTranslationConfig::from_env(),
}
}
pub fn config(&self) -> &SimpleTranslationConfig {
&self.config
}
pub fn config_cloned(&self) -> SimpleTranslationConfig {
self.config.clone()
}
pub fn update_config(&mut self, config: SimpleTranslationConfig) {
self.config = config;
}
pub fn update_with_builder<F>(&mut self, f: F) -> Result<(), String>
where
F: FnOnce(ConfigBuilder) -> ConfigBuilder,
{
let builder = ConfigBuilder {
config: self.config.clone(),
};
let new_config = f(builder).build()?;
self.config = new_config;
Ok(())
}
pub fn validate(&self) -> Result<(), String> {
self.config.validate()
}
}
impl Default for SimpleConfigManager {
fn default() -> Self {
Self::new()
}
}
pub fn quick_config(target_lang: &str, api_url: Option<&str>) -> SimpleTranslationConfig {
SimpleTranslationConfig::quick(target_lang, api_url)
}
pub fn config_builder() -> ConfigBuilder {
ConfigBuilder::new()
}
pub fn load_config_from_env() -> SimpleTranslationConfig {
SimpleTranslationConfig::from_env()
}
pub fn validate_config(config: &SimpleTranslationConfig) -> Result<(), String> {
config.validate()
}
pub mod presets {
use super::*;
pub fn development() -> SimpleTranslationConfig {
SimpleTranslationConfig {
enabled: true,
target_lang: "zh".to_string(),
source_lang: "auto".to_string(),
api_url: "http://localhost:1188/translate".to_string(),
requests_per_second: 2.0,
max_text_length: 1000,
cache_enabled: true,
cache_ttl_seconds: 1800, }
}
pub fn production() -> SimpleTranslationConfig {
SimpleTranslationConfig {
enabled: true,
target_lang: "zh".to_string(),
source_lang: "auto".to_string(),
api_url: "http://localhost:1188/translate".to_string(),
requests_per_second: 1.0,
max_text_length: 3000,
cache_enabled: true,
cache_ttl_seconds: 3600, }
}
pub fn testing() -> SimpleTranslationConfig {
SimpleTranslationConfig {
enabled: false, target_lang: "zh".to_string(),
source_lang: "auto".to_string(),
api_url: "http://localhost:1188/translate".to_string(),
requests_per_second: 10.0, max_text_length: 500,
cache_enabled: false, cache_ttl_seconds: 300, }
}
pub fn high_performance() -> SimpleTranslationConfig {
SimpleTranslationConfig {
enabled: true,
target_lang: "zh".to_string(),
source_lang: "auto".to_string(),
api_url: "http://localhost:1188/translate".to_string(),
requests_per_second: 5.0,
max_text_length: 5000,
cache_enabled: true,
cache_ttl_seconds: 7200, }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = SimpleTranslationConfig::default();
assert!(config.enabled);
assert_eq!(config.target_lang, "zh");
assert_eq!(config.source_lang, "auto");
assert!(config.validate().is_ok());
}
#[test]
fn test_config_builder() {
let config = ConfigBuilder::new()
.target_lang("en")
.api_url("http://example.com/translate")
.requests_per_second(2.0)
.build()
.unwrap();
assert_eq!(config.target_lang, "en");
assert_eq!(config.api_url, "http://example.com/translate");
assert_eq!(config.requests_per_second, 2.0);
}
#[test]
fn test_quick_config() {
let config = SimpleTranslationConfig::quick("ja", Some("http://api.example.com"));
assert_eq!(config.target_lang, "ja");
assert_eq!(config.api_url, "http://api.example.com");
}
#[test]
fn test_config_validation() {
let mut config = SimpleTranslationConfig::default();
assert!(config.validate().is_ok());
config.target_lang = "".to_string();
assert!(config.validate().is_err());
config.target_lang = "zh".to_string();
config.requests_per_second = -1.0;
assert!(config.validate().is_err());
}
#[test]
fn test_config_manager() {
let mut manager = SimpleConfigManager::new();
assert!(manager.validate().is_ok());
let result = manager.update_with_builder(|builder| {
builder.target_lang("ko").requests_per_second(3.0)
});
assert!(result.is_ok());
assert_eq!(manager.config().target_lang, "ko");
assert_eq!(manager.config().requests_per_second, 3.0);
}
#[test]
fn test_presets() {
let dev_config = presets::development();
assert!(dev_config.enabled);
assert_eq!(dev_config.requests_per_second, 2.0);
let prod_config = presets::production();
assert_eq!(prod_config.max_text_length, 3000);
let test_config = presets::testing();
assert!(!test_config.enabled);
assert!(!test_config.cache_enabled);
}
#[test]
fn test_convenience_functions() {
let config = quick_config("fr", Some("http://api.example.com"));
assert_eq!(config.target_lang, "fr");
let builder = config_builder().target_lang("de");
let config = builder.build().unwrap();
assert_eq!(config.target_lang, "de");
}
#[test]
fn test_duration_helpers() {
let config = SimpleTranslationConfig::default();
let interval = config.request_interval();
assert_eq!(interval, Duration::from_secs(1));
let ttl = config.cache_ttl();
assert_eq!(ttl, Duration::from_secs(3600));
}
}