mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
- Created zh-CN.json and zh-TW.json for Simplified and Traditional Chinese translations respectively. - Added comprehensive test suite in test_i18n.py to validate JSON structure, server-side i18n functionality, and translation completeness across multiple languages.
115 lines
4.1 KiB
Python
115 lines
4.1 KiB
Python
import os
|
|
import json
|
|
import logging
|
|
from typing import Dict, Any, Optional
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class ServerI18nManager:
|
|
"""Server-side internationalization manager for template rendering"""
|
|
|
|
def __init__(self):
|
|
self.translations = {}
|
|
self.current_locale = 'en'
|
|
self._load_translations()
|
|
|
|
def _load_translations(self):
|
|
"""Load all translation files from the locales directory"""
|
|
i18n_path = os.path.join(
|
|
os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
|
|
'locales'
|
|
)
|
|
|
|
if not os.path.exists(i18n_path):
|
|
logger.warning(f"I18n directory not found: {i18n_path}")
|
|
return
|
|
|
|
# Load all available locale files
|
|
for filename in os.listdir(i18n_path):
|
|
if filename.endswith('.json'):
|
|
locale_code = filename[:-5] # Remove .json extension
|
|
try:
|
|
self._load_locale_file(i18n_path, filename, locale_code)
|
|
except Exception as e:
|
|
logger.error(f"Error loading locale file {filename}: {e}")
|
|
|
|
def _load_locale_file(self, path: str, filename: str, locale_code: str):
|
|
"""Load a single locale JSON file"""
|
|
file_path = os.path.join(path, filename)
|
|
|
|
try:
|
|
with open(file_path, 'r', encoding='utf-8') as f:
|
|
translations = json.load(f)
|
|
|
|
self.translations[locale_code] = translations
|
|
logger.debug(f"Loaded translations for {locale_code} from {filename}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error parsing locale file {filename}: {e}")
|
|
|
|
def set_locale(self, locale: str):
|
|
"""Set the current locale"""
|
|
if locale in self.translations:
|
|
self.current_locale = locale
|
|
else:
|
|
logger.warning(f"Locale {locale} not found, using 'en'")
|
|
self.current_locale = 'en'
|
|
|
|
def get_translation(self, key: str, params: Dict[str, Any] = None, **kwargs) -> str:
|
|
"""Get translation for a key with optional parameters (supports both dict and keyword args)"""
|
|
# Merge kwargs into params for convenience
|
|
if params is None:
|
|
params = {}
|
|
if kwargs:
|
|
params = {**params, **kwargs}
|
|
|
|
if self.current_locale not in self.translations:
|
|
return key
|
|
|
|
# Navigate through nested object using dot notation
|
|
keys = key.split('.')
|
|
value = self.translations[self.current_locale]
|
|
|
|
for k in keys:
|
|
if isinstance(value, dict) and k in value:
|
|
value = value[k]
|
|
else:
|
|
# Fallback to English if current locale doesn't have the key
|
|
if self.current_locale != 'en' and 'en' in self.translations:
|
|
en_value = self.translations['en']
|
|
for k in keys:
|
|
if isinstance(en_value, dict) and k in en_value:
|
|
en_value = en_value[k]
|
|
else:
|
|
return key
|
|
value = en_value
|
|
else:
|
|
return key
|
|
break
|
|
|
|
if not isinstance(value, str):
|
|
return key
|
|
|
|
# Replace parameters if provided
|
|
if params:
|
|
for param_key, param_value in params.items():
|
|
placeholder = f"{{{param_key}}}"
|
|
double_placeholder = f"{{{{{param_key}}}}}"
|
|
value = value.replace(placeholder, str(param_value))
|
|
value = value.replace(double_placeholder, str(param_value))
|
|
|
|
return value
|
|
|
|
def get_available_locales(self) -> list:
|
|
"""Get list of available locales"""
|
|
return list(self.translations.keys())
|
|
|
|
def create_template_filter(self):
|
|
"""Create a Jinja2 filter function for templates"""
|
|
def t_filter(key: str, **params) -> str:
|
|
return self.get_translation(key, params)
|
|
return t_filter
|
|
|
|
# Create global instance
|
|
server_i18n = ServerI18nManager()
|