支持自动检测语言

This commit is contained in:
puke
2025-10-30 11:37:47 +08:00
parent 713b90c176
commit 9d06bcc1c5
2 changed files with 127 additions and 8 deletions

View File

@@ -13,7 +13,7 @@ import streamlit as st
from loguru import logger from loguru import logger
# Import i18n and config manager # Import i18n and config manager
from web.i18n import load_locales, set_language, tr, get_available_languages from web.i18n import load_locales, set_language, tr, get_available_languages, get_language
from reelforge.config import config_manager from reelforge.config import config_manager
from reelforge.models.progress import ProgressEvent from reelforge.models.progress import ProgressEvent
@@ -52,12 +52,10 @@ def safe_rerun():
def init_i18n(): def init_i18n():
"""Initialize internationalization""" """Initialize internationalization"""
# Load locales if not already loaded # Locales are already loaded and system language detected on import
load_locales() # Get language from session state or use auto-detected system language
# Get language from session state or default to Chinese
if "language" not in st.session_state: if "language" not in st.session_state:
st.session_state.language = "zh_CN" st.session_state.language = get_language() # Use auto-detected language
# Set current language # Set current language
set_language(st.session_state.language) set_language(st.session_state.language)
@@ -86,7 +84,8 @@ def get_reelforge():
def init_session_state(): def init_session_state():
"""Initialize session state variables""" """Initialize session state variables"""
if "language" not in st.session_state: if "language" not in st.session_state:
st.session_state.language = "zh_CN" # Use auto-detected system language
st.session_state.language = get_language()
# ============================================================================ # ============================================================================

View File

@@ -3,13 +3,14 @@ International language support for ReelForge Web UI
""" """
import json import json
import locale
from pathlib import Path from pathlib import Path
from typing import Dict, Optional from typing import Dict, Optional
from loguru import logger from loguru import logger
_locales: Dict[str, dict] = {} _locales: Dict[str, dict] = {}
_current_language: str = "zh_CN" _current_language: str = "en_US" # Default fallback to English
def load_locales() -> Dict[str, dict]: def load_locales() -> Dict[str, dict]:
@@ -112,6 +113,125 @@ def get_available_languages() -> Dict[str, str]:
} }
def detect_system_language() -> str:
"""
Detect system/OS language and return the best matching locale code.
Falls back to English if no match found.
This is designed for self-hosted scenarios where the server and browser
are typically on the same machine.
Returns:
Language code (e.g., "zh_CN", "en_US")
"""
try:
import os
import platform
import subprocess
system_locale = None
# Method 1: macOS-specific detection (most reliable for macOS)
if platform.system() == "Darwin": # macOS
try:
# Get AppleLocale which reflects system language preference
result = subprocess.run(
["defaults", "read", "-g", "AppleLocale"],
capture_output=True,
text=True,
timeout=2
)
if result.returncode == 0:
system_locale = result.stdout.strip()
logger.debug(f"System locale from macOS AppleLocale: {system_locale}")
except Exception as e:
logger.debug(f"macOS AppleLocale detection failed: {e}")
# Fallback: try AppleLanguages
if not system_locale:
try:
result = subprocess.run(
["defaults", "read", "-g", "AppleLanguages"],
capture_output=True,
text=True,
timeout=2
)
if result.returncode == 0:
# Parse array output like: ( "zh-Hans-CN", "en-CN" )
output = result.stdout.strip()
# Extract first language
import re
match = re.search(r'"([^"]+)"', output)
if match:
lang = match.group(1)
# Convert zh-Hans-CN to zh_CN
if lang.startswith("zh-Hans"):
system_locale = "zh_CN"
elif lang.startswith("zh-Hant"):
system_locale = "zh_TW"
else:
system_locale = lang.replace("-", "_")
logger.debug(f"System locale from macOS AppleLanguages: {system_locale}")
except Exception as e:
logger.debug(f"macOS AppleLanguages detection failed: {e}")
# Method 2: Get from environment locale (cross-platform)
if not system_locale:
try:
system_locale = locale.getdefaultlocale()[0]
logger.debug(f"System locale from getdefaultlocale(): {system_locale}")
except Exception as e:
logger.debug(f"getdefaultlocale() failed: {e}")
# Method 3: Get from current locale
if not system_locale:
try:
system_locale = locale.getlocale()[0]
logger.debug(f"System locale from getlocale(): {system_locale}")
except Exception as e:
logger.debug(f"getlocale() failed: {e}")
# Method 4: Try to get from environment variables
if not system_locale:
for env_var in ['LC_ALL', 'LC_MESSAGES', 'LANG', 'LANGUAGE']:
env_value = os.environ.get(env_var)
if env_value:
# Extract language code from formats like "zh_CN.UTF-8"
system_locale = env_value.split('.')[0]
logger.debug(f"System locale from {env_var}: {system_locale}")
break
if system_locale:
# Normalize the locale string
# Handle formats: zh_CN, zh-CN, zh_CN.UTF-8, etc.
system_locale = system_locale.replace('-', '_').split('.')[0]
# Direct match (e.g., "zh_CN")
for locale_code in _locales.keys():
if locale_code.lower() == system_locale.lower():
logger.info(f"System language matched: {locale_code}")
return locale_code
# Partial match (e.g., "zh" matches "zh_CN")
lang_prefix = system_locale.split('_')[0].lower()
for locale_code in _locales.keys():
if locale_code.lower().startswith(lang_prefix):
logger.info(f"System language partially matched: {locale_code} (from {system_locale})")
return locale_code
logger.info("No system language detected, using fallback")
except Exception as e:
logger.warning(f"Failed to detect system language: {e}")
# Fallback to English
return "en_US"
# Auto-load locales on import # Auto-load locales on import
load_locales() load_locales()
# Auto-detect and set system language
_detected_language = detect_system_language()
_current_language = _detected_language
logger.info(f"Default language initialized to: {_current_language}")