Dieser Commit ist enthalten in:
Claude Project Manager
2025-08-01 23:50:28 +02:00
Commit 04585e95b6
290 geänderte Dateien mit 64086 neuen und 0 gelöschten Zeilen

0
localization/__init__.py Normale Datei
Datei anzeigen

Datei anzeigen

@ -0,0 +1,272 @@
# Path: localization/language_manager.py
"""
Sprachmanager für die Übersetzung der Benutzeroberfläche.
"""
import os
import json
import logging
import time
from typing import Dict, Any, Optional
from PyQt5.QtCore import QObject, pyqtSignal, QSettings
logger = logging.getLogger("language_manager")
class LanguageManager(QObject):
"""Verwaltet die Sprachen und Übersetzungen der Anwendung."""
# Signal, das ausgelöst wird, wenn sich die Sprache ändert
language_changed = pyqtSignal(str)
# Signal, das den Status des Sprachwechsels anzeigt (True = läuft, False = abgeschlossen)
language_change_status = pyqtSignal(bool)
def __init__(self, app=None):
"""
Initialisiert den Sprachmanager.
Args:
app: Die QApplication-Instanz
"""
super().__init__()
self.app = app
self.current_language = "de" # Standard ist Deutsch
self.translations = {}
self.available_languages = {}
self.last_change_time = 0 # Zeitpunkt des letzten Sprachwechsels
self.change_cooldown = 0.5 # Cooldown in Sekunden zwischen Sprachwechseln
self.is_changing_language = False # Status-Variable für laufenden Sprachwechsel
# Basisverzeichnis für Sprachdateien ermitteln
self.base_dir = os.path.dirname(os.path.abspath(__file__))
self.languages_dir = os.path.join(self.base_dir, "languages")
# Verfügbare Sprachen ermitteln und laden
self._discover_languages()
# Lade die gespeicherte Sprache, falls vorhanden
self.settings = QSettings("Chimaira", "SocialMediaAccountGenerator")
saved_language = self.settings.value("language", "de")
if saved_language in self.available_languages:
self.current_language = saved_language
self._load_language(self.current_language)
logger.info(f"Sprachmanager initialisiert mit Sprache: {self.current_language}")
def _discover_languages(self):
"""Ermittelt die verfügbaren Sprachen aus den Sprachdateien."""
self.available_languages = {}
try:
# Alle JSON-Dateien im Sprachverzeichnis suchen
language_files = []
for filename in os.listdir(self.languages_dir):
if filename.endswith(".json"):
language_code = filename.split(".")[0]
language_path = os.path.join(self.languages_dir, filename)
language_files.append((language_code, language_path))
# Definierte Reihenfolge der Sprachen
ordered_codes = ["de", "en", "fr", "es", "ja"]
# Sortierte Liste erstellen
for code in ordered_codes:
for language_code, language_path in language_files:
if language_code == code:
# Sprachinformationen aus der Datei lesen
try:
with open(language_path, 'r', encoding='utf-8') as file:
language_data = json.load(file)
language_name = language_data.get("language_name", language_code)
self.available_languages[language_code] = {
"name": language_name,
"path": language_path
}
except Exception as e:
logger.error(f"Fehler beim Laden der Sprachinformationen für {language_code}: {e}")
# Eventuelle restliche Sprachen hinzufügen
for language_code, language_path in language_files:
if language_code not in self.available_languages:
try:
with open(language_path, 'r', encoding='utf-8') as file:
language_data = json.load(file)
language_name = language_data.get("language_name", language_code)
self.available_languages[language_code] = {
"name": language_name,
"path": language_path
}
except Exception as e:
logger.error(f"Fehler beim Laden der Sprachinformationen für {language_code}: {e}")
logger.info(f"Verfügbare Sprachen: {', '.join(self.available_languages.keys())}")
except Exception as e:
logger.error(f"Fehler beim Ermitteln der verfügbaren Sprachen: {e}")
def _load_language(self, language_code: str) -> bool:
"""
Lädt die Übersetzungen für eine Sprache.
Args:
language_code: Der Sprachcode (z.B. "de", "en")
Returns:
bool: True bei Erfolg, False bei Fehler
"""
if language_code not in self.available_languages:
logger.error(f"Sprache {language_code} nicht verfügbar")
return False
try:
language_path = self.available_languages[language_code]["path"]
with open(language_path, 'r', encoding='utf-8') as file:
self.translations = json.load(file)
self.current_language = language_code
logger.info(f"Sprache {language_code} geladen")
# Signal auslösen, dass sich die Sprache geändert hat
self.language_changed.emit(language_code)
return True
except Exception as e:
logger.error(f"Fehler beim Laden der Sprache {language_code}: {e}")
return False
def get_text(self, key: str, default: str = None) -> str:
"""
Gibt den übersetzten Text für einen Schlüssel zurück.
Args:
key: Der Schlüssel für den Text (z.B. "main.title")
default: Der Standardtext, falls der Schlüssel nicht gefunden wurde
Returns:
str: Der übersetzte Text oder der Standardtext
"""
# Wenn kein Standardtext angegeben wurde, verwende den Schlüssel
if default is None:
default = key
# Versuche, den Text aus den Übersetzungen zu holen
try:
# Unterstütze verschachtelte Schlüssel mit Punktnotation
parts = key.split('.')
result = self.translations
for part in parts:
if part in result:
result = result[part]
else:
return default
# Wenn das Ergebnis ein unterstützter Datentyp ist, gib es zurück
if isinstance(result, (str, list, dict)):
return result
else:
logger.warning(
f"Schlüssel {key} hat unerwarteten Typ: {type(result)} - {result}"
)
return default
except Exception as e:
logger.warning(f"Fehler beim Abrufen des Textes für Schlüssel {key}: {e}")
return default
def change_language(self, language_code: str) -> bool:
"""
Ändert die aktive Sprache.
Args:
language_code: Der Sprachcode (z.B. "de", "en")
Returns:
bool: True bei Erfolg, False bei Fehler
"""
# Wenn bereits ein Sprachwechsel läuft, blockiere weitere Wechsel
if self.is_changing_language:
logger.debug(f"Ein Sprachwechsel läuft bereits, ignoriere Wechsel zu {language_code}")
return False
# Cooldown prüfen
current_time = time.time()
if current_time - self.last_change_time < self.change_cooldown:
logger.debug("Sprachwechsel zu schnell hintereinander")
return False
# Wenn es die gleiche Sprache ist, nichts tun
if language_code == self.current_language:
return True
# Status auf "Sprachwechsel läuft" setzen
self.is_changing_language = True
self.language_change_status.emit(True)
# Versuche die Sprache zu wechseln
success = self._load_language(language_code)
if success:
# Sprache in Einstellungen speichern
self.settings.setValue("language", language_code)
self.settings.sync()
# Aktualisiere den Zeitpunkt des letzten Sprachwechsels
self.last_change_time = time.time()
# Nach einer kurzen Verzögerung den Status zurücksetzen
# um sicherzustellen, dass die UI-Aktualisierung abgeschlossen ist
from PyQt5.QtCore import QTimer
QTimer.singleShot(500, self._reset_change_status)
return success
def _reset_change_status(self):
"""Setzt den Status des Sprachwechsels zurück."""
self.is_changing_language = False
self.language_change_status.emit(False)
logger.debug("Sprachwechsel-Status zurückgesetzt")
def get_current_language(self) -> str:
"""Gibt den Code der aktuellen Sprache zurück."""
return self.current_language
def get_language_name(self, language_code: str = None) -> str:
"""
Gibt den Namen einer Sprache zurück.
Args:
language_code: Der Sprachcode oder None für die aktuelle Sprache
Returns:
str: Der Name der Sprache
"""
if language_code is None:
language_code = self.current_language
if language_code in self.available_languages:
return self.available_languages[language_code].get("name", language_code)
else:
return language_code
def get_available_languages(self) -> Dict[str, str]:
"""
Gibt eine Liste der verfügbaren Sprachen zurück.
Returns:
Dict[str, str]: Ein Dictionary mit Sprachcodes als Schlüssel und Sprachnamen als Werten
"""
return {code: info.get("name", code) for code, info in self.available_languages.items()}
def is_language_change_in_progress(self) -> bool:
"""
Gibt zurück, ob gerade ein Sprachwechsel im Gange ist.
Returns:
bool: True wenn ein Sprachwechsel läuft, False sonst
"""
return self.is_changing_language

Datei anzeigen

@ -0,0 +1,93 @@
{
"language_name": "Deutsch",
"main": {
"title": "AccountForger",
"subtitle": "Wählen Sie eine Plattform",
"version": "Version 1.0.0",
"overview": "Übersicht"
},
"buttons": {
"back": "↩ Zurück",
"create": "Account erstellen",
"cancel": "Abbrechen",
"refresh": "Aktualisieren",
"export": "Exportieren",
"delete": "Löschen",
"test_proxy": "Proxy testen",
"save_proxy": "Proxy-Einstellungen speichern",
"test_email": "E-Mail testen",
"save_email": "E-Mail-Einstellungen speichern",
"activate_license": "Lizenz aktivieren",
"check_updates": "Auf Updates prüfen",
"ok": "OK"
},
"tabs": {
"generator": "Account Generator",
"accounts": "Konten",
"settings": "Einstellungen",
"about": "Über"
},
"menu": {
"about": "Über",
"about_app": "Über die Anwendung",
"language": "Sprache"
},
"status": {
"ready": "Bereit"
},
"generator_tab": {
"form_title": "Account-Informationen",
"first_name_label": "Vorname:",
"first_name_placeholder": "z.B. Max",
"last_name_label": "Nachname:",
"last_name_placeholder": "z.B. Mustermann",
"age_label": "Alter:",
"age_placeholder": "Alter zwischen 13 und 99",
"registration_method_label": "Registrierungsmethode:",
"email_radio": "E-Mail",
"phone_radio": "Telefon",
"phone_label": "Telefonnummer:",
"phone_placeholder": "z.B. +49123456789",
"email_domain_label": "E-Mail-Domain:",
"proxy_use": "Proxy verwenden",
"proxy_label": "Proxy:",
"proxy_type_label": "Typ:",
"proxy_type_ipv4": "IPv4",
"proxy_type_ipv6": "IPv6",
"proxy_type_mobile": "Mobile",
"headless": "Browser im Hintergrund ausführen",
"debug": "Debug-Modus (detaillierte Protokollierung)",
"log_title": "Log",
"error_title": "Fehler",
"first_name_error": "Bitte geben Sie einen Vornamen ein.",
"last_name_error": "Bitte geben Sie einen Nachnamen ein.",
"age_empty_error": "Bitte geben Sie ein Alter ein.",
"age_int_error": "Das Alter muss eine ganze Zahl sein.",
"age_range_error": "Das Alter muss zwischen 13 und 99 liegen.",
"phone_error": "Bitte geben Sie eine Telefonnummer ein."
},
"accounts_tab": {
"headers": [
"ID",
"Benutzername",
"Passwort",
"E-Mail",
"Handynummer",
"Name",
"Plattform",
"Erstellt am"
],
"no_selection_title": "Kein Konto ausgewählt",
"no_selection_text": "Bitte wählen Sie ein Konto zum Löschen aus.",
"delete_title": "Konto löschen",
"delete_text": "Möchten Sie das Konto '{username}' wirklich löschen?",
"delete_success_title": "Erfolg",
"delete_success_text": "Konto '{username}' wurde gelöscht.",
"delete_error_title": "Fehler",
"delete_error_text": "Konto '{username}' konnte nicht gelöscht werden."
},
"about_dialog": {
"support": "Für Support kontaktieren Sie uns unter: support@intelsight.de",
"license": "Diese Software ist lizenzpflichtig und darf nur mit gültiger Lizenz verwendet werden."
}
}

Datei anzeigen

@ -0,0 +1,93 @@
{
"language_name": "English",
"main": {
"title": "AccountForger",
"subtitle": "Select a platform",
"version": "Version 1.0.0",
"overview": "Overview"
},
"buttons": {
"back": "↩ Back",
"create": "Create Account",
"cancel": "Cancel",
"refresh": "Refresh",
"export": "Export",
"delete": "Delete",
"test_proxy": "Test Proxy",
"save_proxy": "Save Proxy Settings",
"test_email": "Test Email",
"save_email": "Save Email Settings",
"activate_license": "Activate License",
"check_updates": "Check for Updates",
"ok": "OK"
},
"tabs": {
"generator": "Account Generator",
"accounts": "Accounts",
"settings": "Settings",
"about": "About"
},
"menu": {
"about": "About",
"about_app": "About the Application",
"language": "Language"
},
"status": {
"ready": "Ready"
},
"generator_tab": {
"form_title": "Account Information",
"first_name_label": "First Name:",
"first_name_placeholder": "e.g. Max",
"last_name_label": "Last Name:",
"last_name_placeholder": "e.g. Mustermann",
"age_label": "Age:",
"age_placeholder": "Age between 13 and 99",
"registration_method_label": "Registration Method:",
"email_radio": "Email",
"phone_radio": "Phone",
"phone_label": "Phone Number:",
"phone_placeholder": "e.g. +49123456789",
"email_domain_label": "Email Domain:",
"proxy_use": "Use Proxy",
"proxy_label": "Proxy:",
"proxy_type_label": "Type:",
"proxy_type_ipv4": "IPv4",
"proxy_type_ipv6": "IPv6",
"proxy_type_mobile": "Mobile",
"headless": "Run browser headless",
"debug": "Debug mode (detailed logging)",
"log_title": "Log",
"error_title": "Error",
"first_name_error": "Please enter a first name.",
"last_name_error": "Please enter a last name.",
"age_empty_error": "Please enter an age.",
"age_int_error": "Age must be a whole number.",
"age_range_error": "Age must be between 13 and 99.",
"phone_error": "Please enter a phone number."
},
"accounts_tab": {
"headers": [
"ID",
"Username",
"Password",
"Email",
"Phone",
"Name",
"Platform",
"Created At"
],
"no_selection_title": "No Account Selected",
"no_selection_text": "Please select an account to delete.",
"delete_title": "Delete Account",
"delete_text": "Do you really want to delete the account '{username}'?",
"delete_success_title": "Success",
"delete_success_text": "Account '{username}' was deleted.",
"delete_error_title": "Error",
"delete_error_text": "Account '{username}' could not be deleted."
},
"about_dialog": {
"support": "For support contact us at: support@intelsight.de",
"license": "This software is licensed and may only be used with a valid license."
}
}

Datei anzeigen

@ -0,0 +1,93 @@
{
"language_name": "Español",
"main": {
"title": "AccountForger",
"subtitle": "Seleccione una plataforma",
"version": "Versión 1.0.0",
"overview": "Resumen"
},
"buttons": {
"back": "↩ Volver",
"create": "Crear cuenta",
"cancel": "Cancelar",
"refresh": "Actualizar",
"export": "Exportar",
"delete": "Eliminar",
"test_proxy": "Probar proxy",
"save_proxy": "Guardar ajustes de proxy",
"test_email": "Probar correo",
"save_email": "Guardar ajustes de correo",
"activate_license": "Activar licencia",
"check_updates": "Buscar actualizaciones",
"ok": "Aceptar"
},
"tabs": {
"generator": "Generador de Cuentas",
"accounts": "Cuentas",
"settings": "Configuración",
"about": "Acerca de"
},
"menu": {
"about": "Acerca de",
"about_app": "Acerca de la aplicación",
"language": "Idioma"
},
"status": {
"ready": "Listo"
},
"generator_tab": {
"form_title": "Información de la cuenta",
"first_name_label": "Nombre:",
"first_name_placeholder": "p.ej. Max",
"last_name_label": "Apellido:",
"last_name_placeholder": "p.ej. Mustermann",
"age_label": "Edad:",
"age_placeholder": "Edad entre 13 y 99",
"registration_method_label": "Método de registro:",
"email_radio": "Correo electrónico",
"phone_radio": "Teléfono",
"phone_label": "Número de teléfono:",
"phone_placeholder": "p.ej. +49123456789",
"email_domain_label": "Dominio de correo:",
"proxy_use": "Usar proxy",
"proxy_label": "Proxy:",
"proxy_type_label": "Tipo:",
"proxy_type_ipv4": "IPv4",
"proxy_type_ipv6": "IPv6",
"proxy_type_mobile": "Móvil",
"headless": "Ejecutar navegador en segundo plano",
"debug": "Modo depuración (registro detallado)",
"log_title": "Registro",
"error_title": "Error",
"first_name_error": "Por favor, introduzca un nombre.",
"last_name_error": "Por favor, introduzca un apellido.",
"age_empty_error": "Por favor, introduzca una edad.",
"age_int_error": "La edad debe ser un número entero.",
"age_range_error": "La edad debe estar entre 13 y 99.",
"phone_error": "Por favor, introduzca un número de teléfono."
},
"accounts_tab": {
"headers": [
"ID",
"Nombre de usuario",
"Contraseña",
"Correo",
"Teléfono",
"Nombre",
"Plataforma",
"Creado el"
],
"no_selection_title": "Ninguna cuenta seleccionada",
"no_selection_text": "Seleccione una cuenta para eliminar.",
"delete_title": "Eliminar cuenta",
"delete_text": "¿Realmente desea eliminar la cuenta '{username}'?",
"delete_success_title": "Éxito",
"delete_success_text": "La cuenta '{username}' fue eliminada.",
"delete_error_title": "Error",
"delete_error_text": "No se pudo eliminar la cuenta '{username}'."
},
"about_dialog": {
"support": "Para soporte contáctenos en: support@intelsight.de",
"license": "Este software está sujeto a licencia y solo puede utilizarse con una licencia válida."
}
}

Datei anzeigen

@ -0,0 +1,93 @@
{
"language_name": "Français",
"main": {
"title": "AccountForger",
"subtitle": "Sélectionnez une plateforme",
"version": "Version 1.0.0",
"overview": "Aperçu"
},
"buttons": {
"back": "↩ Retour",
"create": "Créer un compte",
"cancel": "Annuler",
"refresh": "Rafraîchir",
"export": "Exporter",
"delete": "Supprimer",
"test_proxy": "Tester le proxy",
"save_proxy": "Enregistrer le proxy",
"test_email": "Tester l'e-mail",
"save_email": "Enregistrer l'e-mail",
"activate_license": "Activer la licence",
"check_updates": "Vérifier les mises à jour",
"ok": "OK"
},
"tabs": {
"generator": "Générateur de Compte",
"accounts": "Comptes",
"settings": "Paramètres",
"about": "À Propos"
},
"menu": {
"about": "À propos",
"about_app": "À propos de l'application",
"language": "Langue"
},
"status": {
"ready": "Prêt"
},
"generator_tab": {
"form_title": "Informations du compte",
"first_name_label": "Prénom:",
"first_name_placeholder": "ex. Max",
"last_name_label": "Nom:",
"last_name_placeholder": "ex. Mustermann",
"age_label": "Âge:",
"age_placeholder": "Âge entre 13 et 99",
"registration_method_label": "Méthode d'enregistrement:",
"email_radio": "E-mail",
"phone_radio": "Téléphone",
"phone_label": "Numéro de téléphone:",
"phone_placeholder": "ex. +49123456789",
"email_domain_label": "Domaine e-mail:",
"proxy_use": "Utiliser un proxy",
"proxy_label": "Proxy:",
"proxy_type_label": "Type:",
"proxy_type_ipv4": "IPv4",
"proxy_type_ipv6": "IPv6",
"proxy_type_mobile": "Mobile",
"headless": "Exécuter le navigateur en arrière-plan",
"debug": "Mode débogage (journal détaillé)",
"log_title": "Journal",
"error_title": "Erreur",
"first_name_error": "Veuillez saisir un prénom.",
"last_name_error": "Veuillez saisir un nom.",
"age_empty_error": "Veuillez saisir un âge.",
"age_int_error": "L'âge doit être un nombre entier.",
"age_range_error": "L'âge doit être compris entre 13 et 99.",
"phone_error": "Veuillez saisir un numéro de téléphone."
},
"accounts_tab": {
"headers": [
"ID",
"Nom d'utilisateur",
"Mot de passe",
"E-mail",
"Téléphone",
"Nom",
"Plateforme",
"Créé le"
],
"no_selection_title": "Aucun compte sélectionné",
"no_selection_text": "Veuillez sélectionner un compte à supprimer.",
"delete_title": "Supprimer le compte",
"delete_text": "Voulez-vous vraiment supprimer le compte '{username}' ?",
"delete_success_title": "Succès",
"delete_success_text": "Le compte '{username}' a été supprimé.",
"delete_error_title": "Erreur",
"delete_error_text": "Le compte '{username}' n'a pas pu être supprimé."
},
"about_dialog": {
"support": "Pour toute assistance, contactez-nous à : support@intelsight.de",
"license": "Ce logiciel est soumis à licence et ne peut être utilisé qu'avec une licence valide."
}
}

Datei anzeigen

@ -0,0 +1,93 @@
{
"language_name": "日本語",
"main": {
"title": "AccountForger",
"subtitle": "プラットフォームを選択",
"version": "バージョン 1.0.0",
"overview": "概要"
},
"buttons": {
"back": "↩ 戻る",
"create": "アカウント作成",
"cancel": "キャンセル",
"refresh": "更新",
"export": "エクスポート",
"delete": "削除",
"test_proxy": "プロキシテスト",
"save_proxy": "プロキシ設定を保存",
"test_email": "メールをテスト",
"save_email": "メール設定を保存",
"activate_license": "ライセンスを有効化",
"check_updates": "アップデートを確認",
"ok": "OK"
},
"tabs": {
"generator": "アカウント生成",
"accounts": "アカウント",
"settings": "設定",
"about": "情報"
},
"menu": {
"about": "情報",
"about_app": "アプリについて",
"language": "言語"
},
"status": {
"ready": "完了"
},
"generator_tab": {
"form_title": "アカウント情報",
"first_name_label": "名:",
"first_name_placeholder": "例: Max",
"last_name_label": "姓:",
"last_name_placeholder": "例: Mustermann",
"age_label": "年齢:",
"age_placeholder": "1399歳",
"registration_method_label": "登録方法:",
"email_radio": "メール",
"phone_radio": "電話",
"phone_label": "電話番号:",
"phone_placeholder": "例: +49123456789",
"email_domain_label": "メールドメイン:",
"proxy_use": "プロキシを使用",
"proxy_label": "プロキシ:",
"proxy_type_label": "タイプ:",
"proxy_type_ipv4": "IPv4",
"proxy_type_ipv6": "IPv6",
"proxy_type_mobile": "モバイル",
"headless": "ブラウザをバックグラウンドで実行",
"debug": "デバッグモード (詳細ログ)",
"log_title": "ログ",
"error_title": "エラー",
"first_name_error": "名を入力してください。",
"last_name_error": "姓を入力してください。",
"age_empty_error": "年齢を入力してください。",
"age_int_error": "年齢は整数である必要があります。",
"age_range_error": "年齢は13から99の間である必要があります。",
"phone_error": "電話番号を入力してください。"
},
"accounts_tab": {
"headers": [
"ID",
"ユーザー名",
"パスワード",
"メール",
"電話",
"名前",
"プラットフォーム",
"作成日"
],
"no_selection_title": "アカウントが選択されていません",
"no_selection_text": "削除するアカウントを選択してください。",
"delete_title": "アカウントの削除",
"delete_text": "アカウント '{username}' を本当に削除しますか?",
"delete_success_title": "成功",
"delete_success_text": "アカウント '{username}' は削除されました。",
"delete_error_title": "エラー",
"delete_error_text": "アカウント '{username}' を削除できませんでした。"
},
"about_dialog": {
"support": "サポートが必要な場合は次へご連絡ください: support@intelsight.de",
"license": "このソフトウェアはライセンス制で、有効なライセンスでのみ使用できます。"
}
}