Spaces:
Sleeping
Sleeping
| """ | |
| Internationalization (i18n) module for Gradio UI | |
| Supports multiple languages with easy translation management | |
| """ | |
| import os | |
| import json | |
| from typing import Dict, Optional | |
| class I18n: | |
| """Internationalization handler""" | |
| def __init__(self, default_language: str = "en"): | |
| """ | |
| Initialize i18n handler | |
| Args: | |
| default_language: Default language code (en, zh, ja, etc.) | |
| """ | |
| self.current_language = default_language | |
| self.translations: Dict[str, Dict[str, str]] = {} | |
| self._load_all_translations() | |
| def _load_all_translations(self): | |
| """Load all translation files from i18n directory""" | |
| current_file = os.path.abspath(__file__) | |
| module_dir = os.path.dirname(current_file) | |
| i18n_dir = os.path.join(module_dir, "i18n") | |
| if not os.path.exists(i18n_dir): | |
| # Create i18n directory if it doesn't exist | |
| os.makedirs(i18n_dir) | |
| return | |
| # Load all JSON files in i18n directory | |
| for filename in os.listdir(i18n_dir): | |
| if filename.endswith(".json"): | |
| lang_code = filename[:-5] # Remove .json extension | |
| filepath = os.path.join(i18n_dir, filename) | |
| try: | |
| with open(filepath, 'r', encoding='utf-8') as f: | |
| self.translations[lang_code] = json.load(f) | |
| except Exception as e: | |
| print(f"Error loading translation file {filename}: {e}") | |
| def set_language(self, language: str): | |
| """Set current language""" | |
| if language in self.translations: | |
| self.current_language = language | |
| else: | |
| print(f"Warning: Language '{language}' not found, using default") | |
| def t(self, key: str, **kwargs) -> str: | |
| """ | |
| Translate a key to current language | |
| Args: | |
| key: Translation key (dot-separated for nested keys) | |
| **kwargs: Optional format parameters | |
| Returns: | |
| Translated string | |
| """ | |
| # Get translation from current language | |
| translation = self._get_nested_value( | |
| self.translations.get(self.current_language, {}), | |
| key | |
| ) | |
| # Fallback to English if not found | |
| if translation is None: | |
| translation = self._get_nested_value( | |
| self.translations.get('en', {}), | |
| key | |
| ) | |
| # Final fallback to key itself | |
| if translation is None: | |
| translation = key | |
| # Apply formatting if kwargs provided | |
| if kwargs: | |
| try: | |
| translation = translation.format(**kwargs) | |
| except KeyError: | |
| pass | |
| return translation | |
| def _get_nested_value(self, data: dict, key: str) -> Optional[str]: | |
| """ | |
| Get nested dictionary value using dot notation | |
| Args: | |
| data: Dictionary to search | |
| key: Dot-separated key (e.g., "section.subsection.key") | |
| Returns: | |
| Value if found, None otherwise | |
| """ | |
| keys = key.split('.') | |
| current = data | |
| for k in keys: | |
| if isinstance(current, dict) and k in current: | |
| current = current[k] | |
| else: | |
| return None | |
| return current if isinstance(current, str) else None | |
| def get_available_languages(self) -> list: | |
| """Get list of available language codes""" | |
| return list(self.translations.keys()) | |
| # Global i18n instance | |
| _i18n_instance: Optional[I18n] = None | |
| def get_i18n(language: Optional[str] = None) -> I18n: | |
| """ | |
| Get global i18n instance | |
| Args: | |
| language: Optional language to set | |
| Returns: | |
| I18n instance | |
| """ | |
| global _i18n_instance | |
| if _i18n_instance is None: | |
| _i18n_instance = I18n(default_language=language or "en") | |
| elif language is not None: | |
| _i18n_instance.set_language(language) | |
| return _i18n_instance | |
| def t(key: str, **kwargs) -> str: | |
| """ | |
| Convenience function for translation | |
| Args: | |
| key: Translation key | |
| **kwargs: Optional format parameters | |
| Returns: | |
| Translated string | |
| """ | |
| return get_i18n().t(key, **kwargs) | |