flare / locale_manager.py
ciyidogan's picture
Update locale_manager.py
7af98e7 verified
raw
history blame
6.07 kB
# 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 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
@classmethod
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]
@classmethod
def _load_locale(cls, language: str) -> Dict:
"""Load locale from file - accepts both 'tr' and 'tr-TR' formats"""
base_path = Path(__file__).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"
}
@classmethod
def list_available_locales(cls) -> List[str]:
"""List all available locale files"""
base_path = Path(__file__).parent / "locales"
if not base_path.exists():
return ["en", "tr"] # Default locales
return [f.stem for f in base_path.glob("*.json")]
@classmethod
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 / "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
@classmethod
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
@classmethod
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
@classmethod
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
@classmethod
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"