Spaces:
Paused
Paused
| # locale_manager.py | |
| """ | |
| Locale Manager - Manages locale files for the system | |
| """ | |
| import json | |
| from pathlib import Path | |
| from typing import Dict, List, Optional | |
| from datetime import datetime | |
| import sys | |
| from utils.logger import log_info, log_error, log_debug, log_warning | |
| class LocaleManager: | |
| """Manages locale files for TTS preprocessing and system-wide language support""" | |
| _cache: Dict[str, Dict] = {} | |
| _available_locales: Optional[List[Dict[str, str]]] = None | |
| def get_locale(cls, language: str) -> Dict: | |
| """Get locale data with caching""" | |
| if language not in cls._cache: | |
| cls._cache[language] = cls._load_locale(language) | |
| return cls._cache[language] | |
| def _load_locale(cls, language: str) -> Dict: | |
| """Load locale from file - accepts both 'tr' and 'tr-TR' formats""" | |
| base_path = Path(__file__).parent.parent / "locales" | |
| # First try exact match | |
| locale_file = base_path / f"{language}.json" | |
| # If not found and has region code, try without region (tr-TR -> tr) | |
| if not locale_file.exists() and '-' in language: | |
| language_code = language.split('-')[0] | |
| locale_file = base_path / f"{language_code}.json" | |
| if locale_file.exists(): | |
| try: | |
| with open(locale_file, 'r', encoding='utf-8') as f: | |
| data = json.load(f) | |
| log_debug(f"✅ Loaded locale file: {locale_file.name}") | |
| return data | |
| except Exception as e: | |
| log_error(f"Failed to load locale file {locale_file}", e) | |
| # Try English fallback | |
| fallback_file = base_path / "en.json" | |
| if fallback_file.exists(): | |
| try: | |
| with open(fallback_file, 'r', encoding='utf-8') as f: | |
| data = json.load(f) | |
| log_warning(f"⚠️ Using English fallback for locale: {language}") | |
| return data | |
| except: | |
| pass | |
| # Minimal fallback if no locale files exist | |
| log_warning(f"⚠️ No locale files found, using minimal fallback") | |
| return { | |
| "code": "tr", | |
| "locale_tag": "tr-TR", | |
| "name": "Türkçe", | |
| "english_name": "Turkish" | |
| } | |
| def list_available_locales(cls) -> List[str]: | |
| """List all available locale files""" | |
| base_path = Path(__file__).parent.parent / "locales" | |
| if not base_path.exists(): | |
| return ["en", "tr"] # Default locales | |
| return [f.stem for f in base_path.glob("*.json")] | |
| def get_available_locales_with_names(cls) -> List[Dict[str, str]]: | |
| """Get list of all available locales with their display names""" | |
| if cls._available_locales is not None: | |
| return cls._available_locales | |
| cls._available_locales = [] | |
| base_path = Path(__file__).parent.parent / "locales" | |
| if not base_path.exists(): | |
| # Return default locales if directory doesn't exist | |
| cls._available_locales = [ | |
| { | |
| "code": "tr-TR", | |
| "name": "Türkçe", | |
| "english_name": "Turkish" | |
| }, | |
| { | |
| "code": "en-US", | |
| "name": "English", | |
| "english_name": "English (US)" | |
| } | |
| ] | |
| return cls._available_locales | |
| # Load all locale files | |
| for locale_file in base_path.glob("*.json"): | |
| try: | |
| locale_code = locale_file.stem | |
| locale_data = cls.get_locale(locale_code) | |
| cls._available_locales.append({ | |
| "code": locale_code, | |
| "name": locale_data.get("name", locale_code), | |
| "english_name": locale_data.get("english_name", locale_code) | |
| }) | |
| log_info(f"✅ Loaded locale: {locale_code} - {locale_data.get('name', 'Unknown')}") | |
| except Exception as e: | |
| log_error(f"❌ Failed to load locale {locale_file}", e) | |
| # Sort by name for consistent ordering | |
| cls._available_locales.sort(key=lambda x: x['name']) | |
| return cls._available_locales | |
| def get_locale_details(cls, locale_code: str) -> Optional[Dict]: | |
| """Get detailed info for a specific locale""" | |
| try: | |
| locale_data = cls.get_locale(locale_code) | |
| # Ensure code is in the data | |
| locale_data['code'] = locale_code | |
| return locale_data | |
| except: | |
| return None | |
| def is_locale_supported(cls, locale_code: str) -> bool: | |
| """Check if a locale is supported system-wide""" | |
| available_codes = [locale['code'] for locale in cls.get_available_locales_with_names()] | |
| return locale_code in available_codes | |
| def validate_project_languages(cls, languages: List[str]) -> List[str]: | |
| """Validate that all languages are system-supported, return invalid ones""" | |
| available_codes = [locale['code'] for locale in cls.get_available_locales_with_names()] | |
| invalid_languages = [ | |
| lang for lang in languages | |
| if lang not in available_codes | |
| ] | |
| return invalid_languages | |
| def get_default_locale(cls) -> str: | |
| """Get system default locale""" | |
| available_locales = cls.get_available_locales_with_names() | |
| # Priority: tr-TR, en-US, first available | |
| for preferred in ["tr-TR", "en-US"]: | |
| if any(locale['code'] == preferred for locale in available_locales): | |
| return preferred | |
| # Return first available or fallback | |
| if available_locales: | |
| return available_locales[0]['code'] | |
| return "en-US" |