diff --git a/changelog.md b/changelog.md index 8f09401..e86d224 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,22 @@ # Changelog +## 0.05.3 : 21.09.2023 + +By: [@Niklas20114552](https://github.com/Niklas20114552) + +Added: + +- Translations for German and English: + - Errorpages and the Homepage aren't translated yet. +- Navigating to ```brapy:settings``` will open the Settings +- Open Folder-Button in Downloadslist +- Remaining Time is now calculated in Downloadslist +- A Warning is now being displayed, when downloading file and the destination file exists already + +Fixed: + +- Tabs will only load in Debugmode + ## 0.05.2 : 21.09.2023 By: [@Niklas20114552](https://github.com/Niklas20114552) diff --git a/extraerror.html b/extraerror.html index 76b88ec..1337fd8 100644 --- a/extraerror.html +++ b/extraerror.html @@ -53,7 +53,7 @@
- + diff --git a/lang/de.json b/lang/de.json new file mode 100644 index 0000000..74bc77a --- /dev/null +++ b/lang/de.json @@ -0,0 +1,164 @@ +{ + "custom_tab": { + "brapy:settings": { + "name": "Einstellungen", + "subtitle": "Einstellungen", + "apply_button": "Änderungen anwenden", + "title1": "Allgemein", + "title2": "Sicherheit", + "title3": "Adblocker", + "title4": "Features", + "adblockl1": "Whiteliste: (Jede URL in eine neue Zeile)", + "adblockl2": "Blackliste: (Jede URL in eine neue Zeile)", + "featl1": "Dieses Land verwenden:", + "featl1p": "Land autom. ermitteln", + "confirmq": "Schließen mit STRL+Q bestätigen", + "userinurl": "Benutzernamen in URLs erlauben", + "dnt": "DoNotTrack aktiviert", + "https": "HTTPS erzwingen", + "safebrowsing": "Google Safe Browsing verwenden", + "enadblock": "Adblocker aktiviert", + "openyoutube": "Youtube auf Invidious umleiten" + } + }, + "webview_tab": { + "adress_barp": "Adresse eingeben", + "search_barp": "Mit DuckDuckGo suchen" + }, + "malware_ahead": { + "visit_page": "Webseite besuchen", + "cancel_load": "Laden Abbrechen", + "show_details": "Details...", + "malware" : { + "wtitle": "Malware auf folgender Website!", + "title": "Malware auf nachfolgender Website", + "text1a": "Zurzeit auf", + "text1b": "befindliche Hacker könnten versuchen,", + "text2": "gefährliche Programme auf deinem Computer zu installieren, um Daten wie Fotos,", + "text3": "Passwörter, Nachrichten und Kreditkartendaten zu stehlen oder zu löschen.", + "detail1a": "Google Safe Browsing hat kürzlich Malware auf ", + "detail1b": " gefunden.", + "detail2": "Websites, die in der Regel sicher sind, können gelegentlich mit Malware infiziert sein." + }, + "phishing": { + "wtitle": "Bei der Aufgerufenen Seite besteht Phishing-Verdacht!", + "title": "Bei der Aufgerufenen Seite besteht Phishing-Verdacht!", + "text1a": "Hacker könnten auf", + "text1b": "etwa versuchen, Sie zur Installation von Software", + "text2": "oder zur Herausgabe von Daten, wie Passwörtern, Telefonnummern oder Kreditkartendetails", + "text3": "zu Bewegen.", + "detail1a": "Google Safe Browsing hat kürzlich Phishing-Methoden auf ", + "detail1b": " gefunden.", + "detail2": "Phsihing Seiten tun so, als ob sie andere Seiten seien, um sie zu täuschen." + } + }, + "adblock_menu": { + "text1e": "Der Adblocker ist aktiviert.", + "text1d": "Der Adblocker ist deaktiviert.", + "current_url": "Aktuelle URL: ", + "view_source": "Dies ist die Ansicht eines Quelltext und wird nicht blockiert", + "browser_file": "Dies ist eine Browserseite und wird nicht blockiert", + "local_file": "Diese Seite ist eine Lokaldatei und wird nicht blockiert", + "blocked": "Diese Seite wurde durch die Adliste blockiert", + "blacklist_blocked": "Diese Seite wurde durch die Blacklist blockiert", + "blocked_whitelist": "Diese Seite steht auf der Adliste, wurde aber gewhitelisted", + "not_blocked": "Diese Seite steht nicht auf der Adliste", + "close_button": "Schließen", + "settings_button": "Einstellungen" + }, + "units": { + "sec": "Sekunden", + "min": "Minuten", + "sec1": "Sekunde", + "min1": "Minute" + }, + "show_downloads": { + "no_downloads": "Keine aktive Downloads in der Sitzung", + "1_download": "1 Download", + "multi_download": " Downloads", + "cancel_download": "Download Abbrechen", + "copy_download": "Downloadaddresse kopieren", + "open_download": "Zielordner öffnen", + "pause_download": "Download pausieren", + "waiting_download": "Warte auf Beginn...", + "paused_download": "Pausiert", + "done_download": "Fertig", + "cancelled_download": "Download abgebrochen", + "failed_download": "Download fehlgschlagen" + }, + "general": { + "yes": "Yes", + "no": "No", + "okay": "Okay", + "cancel": "Cancel", + "of": "von", + "to": "nach" + }, + "pending_downloads": { + "title": "Laufende Downloads", + "1_pending": "Es läuft noch 1 Download.", + "1_warning": "Dieser wird abgebrochen, wenn sie Brapy beenden.", + "m_pending_a": "Es laufen noch ", + "m_pending_b": " Downloads.", + "m_warning": "Diese werden abgebrochen, wenn sie Brapy beenden.", + "still_continue": "Möchten sie trotzdem fortfahren?", + "theses_running": "Folgende Downloads laufen noch:", + "deez": "nuts" + }, + "context_menu": { + "back": "Zurück", + "forward": "Vor", + "reload": "Neu Laden", + "home": "Startseite" + }, + "settings": { + "country_notice": "Hinweis zu Konfiguration", + "country_not1": "Deine Region konnte nicht ermittelt werden.", + "country_fallback": "Es wird nun der US Server als Fallback verwendet.", + "invidious_notavailable": "Ein Invidious Server für deine Region ist leider nicht verfügbar.", + "invidious_turnedoff": "Die Weiterleitung von Youtube auf einen Invidious Server wird temporär deaktiviert.", + "country_detected1": "Deine Aktuelle Region wurde als ", + "country_detected2": " erkannt.", + "invidious_settings": "Sie können einen bestimmten Server in den Einstellungen einstellen.", + "country_available": "Die verfügbaren Server sind:", + "country_list": "DE, FR, CL, US, RO, LU, FI, SE, SG, ES, IN, NL, JP, LT", + "creating_adlist": "Adliste wird erstellt...", + "creating_adlist2": "Die Adliste für den Adblocker wird erstellt..." + }, + "upgrade": { + "done": "Upgrade abgeschlossen", + "confirm": "Upgrade bestätigen", + "cancelled": "Upgrade abgebrochen", + "continue1": "Möchten sie mit den Upgrade auf ", + "continue2": " fortfahren?", + "failed1a": "Das Upgrade kann nicht fortfahren, da ", + "failed1b": " durch eine Paketverwaltung installiert wurde.", + "failed2a": "Bitte verwenden sie die Paketverwaltung um ", + "failed2b": " zu aktualisieren oder kompilieren sie das Paket selber." + }, + "tabs_loading": { + "error_while": "Fehler beim Laden", + "couldnt_restore": "Die Vorherige Sitzung konnte nicht wiederhergestellt werden:" + }, + "ctrlq_close": { + "confirm_close": "Schließen bestätigen", + "really_quit": "Möchten sie Brapy wirklich beenden?" + }, + "adress_bar": { + "view-source": "Seitenquelltext von ", + "error-url": "Fehler beim Laden der Webseite", + "error-file": "Fehler beim Laden der Datei" + }, + "download_dialog": { + "title": "Datei Herunterladen...", + "name": "Name: ", + "browse": "Auswählen...", + "save": "Speichern", + "file_conflict": "Dateikonflikt", + "already_exists": "Die Datei existiert bereits.", + "may_overwrite": "Wenn sie fortfahren wird diese Datei überschrieben.", + "still_continue": "Möchten sie wirklich fortfahren?", + "save_file": "Datei Speichern...", + "all_files": "Alle Dateien" + } +} \ No newline at end of file diff --git a/lang/en.json b/lang/en.json new file mode 100644 index 0000000..f317253 --- /dev/null +++ b/lang/en.json @@ -0,0 +1,164 @@ +{ + "custom_tab": { + "brapy:settings": { + "name": "Settings", + "subtitle": "Settings", + "apply_button": "Apply changes", + "title1": "General", + "title2": "Security", + "title3": "Adblocker", + "title4": "Features", + "adblockl1": "Whiteliste: (Each URL in a new line)", + "adblockl2": "Blackliste: (Each URL in a new line)", + "featl1": "Use this Country:", + "featl1p": "Detect Country automaticly", + "confirmq": "Confirm close with CTRL+Q", + "userinurl": "Allow Usernames in URLs", + "dnt": "Enable DoNotTrack", + "https": "Enforce HTTPS", + "safebrowsing": "Use Google Safe Browsing", + "enadblock": "Enable Adblocker", + "openyoutube": "Redirect Youtube to Invidious" + } + }, + "webview_tab": { + "adress_barp": "Enter Address", + "search_barp": "Search with DuckDuckGo" + }, + "malware_ahead": { + "visit_page": "Visit Website", + "cancel_load": "Cancel Loading", + "show_details": "Details...", + "malware" : { + "wtitle": "The Site ahead contains malware", + "title": "The Site ahead contains malware!", + "text1a": "Attackers currently on", + "text1b": "might attempt to install dangerous programs on", + "text2": "your computer that steal or delete your information (for example, photos, passwords,", + "text3": "messages, and credit cards).", + "detail1a": "Google Safe Browsing has recently found malware on ", + "detail1b": ".", + "detail2": "Websites that are generally safe can occasionally be infected with malware." + }, + "phishing": { + "wtitle": "Phishing attack ahead", + "title": "Phishing attack ahead!", + "text1a": "Attackers on", + "text1b": "might trick you to steal", + "text2": "your information (for example passwords,", + "text3": "messages, or credit cards).", + "detail1a": "Google Safe Browsing recently detected phishing on ", + "detail1b": ".", + "detail2": "Phishing sites pretend to be other websites to trick you." + } + }, + "adblock_menu": { + "text1e": "The Adblocker is enabled.", + "text1d": "The Adblocker is disabled.", + "current_url": "Current URL: ", + "view_source": "This is a Source-Code view and won't be blocked", + "browser_file": "This is a Browser-Site and won't be blocked", + "local_file": "This is a local file and won't be blocked", + "blocked": "This Site was blocked through the Adliste", + "blacklist_blocked": "This Site was blocked through the Blacklist", + "blocked_whitelist": "This Site is on the Adlist, but was whitelisted", + "not_blocked": "This Site is not on the Adlist", + "close_button": "Close", + "settings_button": "Settings" + }, + "units": { + "sec": "Seconds", + "min": "Minutes", + "sec1": "Second", + "min1": "Minute" + }, + "show_downloads": { + "no_downloads": "No active Downloads in this Session", + "1_download": "1 Download", + "multi_download": " Downloads", + "cancel_download": "Cancel Download", + "copy_download": "Copy Downloadadress", + "open_download": "Open Destination", + "pause_download": "Pause Download", + "waiting_download": "Waiting to start...", + "paused_download": "Paused", + "done_download": "Done", + "cancelled_download": "Download cancelled", + "failed_download": "Download failed" + }, + "general": { + "yes": "Yes", + "no": "No", + "okay": "Okay", + "cancel": "Cancel", + "of": "von", + "to": "nach" + }, + "pending_downloads": { + "title": "Running Downloads", + "1_pending": "One Download is still running.", + "1_warning": "This will be canceled if you exit Brapy.", + "m_pending_a": "", + "m_pending_b": " Downloads are still running.", + "m_warning": "These will be canceled when they exit Brapy.", + "still_continue": "Do you still want to continue?", + "theses_running": "These Downloads are still running:", + "deez": "nuts :-)" + }, + "context_menu": { + "back": "Back", + "forward": "Forward", + "reload": "Reload", + "home": "Home" + }, + "settings": { + "country_notice": "Note on configuration", + "country_not1": "Your region could not be determined.", + "country_fallback": "The US server is now used as a fallback.", + "invidious_notavailable": "Unfortunately, an Invidious server is not available for your region.", + "invidious_turnedoff": "The redirection of YouTube to an Invidious server will be temporarily deactivated.", + "country_detected1": "Your current region was recognized as ", + "country_detected2": ".", + "invidious_settings": "You can set a specific server in the settings.", + "country_available": "The available servers are:", + "country_list": "DE, FR, CL, US, RO, LU, FI, SE, SG, ES, IN, NL, JP, LT", + "creating_adlist": "Adlist is being created...", + "creating_adlist2": "The adlist for the adblocker is being created..." + }, + "upgrade": { + "done": "Upgrade done", + "confirm": "Confirm Upgrade", + "cancelled": "Upgrade cancelled", + "continue1": "Do you want to continue with the upgrade to ", + "continue2": "?", + "failed1a": "The Upgrade cant continue, because ", + "failed1b": " was installed trough an packagemanager.", + "failed2a": "Please use the packagemanager to update ", + "failed2b": " or compile the package yourself." + }, + "tabs_loading": { + "error_while": "Error while Loading", + "couldnt_restore": "The previous session could not be restored:" + }, + "ctrlq_close": { + "confirm_close": "Confirm Close", + "really_quit": "Do you really want to close Brapy?" + }, + "adress_bar": { + "view-source": "Source Code of ", + "error_url": "Error while Loading the Website", + "error_file": "Error while Loading the File" + }, + "download_dialog": { + "title": "Download File...", + "name": "Name: ", + "browse": "Browse...", + "save": "Save", + "file_conflict": "Fileconflict", + "already_exists": "The File already exists.", + "may_overwrite": "If you continue, this file will be overwritten.", + "still_continue": "Dou you really want to continue?", + "save_file": "Save File...", + "all_files": "All Files" + } +} \ No newline at end of file diff --git a/linux_setup.py b/linux_setup.py index 678b3c1..947fe1f 100755 --- a/linux_setup.py +++ b/linux_setup.py @@ -10,11 +10,11 @@ except ModuleNotFoundError: print("Installing Libraries") if os.path.exists("/etc/arch-release"): - os.system("pkexec pacman -S --noconfirm --needed python-pyqt5 python-requests python-matplotlib") + os.system("pkexec pacman -S --noconfirm --needed python-pyqt5 python-requests python-matplotlib python-pip") elif os.path.exists("/etc/debian_version"): - os.system("pkexec apt-get install python3-pyqt5 python3-requests python3-matplotlib -y") + os.system("pkexec apt-get install python3-pyqt5 python3-requests python3-matplotlib python3-pip -y") elif os.path.exists("/etc/redhat-release"): - os.system("pkexec dnf install PyQt python3-requests python-matplotlib -y") + os.system("pkexec dnf install PyQt python3-requests python-matplotlib python-pip -y") else: pip.main(["install", "pyqt5", "requets", "matplotlib"]) subprocess.run("./linux_setup.py", shell=True) @@ -285,16 +285,20 @@ def update_progress_bar(value): elif value == 12: log1.append("Kopiere genadlist.py nach /usr/local/share/brapy/genadlist.py") elif value == 13: - log1.append("Kopiere uninstall.sh nach /usr/local/bin/brapy-uninstaller") + log1.append("Kopiere lang/en.json nach /usr/local/share/brapy/lang/en.json") elif value == 14: - log1.append("Kopiere brapy.desktop nach /usr/share/applications/brapy.desktop") + log1.append("Kopiere lang/de.json nach /usr/local/share/brapy/lang/de.json") elif value == 15: - log1.append("Schriftarten werden herunterladen...") + log1.append("Kopiere uninstall.sh nach /usr/local/bin/brapy-uninstaller") elif value == 16: - log1.append("Kopieren wird abgeschlossen...") + log1.append("Kopiere brapy.desktop nach /usr/share/applications/brapy.desktop") elif value == 17: - log1.append("Installation wird verifiziert...") + log1.append("Schriftarten werden herunterladen...") elif value == 18: + log1.append("Kopieren wird abgeschlossen...") + elif value == 19: + log1.append("Installation wird verifiziert...") + elif value == 20: log1.append("Fertig. Klicken Sie auf Weiter") log1.moveCursor(log1.textCursor().End) @@ -327,6 +331,7 @@ def run_installation(): progress_updater.update_progress.emit(2) os.makedirs("/tmp/brapy/", exist_ok=True) os.makedirs("/tmp/brapy-bin/", exist_ok=True) + os.makedirs("/tmp/brapy/lang", exist_ok=True) progress_updater.update_progress.emit(3) copyfile("brapy_logo.png", "/tmp/brapy/brapy_logo.png") progress_updater.update_progress.emit(4) @@ -348,25 +353,29 @@ def run_installation(): progress_updater.update_progress.emit(12) copyfile("genadlist.py", "/tmp/brapy/genadlist.py") progress_updater.update_progress.emit(13) - copyfile("uninstall.sh", "/tmp/brapy-bin/brapy-uninstaller") + copyfile("lang/en.json", "/tmp/brapy/lang/en.json") progress_updater.update_progress.emit(14) - copyfile("brapy.desktop", "/tmp/brapy.desktop") + copyfile("lang/de.json", "/tmp/brapy/lang/de.json") progress_updater.update_progress.emit(15) + copyfile("uninstall.sh", "/tmp/brapy-bin/brapy-uninstaller") + progress_updater.update_progress.emit(16) + copyfile("brapy.desktop", "/tmp/brapy.desktop") + progress_updater.update_progress.emit(17) fonts = font_manager.get_font_names() if not "Material Icons" in fonts: copyfileobj(requests.get("https://github.com/google/material-design-icons/raw/master/font/MaterialIcons-Regular.ttf", stream=True).raw, open("/tmp/MaterialIcons-Regular.ttf", 'wb')) if not "Material Icons Outlined" in fonts: copyfileobj(requests.get("https://github.com/google/material-design-icons/raw/master/font/MaterialIconsOutlined-Regular.otf", stream=True).raw, open("/tmp/MaterialIconsOutlined-Regular.otf", 'wb')) - progress_updater.update_progress.emit(16) + progress_updater.update_progress.emit(18) process = subprocess.Popen("pkexec bash -c 'mkdir -p {/usr/local/share/brapy,/usr/local/bin}; mv /tmp/brapy/* /usr/local/share/brapy/; mv /tmp/brapy-bin/* /usr/local/bin/; mv /tmp/brapy.desktop /usr/share/applications/; [ -f /tmp/MaterialIcons-Regular.ttf ] && mv /tmp/MaterialIcons-Regular.ttf /usr/share/fonts/; [ -f /tmp/MaterialIconsOutlined-Regular.otf ] && mv /tmp/MaterialIconsOutlined-Regular.otf /usr/share/fonts/; chown -R root:root {/usr/local/bin/,/usr/local/share/brapy,/usr/share/applications,/usr/share/fonts}; chmod +x /usr/local/bin/{brapy,brapy-uninstaller}; chmod +x /usr/local/share/brapy/genadlist.py'", shell=True) stdoutdata, stderrdata = process.communicate() if process.returncode == 127: progress_updater.installfailed.emit("Der Nutzer hat den Vorgang abgebrochen.") return - progress_updater.update_progress.emit(17) + progress_updater.update_progress.emit(19) if not os.path.exists("/usr/local/share/brapy") or not os.path.exists("/usr/share/applications/brapy.desktop") or not os.path.exists("/usr/local/bin/brapy") or not os.path.exists("/usr/local/bin/brapy-uninstaller"): progress_updater.installfailed.emit("Das Kopieren der Dateien ist fehlgeschlagen.") - progress_updater.update_progress.emit(18) + progress_updater.update_progress.emit(20) self.closeable = True button_next.setEnabled(True) diff --git a/main.py b/main.py index 9c2004e..417ebe9 100755 --- a/main.py +++ b/main.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 -import sys, requests, os, json, getopt, re, subprocess, ast, urllib3, pyperclip +import sys, requests, os, json, getopt, re, subprocess, ast, urllib3, pyperclip, math, webbrowser from PyQt5.QtCore import Qt, QUrl, QDir, QTimer, QThread, pyqtSignal, QSize -from PyQt5.QtWidgets import QApplication, QMainWindow, QLineEdit, QHBoxLayout, QVBoxLayout, QWidget, QTextEdit, QPushButton, QTabWidget, QTabBar, QMenu, QAction, QDialog, QLabel, QFileDialog, QProgressBar, QScrollArea, QFrame, QCheckBox +from PyQt5.QtWidgets import QApplication, QMainWindow, QLineEdit, QHBoxLayout, QVBoxLayout, QWidget, QTextEdit, QPushButton, QTabWidget, QTabBar, QMenu, QAction, QDialog, QLabel, QFileDialog, QProgressBar, QScrollArea, QFrame, QCheckBox, QComboBox from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineProfile, QWebEnginePage, QWebEngineSettings, QWebEngineDownloadItem from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor, QWebEngineUrlRequestInfo from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply @@ -15,12 +15,13 @@ requests.packages.urllib3.disable_warnings(InsecureRequestWarning) config = ConfigParser() -APP_VERSION: str = "0.05.2" +APP_VERSION: str = "0.05.3" APP_VERSION_ISBETA: bool = False APP_VERSION_BETA: int = 0 APP_NAME: str = "Brapy" APP_DESCR: str = APP_NAME + " ist ein auf Qt5 (PyQt5) in Python geschriebender Webbrowser." APP_MANUAL_INSTALLED: bool = True +APP_LOCALE = None BrowserFiles: list = ["file:///usr/local/share/brapy/home.html", "file:///usr/local/share/brapy/homeupdate.html", "file:///usr/local/share/brapy/error.html", "file:///usr/local/share/brapy/errorfile.html", "file:///usr/local/share/brapy/extraerror.html", "file:///usr/local/share/brapy/upgrade.html"] @@ -63,6 +64,8 @@ def ColorPrint(text, color): sys.stdout.write("\033[1;36m") elif color == "bold-white": sys.stdout.write("\033[1;97m") + elif color == "bg-red": + sys.stdout.write("\033[0;41m") print(text) sys.stdout.write("\033[0;0m") @@ -84,16 +87,17 @@ def showDetails(self): if self.detailstype == 1: self.layout.addWidget(self.text11) self.layout.addWidget(self.text12) - self.detailsbutton.setText("Webseite besuchen") + self.detailsbutton.setText(self.translation['malware_ahead']['visit_page']) elif self.detailstype == 2: self.accept() self.detailstype += 1 - def __init__(self, url, type): + def __init__(self, url, type, translation): super().__init__() self.detailstype = 1 self.setStyleSheet('background-color: #de312e;') self.layout = QVBoxLayout(self) + self.translation = translation horiz_layout1 = QHBoxLayout() horiz_layout2 = QHBoxLayout() @@ -106,31 +110,31 @@ def __init__(self, url, type): text3 = QLabel() self.text11 = QLabel() self.text12 = QLabel() - backbutton = QPushButton("Laden Abbrechen") + backbutton = QPushButton(self.translation['malware_ahead']['cancel_load']) backbutton.clicked.connect(self.reject) backbutton.setStyleSheet('background-color: white; color: #de312e;') - self.detailsbutton = QPushButton("Details...") + self.detailsbutton = QPushButton(self.translation['malware_ahead']['show_details']) self.detailsbutton.setFixedWidth(150) self.detailsbutton.clicked.connect(self.showDetails) self.detailsbutton.setStyleSheet('background-color: #de312e;') self.setWindowIcon(QIcon('/usr/local/share/brapy/brapy_logo.png')) if type == "malware": - self.setWindowTitle("Malware auf folgender Website!") - title.setText("Malware auf nachfolgender Website") - text1.setText("Zurzeit auf " + url + " befindliche Hacker könnten versuchen,") - text2.setText("gefährliche Programme auf deinem Computer zu installieren, um Daten wie Fotos,") - text3.setText("Passwörter, Nachrichten und Kreditkartendaten zu stehlen oder zu löschen.") - self.text11.setText("Google Safe Browsing hat kürzlich Malware auf " + url + " gefunden.") - self.text12.setText("Websites, die in der Regel sicher sind, können gelegentlich mit Malware infiziert sein.") + self.setWindowTitle(self.translation['malware_ahead']['malware']['wtitle']) + title.setText(self.translation['malware_ahead']['malware']['title']) + text1.setText(self.translation['malware_ahead']['malware']['text1a'] + " " + url + " " + self.translation['malware_ahead']['malware']['text1b']) + text2.setText(self.translation['malware_ahead']['malware']['text2']) + text3.setText(self.translation['malware_ahead']['malware']['text3']) + self.text11.setText(self.translation['malware_ahead']['malware']['detail1a'] + url + self.translation['malware_ahead']['malware']['detail1b']) + self.text12.setText(self.translation['malware_ahead']['malware']['detail2']) elif type == "phish": - self.setWindowTitle("Bei der Aufgerufenen Seite besteht Phishing-Verdacht!") - title.setText("Bei der Aufgerufenen Seite besteht Phishing-Verdacht!") - text1.setText("Hacker könnten auf " + url + " etwa versuchen, Sie zur Installation von Software") - text2.setText("oder zur Herausgabe von Daten, wie Passwörtern, Telefonnummern oder Kreditkartendetails") - text3.setText("zu Bewegen.") - self.text11.setText("Google Safe Browsing hat kürzlich Phishing-Methoden auf " + url + " gefunden.") - self.text12.setText("Solche Seiten wurden erstellt, um sie zu täuschen.") + self.setWindowTitle(self.translation['malware_ahead']['phishing']['wtitle']) + title.setText(self.translation['malware_ahead']['phishing']['title']) + text1.setText(self.translation['malware_ahead']['phishing']['text1a'] + " " + url + " " + self.translation['malware_ahead']['phishing']['text1b']) + text2.setText(self.translation['malware_ahead']['phishing']['text2']) + text3.setText(self.translation['malware_ahead']['phishing']['text3']) + self.text11.setText(self.translation['malware_ahead']['phishing']['detail1a'] + url + self.translation['malware_ahead']['phishing']['detail1b']) + self.text12.setText(self.translation['malware_ahead']['phishing']['detail2']) title.setFont(QFont(title.font().family(), 20)) text1.setFont(QFont(text1.font().family(), 11)) @@ -155,7 +159,7 @@ def __init__(self, url, type): self.layout.addLayout(horiz_layout2) class AdblockMenu(QDialog): - def __init__(self, enabledstate, adlist, whitelist, current_url, blacklist): + def __init__(self, enabledstate, adlist, whitelist, current_url, blacklist, translation): super().__init__() self.setWindowTitle("Adblocker") self.setWindowIcon(QIcon('/usr/local/share/brapy/brapy_logo.png')) @@ -184,28 +188,28 @@ def __init__(self, enabledstate, adlist, whitelist, current_url, blacklist): text = QLabel() if enabledstate: - text.setText("Der Adblocker ist aktiviert.") - text2 = QLabel("Aktuelle URL: " + current_url) + text.setText(translation['adblock_menu']['text1e']) + text2 = QLabel(translation['adblock_menu']['current_url'] + current_url) if current_url.startswith("view-source://"): - text3 = QLabel("Dies ist die Ansicht eines Quelltext und wird nicht blockiert") + text3 = QLabel(translation['adblock_menu']['view_source']) elif current_url.split('?', 1)[0] in BrowserFiles: - text3 = QLabel("Dies ist eine Browserseite und wird nicht blockiert") + text3 = QLabel(translation['adblock_menu']['browser_file']) elif current_url.startswith("file://"): - text3 = QLabel("Diese Seite ist eine Lokaloatei und wird nicht blockiert") + text3 = QLabel(translation['adblock_menu']['local_file']) elif hostname in adlist and not hostname in whitelist and not hostname in blacklist: - text3 = QLabel("Diese Seite wurde durch die Adliste blockiert") + text3 = QLabel(translation['adblock_menu']['blocked']) elif hostname in adlist and not hostname in whitelist and hostname in blacklist: - text3 = QLabel("Diese Seite wurde durch die Blacklist blockiert") + text3 = QLabel(translation['adblock_menu']['blacklist_blocked']) elif hostname in adlist and hostname in whitelist: - text3 = QLabel("Diese Seite steht auf der Adliste, wurde aber gewhitelisted") + text3 = QLabel(translation['adblock_menu']['blocked_whitelist']) else: - text3 = QLabel("Diese Seite steht nicht auf der Adliste") + text3 = QLabel(translation['adblock_menu']['not_blocked']) else: - text.setText("Der Adblocker ist deaktiviert.") + text.setText(translation['adblock_menu']['text1d']) - settingsbutton = QPushButton("Einstellungen") + settingsbutton = QPushButton(translation['adblock_menu']['settings_button']) settingsbutton.clicked.connect(self.accept) - okbutton = QPushButton("Schließen") + okbutton = QPushButton(translation['adblock_menu']['close_button']) okbutton.setFixedWidth(75) okbutton.clicked.connect(self.reject) @@ -220,10 +224,10 @@ def __init__(self, enabledstate, adlist, whitelist, current_url, blacklist): layout.addLayout(horiz_layout2) class ShowDownloads(QDialog): - def __init__(self, downloads): + def __init__(self, downloads, locale): super().__init__() - self.setMinimumWidth(300) self.setMinimumWidth(600) + self.setMaximumWidth(1600) self.main_layout = QVBoxLayout(self) self.downloads: list = downloads self.overview = QLabel() @@ -236,6 +240,7 @@ def __init__(self, downloads): self.scroll_area.setWidget(self.scroll_widget) self.scroll_layout = QVBoxLayout() self.scroll_widget.setLayout(self.scroll_layout) + self.locale = locale h1layout = QHBoxLayout() h1layout.addStretch() @@ -246,12 +251,12 @@ def __init__(self, downloads): self.main_layout.addWidget(self.scroll_area) if self.downloads == []: - self.overview.setText("Keine aktive Downloads in der Sitzung") + self.overview.setText(self.locale['show_downloads']['no_downloads']) else: if len(self.downloads) == 1: - self.overview.setText("1 Download") + self.overview.setText(self.locale['show_downloads']['1_download']) else: - self.overview.setText(str(len(self.downloads)) + " Downloads") + self.overview.setText(str(len(self.downloads)) + self.locale['show_downloads']['multi_download']) for download in self.downloads: download_layout = QVBoxLayout() hlayout1 = QHBoxLayout() @@ -268,9 +273,10 @@ def __init__(self, downloads): cancel_button.setFont(QFont("Material Icons Outlined", 12)) cancel_button.setFixedSize(30, 26) cancel_button.clicked.connect(lambda: self.cancel_download(download)) + cancel_button.setToolTip(self.locale['show_downloads']['cancel_download']) hlayout1.addWidget(cancel_button) - status_label = QLabel("Bitte warten...") + status_label = QLabel() status_label.setFont(QFont(status_label.font().family(), 8)) hlayout2.addWidget(status_label) @@ -280,12 +286,21 @@ def __init__(self, downloads): copyurl_button.setFont(QFont("Material Icons Outlined", 12)) copyurl_button.setFixedSize(30, 26) copyurl_button.clicked.connect(lambda: self.copyurl_download(download)) + copyurl_button.setToolTip(self.locale['show_downloads']['copy_download']) hlayout1.addWidget(copyurl_button) + openf_button = QPushButton("") + openf_button.setFont(QFont("Material Icons Outlined", 12)) + openf_button.setFixedSize(30, 26) + openf_button.clicked.connect(lambda: self.open_folder(download)) + openf_button.setToolTip(self.locale['show_downloads']['open_download']) + hlayout1.addWidget(openf_button) + pause_button = QPushButton("") pause_button.setFont(QFont("Material Icons", 12)) pause_button.setFixedSize(30, 26) pause_button.clicked.connect(lambda: self.pause_download(download)) + pause_button.setToolTip(self.locale['show_downloads']['pause_download']) hlayout1.addWidget(pause_button) download_layout.addLayout(hlayout1) @@ -295,6 +310,7 @@ def __init__(self, downloads): 'progress_bar': progress_bar, 'cancel_button': cancel_button, 'copy_button': copyurl_button, + 'openf_button': openf_button, 'pause_button': pause_button, 'status_label': status_label, 'prev_amount': 0 @@ -316,6 +332,9 @@ def pause_download(self, download: QWebEngineDownloadItem): def copyurl_download(self, download: QWebEngineDownloadItem): pyperclip.copy(download.url().toString()) + def open_folder(self, download: QWebEngineDownloadItem): + webbrowser.open(os.path.realpath(download.path().rsplit('/', 1)[0])) + def cancel_download(self, download: QWebEngineDownloadItem): download.cancel() download_path = download.path() @@ -327,7 +346,9 @@ def cancel_download(self, download: QWebEngineDownloadItem): self.update_list() def convert_bytes(self, bytes): - if bytes >= 900000000000: + if bytes >= 900000000000000: + return str(round(bytes / 1000000000000000, 2)) + " PB" + elif bytes >= 900000000000: return str(round(bytes / 1000000000000, 2)) + " TB" elif bytes >= 900000000: return str(round(bytes / 1000000000, 2)) + " GB" @@ -338,60 +359,97 @@ def convert_bytes(self, bytes): else: return str(round(bytes, 2)) + "B" - def update_list(self): - for download in self.downloads: - layout = self.download_layouts[download] - progress_bar = layout['progress_bar'] - status_label = layout['status_label'] - prev_amount = layout['prev_amount'] - cancel_button = layout['cancel_button'] - pause_button = layout['pause_button'] - received_bytes = download.receivedBytes() - total_bytes = download.totalBytes() - - progress = 0 - state = download.state() - speed_str = self.convert_bytes((received_bytes - prev_amount) * 2) + "/s" - progress_bar.setVisible(False) - cancel_button.setDisabled(False) - pause_button.setDisabled(False) - if state == QWebEngineDownloadItem.DownloadRequested: - status_label.setText("Warte auf Beginn...") - elif state == QWebEngineDownloadItem.DownloadInProgress: - if download.isPaused(): - progress_bar.setDisabled(True) - pause_button.setText("") - if total_bytes == -1: - status_label.setText(self.convert_bytes(received_bytes) + " / ? - Pausiert") - progress = 100 - else: - status_label.setText(self.convert_bytes(received_bytes) + " / " + self.convert_bytes(total_bytes) + " - Pausiert") - progress = int((received_bytes / total_bytes) * 100) + def convert_time(self, sec): + h = math.floor(sec / 3600) + r = sec % 3600 + m = math.floor(r / 60) + s = round(r % 60) + if s == 1: + secs = self.locale['units']['sec1'] + else: + secs = self.locale['units']['sec'] + if m == 1: + mins = self.locale['units']['min1'] + else: + mins = self.locale['units']['min'] + if h > 0: + if m == 0: + return f"{h}h" + else: + return f"{h}h {m}m" + else: + if m == 0: + return f"{s} {secs}" + elif m <= 3: + if s == 0: + return f"{m} {mins}" else: - progress_bar.setDisabled(False) - pause_button.setText("") - if total_bytes == -1: - status_label.setText(self.convert_bytes(received_bytes) + " / ? - " + speed_str) - progress = 100 + return f"{m} {mins} {s} {secs}" + else: + return f"{m} {mins}" + return "Error calculation time..." + + def update_list(self): + for download in self.downloads: + layout = self.download_layouts[download] + progress_bar = layout['progress_bar'] + status_label = layout['status_label'] + prev_amount = layout['prev_amount'] + cancel_button = layout['cancel_button'] + openf_button = layout['openf_button'] + pause_button = layout['pause_button'] + received_bytes = download.receivedBytes() + total_bytes = download.totalBytes() + + progress = 0 + state = download.state() + speed = (received_bytes - prev_amount) * 2 + speed_str = self.convert_bytes(speed) + "/s" + progress_bar.setVisible(False) + cancel_button.setDisabled(False) + pause_button.setDisabled(False) + openf_button.setDisabled(False) + if state == QWebEngineDownloadItem.DownloadRequested: + status_label.setText(self.locale['show_downloads']['waiting_download']) + elif state == QWebEngineDownloadItem.DownloadInProgress: + if download.isPaused(): + progress_bar.setDisabled(True) + pause_button.setText("") + if total_bytes == -1: + status_label.setText(self.convert_bytes(received_bytes) + " / ? - " + self.locale['show_downloads']['paused_download']) + progress = 100 + else: + status_label.setText(self.convert_bytes(received_bytes) + " / " + self.convert_bytes(total_bytes) + " - " + self.locale['show_downloads']['paused_download']) + progress = int((received_bytes / total_bytes) * 100) else: - status_label.setText(self.convert_bytes(received_bytes) + " / " + self.convert_bytes(total_bytes) + " - " + speed_str) - progress = int((received_bytes / total_bytes) * 100) - progress_bar.setVisible(True) - elif state == QWebEngineDownloadItem.DownloadCompleted: - cancel_button.setDisabled(True) - pause_button.setDisabled(True) - status_label.setText("Fertig - " + self.convert_bytes(total_bytes)) - elif state == QWebEngineDownloadItem.DownloadCancelled: - cancel_button.setDisabled(True) - pause_button.setDisabled(True) - status_label.setText("Download abgebrochen") - elif state == QWebEngineDownloadItem.DownloadInterrupted: - cancel_button.setDisabled(True) - pause_button.setDisabled(True) - status_label.setText("Download fehlgschlagen") - - layout['prev_amount'] = received_bytes - progress_bar.setValue(progress) + progress_bar.setDisabled(False) + pause_button.setText("") + if total_bytes == -1: + status_label.setText(self.convert_bytes(received_bytes) + " / ? - " + speed_str) + progress = 100 + else: + if speed == 0: + status_label.setText(self.convert_bytes(received_bytes) + " / " + self.convert_bytes(total_bytes) + " - " + speed_str) + else: + status_label.setText(self.convert_time((total_bytes - received_bytes) / speed) + ' ' + self.convert_bytes(received_bytes) + " / " + self.convert_bytes(total_bytes) + " - " + speed_str) + progress = int((received_bytes / total_bytes) * 100) + progress_bar.setVisible(True) + elif state == QWebEngineDownloadItem.DownloadCompleted: + cancel_button.setDisabled(True) + pause_button.setDisabled(True) + status_label.setText(self.locale['show_downloads']['done_download'] + " - " + self.convert_bytes(total_bytes)) + elif state == QWebEngineDownloadItem.DownloadCancelled: + cancel_button.setDisabled(True) + pause_button.setDisabled(True) + openf_button.setDisabled(True) + status_label.setText(self.locale['show_downloads']['cancelled_download']) + elif state == QWebEngineDownloadItem.DownloadInterrupted: + cancel_button.setDisabled(True) + pause_button.setDisabled(True) + status_label.setText(self.locale['show_downloads']['failed_download']) + + layout['prev_amount'] = received_bytes + progress_bar.setValue(progress) def closeEvent(self, event): self.closeWindow() @@ -402,13 +460,14 @@ def closeWindow(self): self.reject() class DownloadDialog(QDialog): - def __init__(self, url, file_name, parent=None): + def __init__(self, locale, url, file_name, parent=None): super().__init__(parent) - self.setWindowTitle("Datei Herunterladen...") + self.locale = locale + self.setWindowTitle(self.locale['download_dialog']['title']) self.setWindowIcon(QIcon('/usr/local/share/brapy/brapy_logo.png')) layout = QVBoxLayout(self) - self.file_label = QLabel(f"Name: {file_name}") + self.file_label = QLabel(f"{self.locale['download_dialog']['name']}{file_name}") self.file_label.setFixedWidth(500) self.url_label = QLabel(f"URL: {url}") self.url_label.setFixedWidth(500) @@ -418,38 +477,49 @@ def __init__(self, url, file_name, parent=None): pathlayout = QHBoxLayout() self.path_lineedit = QLineEdit() pathlayout.addWidget(self.path_lineedit) - self.browse_button = QPushButton("Auswählen...") + self.browse_button = QPushButton(self.locale['download_dialog']['browse']) self.browse_button.clicked.connect(self.browse_path) pathlayout.addWidget(self.browse_button) layout.addLayout(pathlayout) buttonlayout = QHBoxLayout() - self.confirm_button = QPushButton("Downloaden") - self.confirm_button.clicked.connect(self.accept) - self.cancel_button = QPushButton("Abbrechen") + self.confirm_button = QPushButton(self.locale['download_dialog']['save']) + self.confirm_button.clicked.connect(self.accept_download) + self.cancel_button = QPushButton(self.locale['general']['cancel']) self.cancel_button.clicked.connect(self.reject) buttonlayout.addWidget(self.cancel_button) buttonlayout.addWidget(self.confirm_button) layout.addLayout(buttonlayout) + def accept_download(self): + path = self.path_lineedit.text() + if os.path.exists(path): + dialog = YesNoDialog('yesno', self.locale, self.locale['download_dialog']['file_conflict'], self.locale['download_dialog']['already_exists'], self.locale['download_dialog']['may_overwrite'], self.locale['download_dialog']['still_continue']) + if dialog.exec_() == QDialog.Accepted: + self.accept() + else: + return + else: + self.accept() + def browse_path(self): - file_path, _ = QFileDialog.getSaveFileName(self, "Datei Speichern...", self.path_lineedit.text(), "Alle Dateien") + file_path, _ = QFileDialog.getSaveFileName(self, self.locale['download_dialog']['save_file'], self.path_lineedit.text(), self.locale['download_dialog']['all_files']) if not file_path == "": self.path_lineedit.setText(file_path) class ConfirmUpgrade(QDialog): - def __init__(self, installed, toversion=None): + def __init__(self, locale, installed, toversion=None): super().__init__() self.setWindowIcon(QIcon('/usr/local/share/brapy/brapy_logo.png')) if installed: - self.setWindowTitle("Upgrade bestätigen") + self.setWindowTitle(locale['upgrade']['confirm']) else: - self.setWindowTitle("Upgrade abgebrochen") + self.setWindowTitle(locale['upgrade']['cancelled']) layout = QVBoxLayout(self) if installed: - self.text = QLabel(f"Möchten sie mit den Upgrade auf {APP_NAME.lower()} {toversion} fortfahren?") - self.button_yes = QPushButton("Ja") - self.button_no = QPushButton("Nein") + self.text = QLabel(f"{locale['upgrade']['continue1']}{APP_NAME.lower()} {toversion}{locale['upgrade']['continue2']}") + self.button_yes = QPushButton(locale['general']['yes']) + self.button_no = QPushButton(locale['general']['no']) self.button_yes.clicked.connect(self.accept) self.button_no.clicked.connect(self.reject) layout.addWidget(self.text) @@ -458,16 +528,16 @@ def __init__(self, installed, toversion=None): button_layout.addWidget(self.button_yes) layout.addLayout(button_layout) else: - self.text = QLabel(f"Das Upgrade kann nicht fortfahren, da {APP_NAME} durch eine Paketverwaltung installiert wurde.") - self.text2 = QLabel(f"Bitte verwenden sie die Paketverwaltung um {APP_NAME} zu aktualisieren oder kompilieren sie das Paket selber.") - self.button_ok = QPushButton("Ok") + self.text = QLabel(f"{locale['upgrade']['failed1a']}{APP_NAME}{locale['upgrade']['failed1b']}") + self.text2 = QLabel(f"{locale['upgrade']['failed2a']}{APP_NAME}{locale['upgrade']['failed2b']}") + self.button_ok = QPushButton(locale['general']['okay']) self.button_ok.clicked.connect(self.reject) layout.addWidget(self.text) layout.addWidget(self.text2) layout.addWidget(self.button_ok) class BrowserInterceptor(QWebEngineUrlRequestInterceptor): - def __init__(self, config_allowusernamesinurl, config_enableadblocker, config_adblockwhitelist, config_rediyoutube, config_httpsrewrite, config_dnt, config_safebrowse, final_adlist, debugged, indi_url): + def __init__(self, config_allowusernamesinurl, config_enableadblocker, config_adblockwhitelist, config_rediyoutube, config_httpsrewrite, config_dnt, config_safebrowse, final_adlist, debugged, indi_url, translation): super().__init__() self.config_allowusernamesinurl = config_allowusernamesinurl self.config_enableadblocker = config_enableadblocker @@ -479,8 +549,10 @@ def __init__(self, config_allowusernamesinurl, config_enableadblocker, config_ad self.final_adlist = final_adlist self.debugged = debugged self.invidious_url = indi_url + self.translation = translation self.norewrite = [] self.resultlist = [] + self.locale = translation if self.debugged: print("[INTERCEPTOR] Loaded") @@ -539,7 +611,7 @@ def interceptRequest(self, info: QWebEngineUrlRequestInfo): info.block(True) if self.debugged: print("[INTERCEPTOR] Blocked (Username): " + url) - dialog = YesNoDialog("okcancel", "Sicherheitswarnung", 'Das Laden von "' + hostname + '" wurde abgebrochen.', 'In der URL wurde der Benutzername "' + username + '" angegeben.', 'Dies könnte ein Versuch sein, sie zu täuschen, um Anmeldedaten zu stehlen.', 'Klicken sie OK um trotzdem fort zu fahren.') + dialog = YesNoDialog("okcancel", self.locale, "Sicherheitswarnung", 'Das Laden von "' + hostname + '" wurde abgebrochen.', 'In der URL wurde der Benutzername "' + username + '" angegeben.', 'Dies könnte ein Versuch sein, sie zu täuschen, um Anmeldedaten zu stehlen.', 'Klicken sie OK um trotzdem fort zu fahren.') if dialog.exec_() == QDialog.Accepted: info.block(False) else: @@ -570,7 +642,7 @@ def interceptRequest(self, info: QWebEngineUrlRequestInfo): print("[INTERCEPTOR] Redirected to HTTPS: " + url) except requests.exceptions.RequestException as e: info.block(True) - dialog = YesNoDialog("yesno", "HTTPS-Variante nicht verfügbar", "Die HTTPS Variante von " + hostname + " ist nicht verfügbar.", "Möchten sie den HTTPS-Rewrite für diese Seite temporär deaktivieren?") + dialog = YesNoDialog("yesno", self.locale, "HTTPS-Variante nicht verfügbar", "Die HTTPS Variante von " + hostname + " ist nicht verfügbar.", "Möchten sie den HTTPS-Rewrite für diese Seite temporär deaktivieren?") if dialog.exec_() == QDialog.Accepted: self.norewrite.append(hostname) info.block(False) @@ -603,7 +675,7 @@ def interceptRequest(self, info: QWebEngineUrlRequestInfo): self.resultlist.append({'hostname': url_without_arg, 'result': safebrowsing}) if safebrowsing == "malware" or safebrowsing == "phishing": info.block(True) - dialog = MalwareAhead(hostname, safebrowsing) + dialog = MalwareAhead(hostname, safebrowsing, self.translation) if dialog.exec_() == QDialog.Accepted: info.block(False) else: @@ -615,7 +687,7 @@ def interceptRequest(self, info: QWebEngineUrlRequestInfo): ColorPrint("[INTERCEPTOR] Safe-Browsing Return for " + url + ": PHISHING (offline check)", "yellow") if safebrowsing == "malware" or safebrowsing == "phishing": info.block(True) - dialog = MalwareAhead(hostname, safebrowsing) + dialog = MalwareAhead(hostname, safebrowsing, self.translation) if dialog.exec_() == QDialog.Accepted: info.block(False) @@ -647,7 +719,7 @@ def __init__(self, okbutton, title, line1, line2=None, line3=None, line4=None, l layout.addWidget(self.button) class YesNoDialog(QDialog): - def __init__(self, type, title, line1, line2=None, line3=None, line4=None): + def __init__(self, locale, type, title, line1, line2=None, line3=None, line4=None): super().__init__() self.setWindowIcon(QIcon('/usr/local/share/brapy/brapy_logo.png')) self.setWindowTitle(title) @@ -665,11 +737,11 @@ def __init__(self, type, title, line1, line2=None, line3=None, line4=None): layout.addWidget(self.line4) button_layout = QHBoxLayout() if type == "yesno": - self.button1 = QPushButton("Nein") - self.button2 = QPushButton("Ja") + self.button1 = QPushButton(locale['general']['no']) + self.button2 = QPushButton(locale['general']['yes']) elif type == "okcancel": - self.button1 = QPushButton("Abbrechen") - self.button2 = QPushButton("Ok") + self.button1 = QPushButton(locale['general']['cancel']) + self.button2 = QPushButton(locale['general']['okay']) self.button1.clicked.connect(self.reject) self.button2.clicked.connect(self.accept) button_layout.addWidget(self.button1) @@ -677,27 +749,28 @@ def __init__(self, type, title, line1, line2=None, line3=None, line4=None): layout.addLayout(button_layout) class UnfinishedDownloadDialog(QDialog): - def __init__(self, unfinished_downloads: list): + def __init__(self, locale, unfinished_downloads: list): super().__init__() self.unfinished_downloads = unfinished_downloads self.setWindowIcon(QIcon('/usr/local/share/brapy/brapy_logo.png')) - self.setWindowTitle("Laufende Downloads") + self.setWindowTitle(locale['pending_downloads']['title']) layout = QVBoxLayout(self) - if len(self.unfinished_downloads) == 1:\ - label1 = QLabel("Es läuft noch 1 Download.") + if len(self.unfinished_downloads) == 1: + label1 = QLabel(locale['pending_downloads']['1_pending']) + label2 = QLabel(locale['pending_downloads']['1_warning']) else: - label1 = QLabel("Es laufen noch " + len(self.unfinished_downloads) + " Downloads.") - label2 = QLabel("Dieser wird abgebrochen, wenn sie Brapy beenden.") - label3 = QLabel("Möchten sie trotzdem fortfahren?") + label1 = QLabel(locale['pending_downloads']['m_pending_a'] + len(self.unfinished_downloads) + locale['pending_downloads']['m_pending_b']) + label2 = QLabel(locale['pending_downloads']['m_warning']) + label3 = QLabel(locale['pending_downloads']['still_continue']) self.text_box = QTextEdit() self.text_box.setReadOnly(True) self.text_box.setFixedWidth(550) - yes_button = QPushButton("Ja") + yes_button = QPushButton(locale['general']['yes']) yes_button.clicked.connect(self.accept) yes_button.setFixedWidth(70) - no_button = QPushButton("Nein") + no_button = QPushButton(locale['general']['no']) no_button.clicked.connect(self.reject) no_button.setFixedWidth(70) @@ -713,7 +786,7 @@ def __init__(self, unfinished_downloads: list): layout.addWidget(self.text_box) layout.addLayout(h1layout) - self.text_box.append("Folgende Downloads laufen noch:") + self.text_box.append("" + locale['pending_downloads']['theses_running'] + "") for download_array in self.unfinished_downloads: self.text_box.append(download_array[0] + " von " + download_array[2] + " nach " + download_array[1]) @@ -721,22 +794,22 @@ def __init__(self, unfinished_downloads: list): class ProgressDialog(QDialog): def __init__(self, process, title, text): super().__init__() - + self.setWindowIcon(QIcon('/usr/local/share/brapy/brapy_logo.png')) self.setWindowTitle(title) self.setFixedHeight(50) - + layout = QVBoxLayout() - + self.label = QLabel(title) self.progress_bar = QProgressBar() self.progress_bar.setRange(0, 0) - + layout.addWidget(self.label) layout.addWidget(self.progress_bar) - + self.setLayout(layout) - + self.process = process self.process.finished.connect(self.close_dialog) @@ -762,18 +835,22 @@ class BrapyPage(QWebEnginePage): def certificateError(self, error): url = error.url().toString() hostname = urlparse(url).hostname - dialog = YesNoDialog("yesno", "Zertifikatfehler", f"Das Laden von {hostname} wurde abgebrochen.", "Es wurde ein Zertifikatfehler erkannt.", "Falls Sie die Website besuchen, könnten Angreifer versuchen, Passwörter, E-Mails oder Kreditkartendaten zu stehlen.", "Möchten sie wirklich fortfahren?") - if dialog.exec_() == QDialog.Accepted: - error.ignoreCertificateError() - return True + if not APP_LOCALE == None: + dialog = YesNoDialog("yesno", self.locale, "Zertifikatfehler", f"Das Laden von {hostname} wurde abgebrochen.", "Es wurde ein Zertifikatfehler erkannt.", "Falls Sie die Website besuchen, könnten Angreifer versuchen, Passwörter, E-Mails oder Kreditkartendaten zu stehlen.", "Möchten sie wirklich fortfahren?") + if dialog.exec_() == QDialog.Accepted: + error.ignoreCertificateError() + return True + else: + return super().certificateError(error) else: return super().certificateError(error) class BrapyEngine(QWebEngineView): - def __init__(self, homeurl, *args, **kwargs): + def __init__(self, locale, homeurl, *args, **kwargs): super().__init__(*args, **kwargs) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.showContextMenu) self.homeurl = homeurl + self.locale = locale settings = self.settings() settings.setAttribute(QWebEngineSettings.JavascriptEnabled, True) @@ -784,19 +861,19 @@ def __init__(self, homeurl, *args, **kwargs): def showContextMenu(self, pos): menu = QMenu(self) - action_back = QAction("Zurück") + action_back = QAction(self.locale['context_menu']['back']) action_back.triggered.connect(self.back) menu.addAction(action_back) - action_forward = QAction("Vor") + action_forward = QAction(self.locale['context_menu']['forward']) action_forward.triggered.connect(self.forward) menu.addAction(action_forward) - action_reload = QAction("Neu Laden") + action_reload = QAction(self.locale['context_menu']['reload']) action_reload.triggered.connect(self.reload) menu.addAction(action_reload) - action_home = QAction("Startseite") + action_home = QAction(self.locale['context_menu']['home']) action_home.triggered.connect(lambda: self.load(QUrl(self.homeurl))) menu.addAction(action_home) @@ -814,7 +891,7 @@ def __init__(self, debugmode): self.update_config() if self.debugmode: - print("[BROWSER] Suche nach Stable-Updates") + print("[BROWSER] Search for Stable-Updates") text = requests.get("https://raw.githubusercontent.com/Niklas20114552/brapy/main/main.py").text pattern = r'APP_VERSION: str = "(.+?)"' @@ -881,7 +958,7 @@ def __init__(self, debugmode): corner_widget = QWidget() corner_widget.setLayout(corner_layout) - self.webview_interceptor = BrowserInterceptor(self.config_allowusernamesinurl, self.config_enableadblocker, self.config_adblockwhitelist, self.config_rediyoutube, self.config_httpsrewrite, self.config_dnt, self.config_safebrowse, self.final_adlist, self.debugmode, self.invidious_url) + self.webview_interceptor = BrowserInterceptor(self.config_allowusernamesinurl, self.config_enableadblocker, self.config_adblockwhitelist, self.config_rediyoutube, self.config_httpsrewrite, self.config_dnt, self.config_safebrowse, self.final_adlist, self.debugmode, self.invidious_url, self.locale_file) self.interceptor_ready = True @@ -915,8 +992,14 @@ def __init__(self, debugmode): self.tab_widget.currentChanged.connect(self.upmutebutton) + def expand_lang(self, lang): + if lang == 'DE': + return 'DE - Deutsch' + elif lang == 'EN': + return 'EN - English' + def replace_interceptor(self): - self.webview_interceptor = BrowserInterceptor(self.config_allowusernamesinurl, self.config_enableadblocker, self.config_adblockwhitelist, self.config_rediyoutube, self.config_httpsrewrite, self.config_dnt, self.config_safebrowse, self.final_adlist, self.debugmode, self.invidious_url) + self.webview_interceptor = BrowserInterceptor(self.config_allowusernamesinurl, self.config_enableadblocker, self.config_adblockwhitelist, self.config_rediyoutube, self.config_httpsrewrite, self.config_dnt, self.config_safebrowse, self.final_adlist, self.debugmode, self.invidious_url, self.locale_file) if self.debugmode: print("[CONFIG_RELOAD] Interceptor was replaced") for index in range(self.tab_widget.count()): @@ -932,23 +1015,24 @@ def replace_interceptor(self): def update_config(self): if self.debugmode: - print("[CONFIG] Lade Konfiguration") + print("[CONFIG] Load Configuration") if not os.path.exists(os.path.expanduser('~/.config/brapy')): if self.debugmode: - print("[CONFIG] Konfigurationsornder existiert nicht. Erstelle Konfigurationsornder") + print("[CONFIG] Configurationfolder does not exist. Make Configurationfolder") os.makedirs(os.path.expanduser('~/.config/brapy'), exist_ok=True) config.read(os.path.expanduser('~/.config/brapy/brapy.ini')) if not os.path.exists(os.path.expanduser('~/.config/brapy/brapy.ini')): if self.debugmode: - print("[CONFIG] Konfiguration existiert nicht. Erstelle Konfiguration") + print("[CONFIG] Configuration does not exist. Create Configuration") config.add_section('Security') config.set('Security', 'allow_usernames_in_url', 'False') config.set('Security', 'do_not_track_enabled', 'True') config.set('Security', 'enable_google_safe_browsing', 'True') config.add_section('Window') config.set('Window', 'confirm_close_with_ctrl+q', 'True') + config.set('Window', 'language', 'EN') config.add_section('Features') config.set('Features', 'enable_adblocker', 'True') config.set('Features', 'adblocker_whitelist', "['canyoublockit.com']") @@ -961,76 +1045,82 @@ def update_config(self): if not config.has_section('Security'): if self.debugmode: - print("[CONFIG] Sektion Security existiert nicht. Erstelle Security") + print("[CONFIG] Section Security does not exist. Create Security") config.add_section('Security') if not config.has_section('Window'): if self.debugmode: - print("[CONFIG] Sektion Window existiert nicht. Erstelle Window") + print("[CONFIG] Section Window does not exist. Create Window") config.add_section('Window') if not config.has_section('Features'): if self.debugmode: - print("[CONFIG] Sektion Features existiert nicht. Erstelle Features") + print("[CONFIG] Section Features does not exist. Create Features") config.add_section('Features') if not config.has_option('Security', 'allow_usernames_in_url'): if self.debugmode: - print("[CONFIG] Option allow_username_in_url existiert nicht. Erstelle allow_username_in_url") + print("[CONFIG] Option allow_username_in_url does not exist. Create allow_username_in_url") config.set('Security', 'allow_usernames_in_url', 'False') self.config_allowusernamesinurl = False if not config.has_option('Security', 'do_not_track_enabled'): if self.debugmode: - print("[CONFIG] Option do_not_track_enabled existiert nicht. Erstelle do_not_track_enabled") + print("[CONFIG] Option do_not_track_enabled does not exist. Create do_not_track_enabled") config.set('Security', 'do_not_track_enabled', 'True') self.config_dnt = True if not config.has_option('Security', 'enable_google_safe_browsing'): if self.debugmode: - print("[CONFIG] Option enable_google_safe_browsing existiert nicht. Erstelle enable_google_safe_browsing") + print("[CONFIG] Option enable_google_safe_browsing does not exist. Create enable_google_safe_browsing") config.set('Security', 'enable_google_safe_browsing', 'True') self.config_safebrowse = True if not config.has_option('Window', 'confirm_close_with_ctrl+q'): if self.debugmode: - print("[CONFIG] Option confirm_close_with_ctrl+q existiert nicht. Erstelle confirm_close_with_ctrl+q") + print("[CONFIG] Option confirm_close_with_ctrl+q does not exist. Create confirm_close_with_ctrl+q") config.set('Window', 'confirm_close_with_ctrl+q', 'True') self.config_confirmclosewithctrlq = True + if not config.has_option('Window', 'language'): + if self.debugmode: + print("[CONFIG] Option confirm_close_with_ctrl+q does not exist. Create confirm_close_with_ctrl+q") + config.set('Window', 'language', 'EN') + self.language = 'EN' + if not config.has_option('Features', 'enable_adblocker'): if self.debugmode: - print("[CONFIG] Option enable_adblocker existiert nicht. Erstelle enable_adblocker") + print("[CONFIG] Option enable_adblocker does not exist. Create enable_adblocker") config.set('Features', 'enable_adblocker', 'True') self.config_enableadblocker = True if not config.has_option('Features', 'adblocker_whitelist'): if self.debugmode: - print("[CONFIG] Option adblocker_whitelist existiert nicht. Erstelle adblocker_whitelist") + print("[CONFIG] Option adblocker_whitelist does not exist. Create adblocker_whitelist") config.set('Features', 'adblocker_whitelist', "['canyoublockit.com']") self.config_adblockwhitelist = ['canyoublockit.com'] if not config.has_option('Features', 'adblocker_blacklist'): if self.debugmode: - print("[CONFIG] Option adblocker_blacklist existiert nicht. Erstelle adblocker_blacklist") + print("[CONFIG] Option adblocker_blacklist does not exist. Create adblocker_blacklist") config.set('Features', 'adblocker_blacklist', "[]") self.config_adblockblacklist = [] if not config.has_option('Features', 'redirect_youtube_to_invidious'): if self.debugmode: - print("[CONFIG] Option redirect_youtube_to_invidious existiert nicht. Erstelle redirect_youtube_to_invidious") + print("[CONFIG] Option redirect_youtube_to_invidious does not exist. Create redirect_youtube_to_invidious") config.set('Features', 'redirect_youtube_to_invidious', "False") self.config_rediyoutube = False if not config.has_option('Features', 'override_country'): if self.debugmode: - print("[CONFIG] Option override_country existiert nicht. Erstelle override_country") + print("[CONFIG] Option override_country does not exist. Create override_country") config.set('Features', 'override_country', "") self.config_countryoverride = None if not config.has_option('Features', 'rewrite_to_https'): if self.debugmode: - print("[CONFIG] Option rewrite_to_https existiert nicht. Erstelle rewrite_to_https") + print("[CONFIG] Option rewrite_to_https does not exist. Create rewrite_to_https") config.set('Features', 'rewrite_to_https', "False") self.config_httpsrewrite = False @@ -1040,7 +1130,7 @@ def update_config(self): self.config_allowusernamesinurl = False else: if self.debugmode: - ColorPrint("[CONFIG] Option allow_usernames_in_url ist fehlerhaft. Setze zurück", "red") + ColorPrint("[CONFIG] Option allow_usernames_in_url contains an error. Resetting...", "red") config.set('Security', 'allow_usernames_in_url', 'False') self.config_allowusernamesinurl = False @@ -1050,7 +1140,7 @@ def update_config(self): self.config_dnt = False else: if self.debugmode: - ColorPrint("[CONFIG] Option do_not_track_enabled ist fehlerhaft. Setze zurück", "red") + ColorPrint("[CONFIG] Option do_not_track_enabled contains an error. Resetting...", "red") config.set('Security', 'do_not_track_enabled', 'True') self.config_dnt = True @@ -1060,7 +1150,7 @@ def update_config(self): self.config_safebrowse = False else: if self.debugmode: - ColorPrint("[CONFIG] Option enable_google_safe_browsing ist fehlerhaft. Setze zurück", "red") + ColorPrint("[CONFIG] Option enable_google_safe_browsing contains an error. Resetting...", "red") config.set('Security', 'enable_google_safe_browsing', 'True') self.config_safebrowse = True @@ -1070,17 +1160,19 @@ def update_config(self): self.config_confirmclosewithctrlq = False else: if self.debugmode: - ColorPrint("[CONFIG] Option confirm_close_with_ctrl+q ist fehlerhaft. Setze zurück", "red") + ColorPrint("[CONFIG] Option confirm_close_with_ctrl+q contains an error. Resetting...", "red") config.set('Window', 'confirm_close_with_ctrl+q', 'True') self.config_confirmclosewithctrlq = True + self.language = config.get('Window', 'language') + if config.get('Features', 'enable_adblocker') == "True": self.config_enableadblocker = True elif config.get('Features', 'enable_adblocker') == "False": self.config_enableadblocker = False else: if self.debugmode: - ColorPrint("[CONFIG] Option enable_adblocker ist fehlerhaft. Setze zurück", "red") + ColorPrint("[CONFIG] Option enable_adblocker contains an error. Resetting...", "red") config.set('Features', 'enable_adblocker', 'True') self.config_enableadblocker = True @@ -1090,7 +1182,7 @@ def update_config(self): self.config_rediyoutube = False else: if self.debugmode: - ColorPrint("[CONFIG] Option redirect_youtube_to_invidious ist fehlerhaft. Setze zurück", "red") + ColorPrint("[CONFIG] Option redirect_youtube_to_invidious contains an error. Resetting...", "red") config.set('Features', 'redirect_youtube_to_invidious', 'False') self.config_rediyoutube = False @@ -1100,7 +1192,7 @@ def update_config(self): self.config_adblockwhitelist = ast.literal_eval(config.get('Features', 'adblocker_whitelist')) except SyntaxError: if self.debugmode: - ColorPrint("[CONFIG] Option adblocker_whitelist ist fehlerhaft. Setze zurück.", "red") + ColorPrint("[CONFIG] Option adblocker_whitelist contains an error. Resetting....", "red") config.set('Features', 'adblocker_whitelist', "['canyoublockit.com']") self.config_adblockwhitelist = ['canyoublockit.com'] @@ -1108,14 +1200,22 @@ def update_config(self): self.config_adblockblacklist = ast.literal_eval(config.get('Features', 'adblocker_blacklist')) except SyntaxError: if self.debugmode: - ColorPrint("[CONFIG] Option adblocker_blacklist ist fehlerhaft. Setze zurück.", "red") + ColorPrint("[CONFIG] Option adblocker_blacklist contains an error. Resetting....", "red") config.set('Features', 'adblocker_blacklist', "[]") self.config_adblockblacklist = [] + if os.path.exists(f"/usr/local/share/brapy/lang/{self.language.lower()}.json"): + self.locale_file = json.load(open(f"/usr/local/share/brapy/lang/{self.language.lower()}.json", "r")) + global APP_LOCALE + APP_LOCALE = self.locale_file + else: + ColorPrint("[CONFIG] Fatal: Invalid Language in Config specified", "bg-red") + sys.exit() + if self.config_rediyoutube: if self.config_countryoverride == "" or self.config_countryoverride == None: if self.debugmode: - print("[FEATURES] Land wird ermittelt... (wird verwendet um besten Invidious-Server zu finden)") + print("[FEATURES] Detecting Country... (is used to find best Invidious servers)") tries = 1 while True: try: @@ -1131,7 +1231,7 @@ def update_config(self): if self.debugmode: ColorPrint("[FEATURES] Failed to detect Country. Using US Fallback...", "red") self.country = "US" - dialog = OkDialog("Okay", "Hinweis zu Konfiguration", "Deine Region konnte nicht ermittelt werden.", "Es wird nun der US Server als Fallback verwendet.") + dialog = OkDialog(self.locale_file['general']['okay'], self.locale_file['settings']['country_notice'], self.locale_file['settings']['country_not1'], self.locale_file['settings']['country_fallback']) dialog.exec_() break del tries @@ -1170,7 +1270,7 @@ def update_config(self): self.invidious_url = "https://invidious.0011.lt/" case _: self.config_rediyoutube = False - dialog = OkDialog("Okay", "Hinweis zu Konfiguration", "Ein Invidious Server für deine Region ist leider nicht verfügbar.", "Die Weiterleitung von Youtube auf einen Invidious Server wird temporär deaktiviert.", "Deine Aktuelle Region wurde als " + self.country + " erkannt.", "Sie können einen bestimmten Server in den Einstellungen einstellen.", "Die verfügbaren Server sind:", "DE, FR, CL, US, RO, LU, FI, SE, SG, ES, IN, NL, JP, LT") + dialog = OkDialog(self.locale_file['general']['okay'], self.locale_file['settings']['country_notice'], self.locale_file['settings']['invidious_notavailable'], self.locale_file['settings']['invidious_turnedoff'], self.locale_file['settings']['country_detected1'] + self.country + self.locale_file['settings']['country_detected2'], self.locale_file['settings']['invidious_settings'], self.locale_file['settings']['country_available'], self.locale_file['settings']['country_list']) dialog.exec_() try: if not self.invidious_url: @@ -1186,22 +1286,22 @@ def update_config(self): self.config_httpsrewrite = False else: if self.debugmode: - ColorPrint("[CONFIG] Option rewrite_to_https ist fehlerhaft. Setze zurück", "red") + ColorPrint("[CONFIG] Option rewrite_to_https contains an error. Resetting...", "red") config.set('Features', 'rewrite_to_https', 'False') self.config_httpsrewrite = False notgenagain = False if not os.path.exists(os.path.expanduser('~/.config/brapy/ad.list')): if self.debugmode: - print("[FEATURES] Adliste existiert nicht. Erstelle Adlist") + print("[FEATURES] Adliste does not exist. Create Adlist") process_thread = ProcessThread("/usr/local/share/brapy/genadlist.py", self.debugmode) - dialog = ProgressDialog(process_thread, "Adliste wird erstellt...", "Die Adliste für den Adblocker wird erstellt...") + dialog = ProgressDialog(process_thread, self.locale_file['settings']['creating_adlist'], self.locale_file['settings']['creating_adlist2']) process_thread.finished.connect(dialog.close_dialog) process_thread.start() dialog.exec_() notgenagain = True if self.debugmode: - ColorPrint("[FEATURES] Adliste existiert.", "green") + ColorPrint("[FEATURES] Adliste exists.", "green") self.final_adlist: list = [] with open(os.path.expanduser('~/.config/brapy/ad.list'), 'r') as file: adlist = file.read() @@ -1211,7 +1311,7 @@ def update_config(self): self.final_adlist.append(i) if not notgenagain: if self.debugmode: - print("[FEATURES] Adliste wird aktualisiert") + print("[FEATURES] Updating Adlist") generating_adlist = subprocess.Popen("/usr/local/share/brapy/genadlist.py", shell=True) else: generating_adlist = subprocess.Popen("/usr/local/share/brapy/genadlist.py", stdout=subprocess.PIPE, shell=True) @@ -1223,7 +1323,7 @@ def update_config(self): self.replace_interceptor() else: if self.debugmode: - print("[CONFIG] Skipping on refreshing the Interceptor") + print("[CONFIG] Skipped refreshing the Interceptor") def is_version_greater(self, version1, version2): parts1 = version1.split(".") @@ -1246,13 +1346,13 @@ def is_version_greater(self, version1, version2): def upgrade(self): if APP_MANUAL_INSTALLED: - dialog = ConfirmUpgrade(True, self.lastversion) + dialog = ConfirmUpgrade(self.locale_file, True, self.lastversion) if dialog.exec_() == QDialog.Accepted: self.save_tabs() print("Save complete!") with open(os.path.expanduser('~/.config/brapy/tabs.json'), 'r') as file: data = json.load(file) - data.append({"url": "file:///usr/local/share/brapy/upgrade.html", "title": "Upgrade abgeschlossen"}) + data.append({"url": "file:///usr/local/share/brapy/upgrade.html", "title": self.locale_file['upgrade']['done']}) with open(os.path.expanduser('~/.config/brapy/tabs.json'), 'w') as file: json.dump(data, file) copyfile("/usr/local/share/brapy/upgrade", "/tmp/brapy_upgrade.sh") @@ -1262,7 +1362,7 @@ def upgrade(self): new_brapy = subprocess.Popen("brapy", shell=True) sys.exit() else: - dialog = ConfirmUpgrade(False) + dialog = ConfirmUpgrade(self.locale_file, False) dialog.exec_() def load_tabs(self): @@ -1270,47 +1370,47 @@ def load_tabs(self): if os.path.exists(tabs_file_path): if self.debugmode: print("[BROWSER] Save exists! Load Save!") - with open(tabs_file_path, "r") as tabs_file: - tabs_data = json.load(tabs_file) - if not (tabs_data == [] or tabs_data == ""): - for tab_data in tabs_data: - try: - if tab_data["special"]: - url = tab_data["url"] - self.add_custom_tab(url) - else: - url = tab_data["url"] - if url == "file:///usr/local/share/brapy/home.html" or url.startswith("file:///usr/local/share/brapy/homeupdate.html"): - url = self.homeurl - elif url == "file:///usr/local/share/brapy/upgrade.html": - if APP_VERSION_ISBETA: - url = f"{url}?ver={APP_VERSION}-beta{APP_VERSION_BETA}" - else: - url = url + "?ver=" + APP_VERSION - title = tab_data["title"] - self.add_new_tab(url, title) - except KeyError as e: - if str(e) == "'special'": - url = tab_data["url"] - if url == "file:///usr/local/share/brapy/home.html" or url.startswith("file:///usr/local/share/brapy/homeupdate.html"): - url = self.homeurl - elif url == "file:///usr/local/share/brapy/upgrade.html": - if APP_VERSION_ISBETA: - url = f"{url}?ver={APP_VERSION}-beta{APP_VERSION_BETA}" - else: - url = url + "?ver=" + APP_VERSION - title = tab_data["title"] - self.add_new_tab(url, title) - else: - ColorPrint("[BROWSER] Failed to load Tabs: " + "KeyError: " + str(e), "red") - dialog = OkDialog("Okay", "Fehler beim Laden", "Die Vorherige Sitzung konnte nicht wiederhergestellt werden:", "KeyError: " + str(e)) - dialog.exec_() - else: - if self.debugmode: - ColorPrint("[BROWSER] Save exists, but it's empty. Open Homepage...", "yellow") - self.add_new_tab(self.homeurl, "Neuer Tab") + with open(tabs_file_path, "r") as tabs_file: + tabs_data = json.load(tabs_file) + if not (tabs_data == [] or tabs_data == ""): + for tab_data in tabs_data: + try: + if tab_data["special"]: + url = tab_data["url"] + self.add_custom_tab(url) + else: + url = tab_data["url"] + if url == "file:///usr/local/share/brapy/home.html" or url.startswith("file:///usr/local/share/brapy/homeupdate.html"): + url = self.homeurl + elif url == "file:///usr/local/share/brapy/upgrade.html": + if APP_VERSION_ISBETA: + url = f"{url}?ver={APP_VERSION}-beta{APP_VERSION_BETA}" + else: + url = url + "?ver=" + APP_VERSION + title = tab_data["title"] + self.add_new_tab(url, title) + except KeyError as e: + if str(e) == "'special'": + url = tab_data["url"] + if url == "file:///usr/local/share/brapy/home.html" or url.startswith("file:///usr/local/share/brapy/homeupdate.html"): + url = self.homeurl + elif url == "file:///usr/local/share/brapy/upgrade.html": + if APP_VERSION_ISBETA: + url = f"{url}?ver={APP_VERSION}-beta{APP_VERSION_BETA}" + else: + url = url + "?ver=" + APP_VERSION + title = tab_data["title"] + self.add_new_tab(url, title) + else: + ColorPrint("[BROWSER] Failed to load Tabs: " + "KeyError: " + str(e), "red") + dialog = OkDialog(self.locale_file['general']['okay'], self.locale_file['tabs_loading']['error_while'], self.locale_file['tabs_loading']['couldnt_restore'], "KeyError: " + str(e)) + dialog.exec_() + else: + if self.debugmode: + ColorPrint("[BROWSER] Save exists, but it's empty. Open Homepage...", "yellow") + self.add_new_tab(self.homeurl, "Neuer Tab") else: - self.add_new_tab(self.homeurl, "Neuer Tab") + self.add_new_tab(self.homeurl, "Neuer Tab") def toggle_fullscreen(self): if self.isFullScreen(): @@ -1376,13 +1476,13 @@ def closeEvent(self, event): hostname = urlparse(download.url().toString()).hostname unfinished_downloads.append([download.path().split("/")[-1], download.path().rsplit('/', 1)[0], hostname]) if not unfinished_downloads == []: - dialog = UnfinishedDownloadDialog(unfinished_downloads) + dialog = UnfinishedDownloadDialog(self.locale_file, unfinished_downloads) if dialog.exec_() == QDialog.Rejected: if self.debugmode: print("[CLOSE_EVENT] Close Event ignored") return event.ignore() - if self.debugmode: - print("[CLOSE_EVENT] Disconnecting Update-Tab-Title...") + if self.debugmode: + print("[CLOSE_EVENT] Disconnecting Update-Tab-Title...") for index in range(self.tab_widget.count()): tab_widget = self.tab_widget.widget(index) if not tab_widget.new_tab_specialtab: @@ -1406,14 +1506,14 @@ def quit(self): def quitq(self): if self.config_confirmclosewithctrlq: - dialog = YesNoDialog("yesno", "Schließen bestätigen", "Möchten sie Brapy wirklich beenden?") + dialog = YesNoDialog("yesno", self.locale_file, self.locale_file['ctrlq_close']['confirm_close'], self.locale_file['ctrlq_close']['really_quit']) if dialog.exec_() == QDialog.Accepted: self.quit() else: self.quit() def show_downloads(self): - dialog = ShowDownloads(self.downloads) + dialog = ShowDownloads(self.downloads, self.locale_file) dialog.exec_() # def handle_updated_download_state(self, state, download_item): @@ -1465,6 +1565,13 @@ def load_url(): new_tab_webview.load(QUrl(qeurl)) elif url.startswith("view-source:"): new_tab_webview.load(QUrl(url)) + elif url.startswith("brapy:"): + if url == "brapy:settings": + self.add_custom_tab('brapy:settings') + update_address_bar(new_tab_webview.page().url()) + return + else: + new_tab_webview.load(QUrl(f'file:///usr/local/share/brapy/extraerror.html?eurl={url}&code=b02')) else: if url.startswith("www."): url = f"https://{url}" @@ -1505,7 +1612,7 @@ def search(): def update_tab_title(): title = new_tab_webview.page().title() if title.startswith("view-source:"): - title = f"Seitenquelltext von {title.split(':', 1)[1].split('?', 1)[0]}" + title = f"{self.locale_file['adress_bar']['view-source']}{title.split(':', 1)[1].split('?', 1)[0]}" index = self.tab_widget.currentIndex() if new_tab_webview.page().isAudioMuted(): self.tab_widget.setTabText(index, " " + title) @@ -1523,11 +1630,11 @@ def update_address_bar(url): url_text = url.toString() orig_url = url_text if url_text.startswith("file:///usr/local/share/brapy/error.html" or "file:///usr/local/share/brapy/extraerror.html"): - url_text = "Fehler beim Laden der Webseite" + url_text = self.locale_file['adress_bar']['error_url'] elif url_text.startswith("file:///usr/local/share/brapy/errorfile.html"): - url_text = "Fehler beim Laden der Datei" + url_text = self.locale_file['adress_bar']['error_file'] elif url_text.startswith("file:///usr/local/share/brapy/upgrade.html"): - url_text = "Upgrade abgeschlossen" + url_text = self.locale_file['upgrade']['done'] elif url_text == "file:///usr/local/share/brapy/home.html" or url_text.startswith("file:///usr/local/share/brapy/homeupdate.html"): url_text = "" elif url_text.startswith("file://"): @@ -1539,7 +1646,7 @@ def update_address_bar(url): if url_text.startswith("file:///usr/local/share/brapy/error.html" or "file:///usr/local/share/brapy/extraerror.html"): new_tab_webview.load(QUrl(url_text)) elif url_text.startswith("view-source:"): - url_text = f"Seitenquelltext von {url_text.split(':', 1)[1].split('?', 1)[0]}" + url_text = f"{self.locale_file['adress_bar']['view-source']}{url_text.split(':', 1)[1].split('?', 1)[0]}" self.new_tab_address_bar.setText(url_text) self.new_tab_address_bar.setCursorPosition(0) update_adblock_icon(orig_url) @@ -1559,6 +1666,10 @@ def update_adblock_icon(url=None): new_tab_adblock_button.setText("") def close_tab(index): + tab = self.tab_widget.widget(index) + web_view = tab.findChild(QWebEngineView) + web_view.stop() + tab.deleteLater() self.tab_widget.removeTab(index) tabs_file_path = os.path.expanduser("~/.config/brapy/tabs.json") if self.tab_widget.count() == 0: @@ -1579,9 +1690,9 @@ def download_requested(download): url = download.url().host() path = download.path() file_name = QUrl(path).fileName() - default_path = QDir.homePath() + "/Downloads/" + file_name + default_path = os.path.realpath(QDir.homePath() + "/Downloads/" + file_name) - dialog = DownloadDialog(url, file_name, self) + dialog = DownloadDialog(self.locale_file, url, file_name, self) dialog.path_lineedit.setText(default_path) if dialog.exec_() == QDialog.Accepted: file_path = dialog.path_lineedit.text() @@ -1592,7 +1703,7 @@ def download_requested(download): def show_adblockmenu(): current_url = new_tab_webview.page().url().toString() - dialog = AdblockMenu(self.config_enableadblocker, self.final_adlist, self.config_adblockwhitelist, current_url, self.config_adblockblacklist) + dialog = AdblockMenu(self.config_enableadblocker, self.final_adlist, self.config_adblockwhitelist, current_url, self.config_adblockblacklist, self.locale_file) if dialog.exec_() == QDialog.Accepted: self.add_custom_tab("brapy:settings") @@ -1654,8 +1765,8 @@ def FullscreenRequest(request): new_tab_back_button.clicked.connect(goback) new_tab_reload_button.clicked.connect(reload) new_tab_forward_button.clicked.connect(goforward) - self.new_tab_address_bar.setPlaceholderText("Hier URL eingeben") - new_tab_search_bar.setPlaceholderText("Suchen") + self.new_tab_address_bar.setPlaceholderText(self.locale_file['webview_tab']['adress_barp']) + new_tab_search_bar.setPlaceholderText(self.locale_file['webview_tab']['search_barp']) self.new_tab_address_bar.returnPressed.connect(load_url) new_tab_search_bar.returnPressed.connect(search) new_tab_adblock_button.clicked.connect(show_adblockmenu) @@ -1673,13 +1784,12 @@ def FullscreenRequest(request): brapypage = BrapyPage(self) # Webview zur neuen Registerkarte hinzufügen - new_tab_webview = BrapyEngine(self.homeurl) + new_tab_webview = BrapyEngine(self.locale_file, self.homeurl) new_tab_webview.page().profile().setUrlRequestInterceptor(self.webview_interceptor) new_tab_webview.page().profile().setHttpUserAgent(f"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.15.14 Brapy/{APP_VERSION} Chrome/116.0.0.0 Safari/537.36") new_tab_layout.addWidget(new_tab_webview) new_tab_webview.setPage(brapypage) - # Signal zum Aktualisieren der Adressleiste in der neuen Registerkarte verbinden profile = QWebEngineProfile.defaultProfile() profile.downloadRequested.connect(download_requested) new_tab_webview.urlChanged.connect(update_address_bar) @@ -1688,7 +1798,6 @@ def FullscreenRequest(request): new_tab_webview.page().audioMutedChanged.connect(self.upmutebutton) new_tab_webview.page().fullScreenRequested.connect(FullscreenRequest) load_curl(url) - # Aktuelle Registerkarte auf die neue Registerkarte umschalten self.tab_widget.setCurrentWidget(new_tab_widget) # Schließen-Knopf zur Registerkarte hinzufügen @@ -1743,6 +1852,8 @@ def FullscreenRequest(request): def add_custom_tab(self, tab_url): def close_tab(index): + tab = self.tab_widget.widget(index) + tab.deleteLater() self.tab_widget.removeTab(index) tabs_file_path = os.path.expanduser("~/.config/brapy/tabs.json") if self.tab_widget.count() == 0: @@ -1763,6 +1874,7 @@ def load_config(): new_tab_adbl_enable.setChecked(self.config_enableadblocker) new_tab_feat_ytinvidious.setChecked(self.config_rediyoutube) + new_tab_allg_language.setCurrentText(self.expand_lang(self.language)) new_tab_feat_overridec.setText(self.config_countryoverride) new_tab_adbl_whitelist.clear() @@ -1794,7 +1906,8 @@ def update_apply_button(): new_tab_feat_ytinvidious.isChecked() == self.config_rediyoutube and parse_input(new_tab_adbl_whitelist.toPlainText()) == self.config_adblockwhitelist and parse_input(new_tab_adbl_blacklist.toPlainText()) == self.config_adblockblacklist and - new_tab_feat_overridec.text() == self.config_countryoverride): + new_tab_feat_overridec.text() == self.config_countryoverride and + new_tab_allg_language.currentText().split(' - ')[0] == self.language): new_tab_settings_apply_button.setDisabled(True) else: new_tab_settings_apply_button.setDisabled(False) @@ -1807,11 +1920,15 @@ def update_apply_button(): new_tab_featurelabel1.setDisabled(not new_tab_feat_ytinvidious.isChecked()) def apply_settings(): + if not new_tab_allg_language.currentText().split(' - ')[0] == self.language: + dialog = OkDialog('Okay', 'Restart required', 'A restart is required to apply the settings.') + dialog.exec_() config.read(os.path.expanduser('~/.config/brapy/brapy.ini')) config.set('Security', 'allow_usernames_in_url', str(new_tab_sec_userinurl.isChecked())) config.set('Security', 'do_not_track_enabled', str(new_tab_sec_dnt.isChecked())) config.set('Security', 'enable_google_safe_browsing', str(new_tab_sec_gsafeb.isChecked())) config.set('Window', 'confirm_close_with_ctrl+q', str(new_tab_allg_confirmq.isChecked())) + config.set('Window', 'language', new_tab_allg_language.currentText().split(' - ')[0]) config.set('Features', 'enable_adblocker', str(new_tab_adbl_enable.isChecked())) config.set('Features', 'adblocker_whitelist', str(parse_input(new_tab_adbl_whitelist.toPlainText()))) config.set('Features', 'adblocker_blacklist', str(parse_input(new_tab_adbl_blacklist.toPlainText()))) @@ -1824,7 +1941,7 @@ def apply_settings(): load_config() update_apply_button() - new_tab_widget.new_tab_specialtab_name = "Einstellungen" + new_tab_widget.new_tab_specialtab_name = self.locale_file['custom_tab']['brapy:settings']['name'] new_tab_widget.new_tab_specialtab_icon = None new_tab_layout = QVBoxLayout() new_tab_widget.setLayout(new_tab_layout) @@ -1839,39 +1956,44 @@ def apply_settings(): new_tab_settings_title = QLabel(APP_NAME + " v" + APP_VERSION) new_tab_settings_title.setFont(QFont(new_tab_settings_title.font().family(), 15)) - new_tab_settings_subtitle = QLabel("Einstellungen") + new_tab_settings_subtitle = QLabel(self.locale_file['custom_tab']['brapy:settings']['subtitle']) new_tab_settings_title.setFont(QFont(new_tab_settings_subtitle.font().family(), 13)) - new_tab_settings_apply_button = QPushButton("Änderungen anwenden") + new_tab_settings_apply_button = QPushButton(self.locale_file['custom_tab']['brapy:settings']['apply_button']) new_tab_settings_apply_button.setDisabled(True) - new_tab_title1 = QLabel("Allgemein") + new_tab_title1 = QLabel(self.locale_file['custom_tab']['brapy:settings']['title1']) new_tab_title1.setFont(QFont(new_tab_title1.font().family(), 18)) - new_tab_title2 = QLabel("Sicherheit") + new_tab_title2 = QLabel(self.locale_file['custom_tab']['brapy:settings']['title2']) new_tab_title2.setFont(QFont(new_tab_title2.font().family(), 18)) - new_tab_title3 = QLabel("Adblocker") + new_tab_title3 = QLabel(self.locale_file['custom_tab']['brapy:settings']['title3']) new_tab_title3.setFont(QFont(new_tab_title3.font().family(), 18)) - new_tab_title4 = QLabel("Features") + new_tab_title4 = QLabel(self.locale_file['custom_tab']['brapy:settings']['title4']) new_tab_title4.setFont(QFont(new_tab_title4.font().family(), 18)) - new_tab_adblocklabel1 = QLabel("Whiteliste: (Jede URL in eine neue Zeile)") - new_tab_adblocklabel2 = QLabel("Blackliste: (Jede URL in eine neue Zeile)") + new_tab_allglabel1 = QLabel('Language: (Requires Restart)') + + new_tab_adblocklabel1 = QLabel(self.locale_file['custom_tab']['brapy:settings']['adblockl1']) + new_tab_adblocklabel2 = QLabel(self.locale_file['custom_tab']['brapy:settings']['adblockl2']) + + new_tab_featurelabel1 = QLabel(self.locale_file['custom_tab']['brapy:settings']['featl1']) - new_tab_featurelabel1 = QLabel("Dieses Land verwenden:") + new_tab_allg_confirmq = QCheckBox(self.locale_file['custom_tab']['brapy:settings']['confirmq']) + new_tab_allg_language = QComboBox() + new_tab_allg_language.addItems(['EN - English', 'DE - Deutsch']) - new_tab_allg_confirmq = QCheckBox("Schließen mit STRL+Q bestätigen") - new_tab_sec_userinurl = QCheckBox("Benutzernamen in URLs erlauben") - new_tab_sec_dnt = QCheckBox("DoNotTrack aktiviert") - new_tab_sec_https = QCheckBox("HTTPS erzwingen") - new_tab_sec_gsafeb = QCheckBox("Google Safe Browsing verwenden") - new_tab_adbl_enable = QCheckBox("Adblocker aktiviert") - new_tab_feat_ytinvidious = QCheckBox("Youtube auf Invidious umleiten") + new_tab_sec_userinurl = QCheckBox(self.locale_file['custom_tab']['brapy:settings']['userinurl']) + new_tab_sec_dnt = QCheckBox(self.locale_file['custom_tab']['brapy:settings']['dnt']) + new_tab_sec_https = QCheckBox(self.locale_file['custom_tab']['brapy:settings']['https']) + new_tab_sec_gsafeb = QCheckBox(self.locale_file['custom_tab']['brapy:settings']['safebrowsing']) + new_tab_adbl_enable = QCheckBox(self.locale_file['custom_tab']['brapy:settings']['enadblock']) + new_tab_feat_ytinvidious = QCheckBox(self.locale_file['custom_tab']['brapy:settings']['openyoutube']) new_tab_adbl_whitelist = QTextEdit() new_tab_adbl_blacklist = QTextEdit() new_tab_feat_overridec = QLineEdit() - new_tab_feat_overridec.setPlaceholderText("Land autom. ermitteln") + new_tab_feat_overridec.setPlaceholderText(self.locale_file['custom_tab']['brapy:settings']['featl1p']) new_tab_adbl_whitelist.setMaximumWidth(1000) new_tab_adbl_whitelist.setMinimumWidth(500) @@ -1885,6 +2007,8 @@ def apply_settings(): new_tab_settingsv = QVBoxLayout() new_tab_settingsv.addWidget(new_tab_title1) new_tab_settingsv.addWidget(new_tab_allg_confirmq) + new_tab_settingsv.addWidget(new_tab_allglabel1) + new_tab_settingsv.addWidget(new_tab_allg_language) new_tab_settingsv.addWidget(new_tab_title2) new_tab_settingsv.addWidget(new_tab_sec_userinurl) new_tab_settingsv.addWidget(new_tab_sec_dnt) @@ -1923,6 +2047,7 @@ def apply_settings(): load_config() new_tab_allg_confirmq.toggled.connect(update_apply_button) + new_tab_allg_language.currentTextChanged.connect(update_apply_button) new_tab_sec_userinurl.toggled.connect(update_apply_button) new_tab_sec_dnt.toggled.connect(update_apply_button) new_tab_sec_https.toggled.connect(update_apply_button) @@ -1961,11 +2086,11 @@ def show_console_help_option(): print("Aufruf: " + APP_NAME.lower() + " [OPTIONEN]") print("") print("Optionen:") - print(" -h, --help Hilfeoptionen anzeigen") - print(" -v, --version Version der Anwendung anzeigen") - print(" -u --upgrade Anwendung aktualisieren") - print(" -d --debug Debuginformationen in der Konsole ausgeben") - print(" --download-adlist Adliste vom Adblocker aktualisieren") + print(" -h, --help Show Help") + print(" -v, --version Show Application Version") + print(" -u --upgrade Update Application") + print(" -d --debug Show Debuginformations in Console") + print(" --download-adlist Update Adlist used by Adblocker") print("") def is_version_greater(version1, version2, isbeta=False, betav1=None, betav2=None): @@ -2020,14 +2145,14 @@ def read_commandline_args(argv): print(f"{APP_NAME.lower()} {APP_VERSION}") sys.exit() elif opt in ("-u", "--upgrade"): - print(APP_NAME + " wird aktualisiert...") + print("Updating " + APP_NAME + "...") print() response = None - print("Wollen sie auf eine Betaversion aktualisieren?") - print("1: Ja") - print("2: Nein") + print("Do you want to update to an Betaversion?") + print("1: Yes") + print("2: Np") while response not in {"1", "2"}: - response = input("Bitte geben sie die entsprechende Nummer ein und drücken dann Enter: ") + response = input("Please enter the corresponding number and then press Enter: ") if response == "1": versioning = download_versions("beta") elif response == "2": @@ -2049,24 +2174,24 @@ def read_commandline_args(argv): process = subprocess.Popen("pkexec /tmp/brapy_upgrade.sh main", shell=True) process.wait() else: - print(f"Das Upgrade kann nicht fortfahren, da {APP_NAME} durch eine Paketverwaltung installiert wurde.") - print(f"Bitte verwenden sie die Paketverwaltung um {APP_NAME} zu aktualisieren oder kompilieren sie das Paket selber.") + print(f"The Upgrade can't continue, because {APP_NAME} was installed trough an Packagemanager.") + print(f"Please use the Package Manager to update {APP_NAME} or compilie the package yourself.") else: - print(APP_NAME + " ist bereits auf dem neusten Stand!") + print(APP_NAME + " is up to date!") sys.exit() elif opt in ("-d", "--debug"): - ColorPrint("[Debug] " + APP_NAME + " wird im Debug Modus gestartet...", "bold-white") + ColorPrint("[Debug] " + APP_NAME + " is starting in debug mode...", "bold-white") browser = WebBrowser(True) - print("[Debug] Fenster erstellt") + print("[Debug] Fenster created") browser.show() - print("[Debug] Fenster angezeigt") + print("[Debug] Fenster showed") return "debugged" elif opt in "--download-adlist": - ColorPrint("Adlisten werden nun erstellt...", "yellow") + ColorPrint("Creating Adlist...", "yellow") process = subprocess.Popen("/usr/local/share/brapy/genadlist.py", shell=True) process.wait() - ColorPrint("Adlisten wurden erstellt!", "bold-green") + ColorPrint("Adlists were created!", "bold-green") sys.exit() def main(argv):