支持自动检测语言

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

@@ -3,13 +3,14 @@ International language support for ReelForge Web UI
"""
import json
import locale
from pathlib import Path
from typing import Dict, Optional
from loguru import logger
_locales: Dict[str, dict] = {}
_current_language: str = "zh_CN"
_current_language: str = "en_US" # Default fallback to English
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
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}")