refactor(Translator): enhance language detection and fallback logic

Reorganize language detection methods for Windows and Unix systems, simplifying the fallback mechanism to ensure English is returned when detection fails. Introduce a mapping for language codes based on keyboard layout and system locale, improving maintainability and clarity in the code. This update also removes redundant code and enhances the overall structure of the Translator class.
This commit is contained in:
Pin Studios 2025-04-13 20:54:10 +08:00
parent 61803031dc
commit 271fc818b1

116
main.py
View File

@ -79,18 +79,9 @@ def run_as_admin():
class Translator:
def __init__(self):
self.translations = {}
self.fallback_language = 'en' # Fallback language if translation is missing
self.current_language = self.detect_system_language() # Use correct method name
self.fallback_language = 'en' # Fallback language if translation is missing
self.load_translations()
self.default_layout_id_to_lang_code_mapping = {
0x0409: 'en', # English
0x0404: 'zh_tw', # Traditional Chinese
0x0804: 'zh_cn', # Simplified Chinese
0x0422: 'vi', # Vietnamese
0x0419: 'ru', # Russian
0x0415: 'tr', # Turkish
0x0402: 'bg' # Bulgarian
} # Using in Windows
def detect_system_language(self):
"""Detect system language and return corresponding language code"""
@ -104,59 +95,96 @@ class Translator:
except Exception as e:
print(f"{Fore.YELLOW}{EMOJI['INFO']} Failed to detect system language: {e}{Style.RESET_ALL}")
return self.fallback_language
return 'en'
def _detect_windows_language(self):
"""Detect language on Windows systems"""
final_lang_code = self.fallback_language # Default to English if can not detect Windows system language
try:
# Ensure we are on Windows
if platform.system() != 'Windows':
return final_lang_code
return 'en'
# Get current layout using Windows API
# Get keyboard layout
user32 = ctypes.windll.user32
hwnd = user32.GetForegroundWindow()
threadid = user32.GetWindowThreadProcessId(hwnd, 0)
current_layout_id = user32.GetKeyboardLayout(threadid) & 0xFFFF
layout_id = user32.GetKeyboardLayout(threadid) & 0xFFFF
# Convert layout ID to language code using Windows LOCALE_SISO639LANGNAME
buf_size = 9 # Max size for ISO language code
lang_code = ctypes.create_unicode_buffer(buf_size)
if ctypes.windll.kernel32.LCIDToLocaleName(current_layout_id, lang_code, buf_size, 0) > 0:
final_lang_code = lang_code.value.lower()
else:
# Using default layout mapping if can not get form Windows API
final_lang_code = self.default_layout_id_to_lang_code_mapping.get(current_layout_id, 'en')
if final_lang_code == 'zh':
final_lang_code = 'zh_cn' # Default to Simplified Chinese
if final_lang_code == 'zh_hk':
final_lang_code = 'zh_tw' # Hongkong
return final_lang_code # Fallback
# Map language ID to our language codes
language_map = {
0x0409: 'en', # English
0x0404: 'zh_tw', # Traditional Chinese
0x0804: 'zh_cn', # Simplified Chinese
0x0422: 'vi', # Vietnamese
0x0419: 'ru', # Russian
0x0415: 'tr', # Turkish
0x0402: 'bg', # Bulgarian
}
return language_map.get(layout_id, 'en')
except:
return self._detect_unix_language()
def _detect_unix_language(self):
"""Detect language on Unix-like systems (Linux, macOS)"""
final_lang_code = self.fallback_language # Default to English if can not detect Windows system language
try:
# Get the system locale, it is lang_code.charset_encoding such as: en_US.UTF-8
# Get the system locale
locale.setlocale(locale.LC_ALL, '')
system_locale = locale.getlocale()[0].lower() or os.getenv('LANG').lower() # Use $LANG variable as a fall back
system_locale = locale.getlocale()[0]
if not system_locale:
return final_lang_code # Fallback to English if can not detect Unix system language
# We do not need the charset encoding, so:
final_lang_code = system_locale.split('.')[0] # Extract lang_code from locale if can detect Unix system language
return 'en'
system_locale = system_locale.lower()
# Map locale to our language codes
if system_locale.startswith('zh_tw') or system_locale.startswith('zh_hk'):
return 'zh_tw'
elif system_locale.startswith('zh_cn'):
return 'zh_cn'
elif system_locale.startswith('en'):
return 'en'
elif system_locale.startswith('vi'):
return 'vi'
elif system_locale.startswith('nl'):
return 'nl'
elif system_locale.startswith('de'):
return 'de'
elif system_locale.startswith('fr'):
return 'fr'
elif system_locale.startswith('pt'):
return 'pt'
elif system_locale.startswith('ru'):
return 'ru'
elif system_locale.startswith('tr'):
return 'tr'
elif system_locale.startswith('bg'):
return 'bg'
# Try to get language from LANG environment variable as fallback
env_lang = os.getenv('LANG', '').lower()
if 'tw' in env_lang or 'hk' in env_lang:
return 'zh_tw'
elif 'cn' in env_lang:
return 'zh_cn'
elif 'vi' in env_lang:
return 'vi'
elif 'nl' in env_lang:
return 'nl'
elif 'de' in env_lang:
return 'de'
elif 'fr' in env_lang:
return 'fr'
elif 'pt' in env_lang:
return 'pt'
elif 'ru' in env_lang:
return 'ru'
elif 'tr' in env_lang:
return 'tr'
elif 'bg' in env_lang:
return 'bg'
if final_lang_code == 'zh':
final_lang_code = 'zh_cn' # Default to Simplified Chinese
if final_lang_code == 'zh_hk':
final_lang_code = 'zh_tw' # Hongkong
return final_lang_code # Fallback
return 'en'
except:
return final_lang_code # Fallback
return 'en'
def load_translations(self):
"""Load all available translations"""