""" Flare – Parameter Validation (locale-aware) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Locale-based validation with multi-language support """ import re from typing import Any, Optional, List from datetime import datetime from config.config_models import ParameterConfig from config.locale_manager import LocaleManager from utils.logger import log_info, log_error, log_warning, log_debug def validate(value: str, param: ParameterConfig, locale: Optional[str] = None) -> bool: """Validate parameter value based on type and locale""" t = param.canonical_type() if t == "int": if not value.isdigit(): return False elif t == "float": try: float(value) except ValueError: return False elif t in ("str", "string"): pass # All strings are valid elif t == "bool": # Locale-aware boolean validation return validate_boolean(value, locale) elif t == "date": try: # Check if it's a valid ISO date format (YYYY-MM-DD) datetime.strptime(value, "%Y-%m-%d") except ValueError: return False # Regex validation if provided if param.validation_regex and not re.fullmatch(param.validation_regex, value, re.I): return False return True def validate_boolean(value: str, locale: Optional[str] = None) -> bool: """Validate boolean value based on locale""" # Default values (always accepted) default_true = ["1", "true"] default_false = ["0", "false"] value_lower = value.lower().strip() # Check default values first if value_lower in default_true or value_lower in default_false: return True # If no locale specified, use minimal validation if not locale: return value_lower in ["yes", "no", "evet", "hayır"] try: # Get locale data locale_data = LocaleManager.get_locale(locale) # Get boolean values from locale boolean_values = locale_data.get("boolean_values", {}) true_values = boolean_values.get("true_values", []) false_values = boolean_values.get("false_values", []) # Include synonyms if available yes_synonyms = boolean_values.get("yes_synonyms", []) no_synonyms = boolean_values.get("no_synonyms", []) # Combine all accepted values all_true_values = set(true_values + yes_synonyms + default_true) all_false_values = set(false_values + no_synonyms + default_false) # Convert to lowercase for comparison all_true_values = {v.lower() for v in all_true_values} all_false_values = {v.lower() for v in all_false_values} return value_lower in all_true_values or value_lower in all_false_values except Exception as e: log_error("⚠️ Error in locale-based boolean validation", e) # Fallback to basic validation return value_lower in ["yes", "no", "evet", "hayır", "1", "0", "true", "false"] def get_boolean_value(value: str, locale: Optional[str] = None) -> Optional[bool]: """Convert locale-specific boolean string to Python bool""" value_lower = value.lower().strip() # Default true values if value_lower in ["1", "true"]: return True if value_lower in ["0", "false"]: return False if not locale: # Basic conversion without locale if value_lower in ["yes", "evet"]: return True elif value_lower in ["no", "hayır"]: return False return None try: # Get locale data locale_data = LocaleManager.get_locale(locale) boolean_values = locale_data.get("boolean_values", {}) true_values = set(v.lower() for v in boolean_values.get("true_values", [])) false_values = set(v.lower() for v in boolean_values.get("false_values", [])) yes_synonyms = set(v.lower() for v in boolean_values.get("yes_synonyms", [])) no_synonyms = set(v.lower() for v in boolean_values.get("no_synonyms", [])) # Check if it's a true value if value_lower in true_values or value_lower in yes_synonyms or value_lower == "1": return True # Check if it's a false value if value_lower in false_values or value_lower in no_synonyms or value_lower == "0": return False return None except Exception as e: log_error("⚠️ Error converting boolean value", e) return None def get_supported_locales() -> List[str]: """Get list of supported locales for validation""" return LocaleManager.list_available_locales()