mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-08-02 20:47:35 +08:00
Merge branch 'main' into main
This commit is contained in:
commit
8e6df1d1f8
@ -105,6 +105,12 @@ def setup_config(translator=None):
|
|||||||
'Token': {
|
'Token': {
|
||||||
'refresh_server': 'https://token.cursorpro.com.cn',
|
'refresh_server': 'https://token.cursorpro.com.cn',
|
||||||
'enable_refresh': True
|
'enable_refresh': True
|
||||||
|
},
|
||||||
|
'Language': {
|
||||||
|
'current_language': '', # Set by local system detection if empty
|
||||||
|
'fallback_language': 'en',
|
||||||
|
'auto_update_languages': 'True',
|
||||||
|
'language_cache_dir': os.path.join(config_dir, "language_cache")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
111
main.py
111
main.py
@ -12,6 +12,8 @@ import subprocess
|
|||||||
from config import get_config, force_update_config
|
from config import get_config, force_update_config
|
||||||
import shutil
|
import shutil
|
||||||
import re
|
import re
|
||||||
|
from utils import get_user_documents_path
|
||||||
|
|
||||||
# Add these imports for Arabic support
|
# Add these imports for Arabic support
|
||||||
try:
|
try:
|
||||||
import arabic_reshaper
|
import arabic_reshaper
|
||||||
@ -86,8 +88,37 @@ def run_as_admin():
|
|||||||
class Translator:
|
class Translator:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.translations = {}
|
self.translations = {}
|
||||||
self.current_language = self.detect_system_language() # Use correct method name
|
self.config = get_config()
|
||||||
self.fallback_language = 'en' # Fallback language if translation is missing
|
|
||||||
|
# Create language cache directory if it doesn't exist
|
||||||
|
if self.config and self.config.has_section('Language'):
|
||||||
|
self.language_cache_dir = self.config.get('Language', 'language_cache_dir')
|
||||||
|
os.makedirs(self.language_cache_dir, exist_ok=True)
|
||||||
|
else:
|
||||||
|
self.language_cache_dir = None
|
||||||
|
|
||||||
|
# Set fallback language from config if available
|
||||||
|
self.fallback_language = 'en'
|
||||||
|
if self.config and self.config.has_section('Language') and self.config.has_option('Language', 'fallback_language'):
|
||||||
|
self.fallback_language = self.config.get('Language', 'fallback_language')
|
||||||
|
|
||||||
|
# Load saved language from config if available, otherwise detect system language
|
||||||
|
if self.config and self.config.has_section('Language') and self.config.has_option('Language', 'current_language'):
|
||||||
|
saved_language = self.config.get('Language', 'current_language')
|
||||||
|
if saved_language and saved_language.strip():
|
||||||
|
self.current_language = saved_language
|
||||||
|
else:
|
||||||
|
self.current_language = self.detect_system_language()
|
||||||
|
# Save detected language to config
|
||||||
|
if self.config.has_section('Language'):
|
||||||
|
self.config.set('Language', 'current_language', self.current_language)
|
||||||
|
config_dir = os.path.join(get_user_documents_path(), ".cursor-free-vip")
|
||||||
|
config_file = os.path.join(config_dir, "config.ini")
|
||||||
|
with open(config_file, 'w', encoding='utf-8') as f:
|
||||||
|
self.config.write(f)
|
||||||
|
else:
|
||||||
|
self.current_language = self.detect_system_language()
|
||||||
|
|
||||||
self.load_translations()
|
self.load_translations()
|
||||||
|
|
||||||
def detect_system_language(self):
|
def detect_system_language(self):
|
||||||
@ -208,28 +239,48 @@ class Translator:
|
|||||||
except:
|
except:
|
||||||
return 'en'
|
return 'en'
|
||||||
|
|
||||||
|
def download_language_file(self, lang_code):
|
||||||
|
"""Method kept for compatibility but now returns False as language files are integrated"""
|
||||||
|
print(f"{Fore.YELLOW}{EMOJI['INFO']} Languages are now integrated into the package, no need to download.{Style.RESET_ALL}")
|
||||||
|
return False
|
||||||
|
|
||||||
def load_translations(self):
|
def load_translations(self):
|
||||||
"""Load all available translations"""
|
"""Load all available translations from the integrated package"""
|
||||||
try:
|
try:
|
||||||
locales_dir = os.path.join(os.path.dirname(__file__), 'locales')
|
# Collection of languages we've successfully loaded
|
||||||
|
loaded_languages = set()
|
||||||
|
|
||||||
|
locales_paths = []
|
||||||
|
|
||||||
|
# Check for PyInstaller bundle first
|
||||||
if hasattr(sys, '_MEIPASS'):
|
if hasattr(sys, '_MEIPASS'):
|
||||||
locales_dir = os.path.join(sys._MEIPASS, 'locales')
|
locales_paths.append(os.path.join(sys._MEIPASS, 'locales'))
|
||||||
|
|
||||||
if not os.path.exists(locales_dir):
|
# Check script directory next
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} Locales directory not found{Style.RESET_ALL}")
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
return
|
locales_paths.append(os.path.join(script_dir, 'locales'))
|
||||||
|
|
||||||
|
# Also check current working directory
|
||||||
|
locales_paths.append(os.path.join(os.getcwd(), 'locales'))
|
||||||
|
|
||||||
|
for locales_dir in locales_paths:
|
||||||
|
if os.path.exists(locales_dir) and os.path.isdir(locales_dir):
|
||||||
for file in os.listdir(locales_dir):
|
for file in os.listdir(locales_dir):
|
||||||
if file.endswith('.json'):
|
if file.endswith('.json'):
|
||||||
lang_code = file[:-5] # Remove .json
|
lang_code = file[:-5] # Remove .json
|
||||||
try:
|
try:
|
||||||
with open(os.path.join(locales_dir, file), 'r', encoding='utf-8') as f:
|
with open(os.path.join(locales_dir, file), 'r', encoding='utf-8') as f:
|
||||||
self.translations[lang_code] = json.load(f)
|
self.translations[lang_code] = json.load(f)
|
||||||
|
loaded_languages.add(lang_code)
|
||||||
|
loaded_any = True
|
||||||
except (json.JSONDecodeError, UnicodeDecodeError) as e:
|
except (json.JSONDecodeError, UnicodeDecodeError) as e:
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} Error loading {file}: {e}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} Error loading {file}: {e}{Style.RESET_ALL}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} Failed to load translations: {e}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} Failed to load translations: {e}{Style.RESET_ALL}")
|
||||||
|
# Create at least minimal English translations for basic functionality
|
||||||
|
self.translations['en'] = {"menu": {"title": "Menu", "exit": "Exit", "invalid_choice": "Invalid choice"}}
|
||||||
|
|
||||||
def fix_arabic(self, text):
|
def fix_arabic(self, text):
|
||||||
if self.current_language == 'ar' and arabic_reshaper and get_display:
|
if self.current_language == 'ar' and arabic_reshaper and get_display:
|
||||||
@ -277,7 +328,11 @@ class Translator:
|
|||||||
|
|
||||||
def get_available_languages(self):
|
def get_available_languages(self):
|
||||||
"""Get list of available languages"""
|
"""Get list of available languages"""
|
||||||
return list(self.translations.keys())
|
# Get currently loaded languages
|
||||||
|
available_languages = list(self.translations.keys())
|
||||||
|
|
||||||
|
# Sort languages alphabetically for better display
|
||||||
|
return sorted(available_languages)
|
||||||
|
|
||||||
# Create translator instance
|
# Create translator instance
|
||||||
translator = Translator()
|
translator = Translator()
|
||||||
@ -395,21 +450,45 @@ def select_language():
|
|||||||
print(f"\n{Fore.CYAN}{EMOJI['LANG']} {translator.get('menu.select_language')}:{Style.RESET_ALL}")
|
print(f"\n{Fore.CYAN}{EMOJI['LANG']} {translator.get('menu.select_language')}:{Style.RESET_ALL}")
|
||||||
print(f"{Fore.YELLOW}{'─' * 40}{Style.RESET_ALL}")
|
print(f"{Fore.YELLOW}{'─' * 40}{Style.RESET_ALL}")
|
||||||
|
|
||||||
|
# Get available languages either from local directory or GitHub
|
||||||
languages = translator.get_available_languages()
|
languages = translator.get_available_languages()
|
||||||
|
languages_count = len(languages)
|
||||||
|
|
||||||
|
# Display all available languages with proper indices
|
||||||
for i, lang in enumerate(languages):
|
for i, lang in enumerate(languages):
|
||||||
lang_name = translator.get(f"languages.{lang}")
|
lang_name = translator.get(f"languages.{lang}", fallback=lang)
|
||||||
print(f"{Fore.GREEN}{i}{Style.RESET_ALL}. {lang_name}")
|
print(f"{Fore.GREEN}{i}{Style.RESET_ALL}. {lang_name}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('menu.input_choice', choices=f'0-{len(languages)-1}')}: {Style.RESET_ALL}")
|
# Use the actual number of languages in the prompt
|
||||||
if choice.isdigit() and 0 <= int(choice) < len(languages):
|
choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('menu.input_choice', choices=f'0-{languages_count-1}')}: {Style.RESET_ALL}")
|
||||||
translator.set_language(languages[int(choice)])
|
|
||||||
|
if choice.isdigit() and 0 <= int(choice) < languages_count:
|
||||||
|
selected_language = languages[int(choice)]
|
||||||
|
translator.set_language(selected_language)
|
||||||
|
|
||||||
|
# Save selected language to config
|
||||||
|
config = get_config()
|
||||||
|
if config and config.has_section('Language'):
|
||||||
|
config.set('Language', 'current_language', selected_language)
|
||||||
|
|
||||||
|
# Get config path from user documents
|
||||||
|
config_dir = os.path.join(get_user_documents_path(), ".cursor-free-vip")
|
||||||
|
config_file = os.path.join(config_dir, "config.ini")
|
||||||
|
|
||||||
|
# Write updated config
|
||||||
|
with open(config_file, 'w', encoding='utf-8') as f:
|
||||||
|
config.write(f)
|
||||||
|
|
||||||
|
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {translator.get('menu.language_config_saved', language=translator.get(f'languages.{selected_language}', fallback=selected_language))}{Style.RESET_ALL}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}")
|
# Show invalid choice message with the correct range
|
||||||
|
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.lang_invalid_choice', lang_choices=f'0-{languages_count-1}')}{Style.RESET_ALL}")
|
||||||
return False
|
return False
|
||||||
except (ValueError, IndexError):
|
except (ValueError, IndexError) as e:
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.lang_invalid_choice', lang_choices=f'0-{languages_count-1}')}{Style.RESET_ALL}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def check_latest_version():
|
def check_latest_version():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user