diff --git a/.gitignore b/.gitignore
index 5d8195163a..d075b96dc0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,4 +14,5 @@ Output/
vcredist.exe
wingetuiBin/
wingetui_bin/
-wingetuiBin.zip
\ No newline at end of file
+wingetuiBin.zip
+APIKEY.txt
\ No newline at end of file
diff --git a/media/socialicon.png b/media/socialicon.png
new file mode 100644
index 0000000000..1718e1b0f3
Binary files /dev/null and b/media/socialicon.png differ
diff --git a/wingetui/__init__.py b/wingetui/__init__.py
index 070ca8bb09..0dd93a2595 100644
--- a/wingetui/__init__.py
+++ b/wingetui/__init__.py
@@ -9,12 +9,11 @@
import wingetHelpers, scoopHelpers
from mainWindow import *
from tools import *
+ from tools import _
import globals
from blurwindow import GlobalBlur, ExtendFrameIntoClientArea
- debugging = True
-
if hasattr(Qt, 'AA_EnableHighDpiScaling'):
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
if hasattr(Qt, 'AA_UseHighDpiPixmaps'):
@@ -51,7 +50,7 @@ def __init__(self):
titlewidget.addStretch()
self.popup.layout().addLayout(titlewidget)
self.popup.layout().addStretch()
- self.loadingText = QLabel("Loading WingetUI...")
+ self.loadingText = QLabel(_("Loading WingetUI..."))
self.loadingText.setStyleSheet(f"font-family: \"Segoe UI Variable Text\"; color: {'white' if isDark() else 'black'};font-size: 12px;")
self.popup.layout().addWidget(self.loadingText)
ApplyMenuBlur(self.popup.winId().__int__(), self.popup)
@@ -104,7 +103,7 @@ def __init__(self):
self.kill.connect(lambda: (self.popup.hide(), sys.exit(0)))
self.callInMain.connect(lambda f: f())
Thread(target=self.loadStuffThread, daemon=True).start()
- self.loadingText.setText("Checking for other running instances...")
+ self.loadingText.setText(_("Checking for other running instances..."))
except Exception as e:
raise e
@@ -137,7 +136,7 @@ def loadStuffThread(self):
except Exception as e:
print(e)
finally:
- self.callInMain.emit(lambda: self.loadingText.setText(f"Loading UI components..."))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Loading UI components...")))
self.callInMain.emit(lambda: self.loadingText.repaint())
self.callInMain.emit(self.loadMainUI)
print(globals.componentStatus)
@@ -150,22 +149,22 @@ def checkForRunningInstances(self):
try:
timestamps = [float(file.replace(os.path.join(os.path.join(os.path.expanduser("~"), ".wingetui"), "WingetUI_"), "")) for file in glob.glob(os.path.join(os.path.join(os.path.expanduser("~"), ".wingetui"), "WingetUI_*"))] # get a list with the timestamps
validTimestamps = [timestamp for timestamp in timestamps if timestamp < self.nowTime]
- self.callInMain.emit(lambda: self.loadingText.setText(f"Evaluating found instace(s)..."))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Checking found instace(s)...")))
print("Found lock file(s), reactivating...")
for tst in validTimestamps:
setSettings("RaiseWindow_"+str(tst), True)
if validTimestamps != [] and timestamps != [self.nowTime]:
for i in range(16):
time.sleep(0.1)
- self.callInMain.emit(lambda: self.loadingText.setText(f"Sent handshake. Waiting for instance listener's answer... ({int(i/15*100)}%)"))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Sent handshake. Waiting for instance listener's answer... ({0}%)").format(int(i/15*100))))
for tst in validTimestamps:
if not getSettings("RaiseWindow_"+str(tst), cache = False):
print(f"Instance {tst} responded, quitting...")
- self.callInMain.emit(lambda: self.loadingText.setText(f"Instance {tst} responded, quitting..."))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Instance {0} responded, quitting...").format(tst)))
setSettings(self.lockFileName, False)
self.kill.emit()
sys.exit(0)
- self.callInMain.emit(lambda: self.loadingText.setText(f"Starting daemons..."))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Starting daemons...")))
print("Reactivation signal ignored: RaiseWindow_"+str(validTimestamps))
for tst in validTimestamps:
setSettings("RaiseWindow_"+str(tst), False)
@@ -176,41 +175,41 @@ def checkForRunningInstances(self):
def detectWinget(self):
try:
- self.callInMain.emit(lambda: self.loadingText.setText(f"Locating Winget..."))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Locating Winget...")))
o = subprocess.run(f"{wingetHelpers.winget} -v", shell=True, stdout=subprocess.PIPE)
print(o.stdout)
print(o.stderr)
globals.componentStatus["wingetFound"] = o.returncode == 0
globals.componentStatus["wingetVersion"] = o.stdout.decode('utf-8').replace("\n", "")
- self.callInMain.emit(lambda: self.loadingText.setText(f"Winget found: {globals.componentStatus['wingetFound']}"))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Winget found: {0}").format(globals.componentStatus['wingetFound'])))
except Exception as e:
print(e)
self.loadStatus += 1
print("updating winget")
try:
if not getSettings("DisableUpdateIndexes"):
- self.callInMain.emit(lambda: self.loadingText.setText(f"Updating Winget sources..."))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Updating Winget sources...")))
o = subprocess.run(f"{wingetHelpers.winget} source update --name winget", shell=True, stdout=subprocess.PIPE)
- self.callInMain.emit(lambda: self.loadingText.setText(f"Updated Winget sources"))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Updated Winget sources")))
except Exception as e:
print(e)
self.loadStatus += 1
def detectScoop(self):
try:
- self.callInMain.emit(lambda: self.loadingText.setText(f"Locating Scoop..."))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Locating Scoop...")))
o = subprocess.run(f"powershell -Command scoop -v", shell=True, stdout=subprocess.PIPE)
print(o.stdout)
print(o.stderr)
globals.componentStatus["scoopFound"] = o.returncode == 0
globals.componentStatus["scoopVersion"] = o.stdout.decode('utf-8').split("\n")[1]
- self.callInMain.emit(lambda: self.loadingText.setText(f"Scoop found: {globals.componentStatus['scoopFound']}"))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Scoop found: {0}").format(globals.componentStatus['scoopFound'])))
except Exception as e:
print(e)
self.loadStatus += 1
try:
if not getSettings("DisableUpdateIndexes"):
- self.callInMain.emit(lambda: self.loadingText.setText(f"Clearing Scoop cache..."))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Clearing Scoop cache...")))
p = subprocess.Popen(f"powershell -Command scoop cache rm *", shell=True, stdout=subprocess.PIPE)
if(getSettings("EnableScoopCleanup")):
p2 = subprocess.Popen(f"powershell -Command scoop cleanup --all", shell=True, stdout=subprocess.PIPE)
@@ -220,9 +219,9 @@ def detectScoop(self):
print(e)
try:
if not getSettings("DisableUpdateIndexes"):
- self.callInMain.emit(lambda: self.loadingText.setText(f"Updating Scoop sources..."))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Updating Scoop sources...")))
o = subprocess.run(f"powershell -Command scoop update", shell=True, stdout=subprocess.PIPE)
- self.callInMain.emit(lambda: self.loadingText.setText(f"Updated Scoop sources"))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Updated Scoop sources")))
except Exception as e:
print(e)
self.loadStatus += 1
@@ -230,11 +229,11 @@ def detectScoop(self):
def detectSudo(self):
global sudoLocation
try:
- self.callInMain.emit(lambda: self.loadingText.setText(f"Locating sudo..."))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Locating sudo...")))
o = subprocess.run(f"{sudoPath} -v", shell=True, stdout=subprocess.PIPE)
globals.componentStatus["sudoFound"] = o.returncode == 0
globals.componentStatus["sudoVersion"] = o.stdout.decode('utf-8').split("\n")[0]
- self.callInMain.emit(lambda: self.loadingText.setText(f"Sudo found: {globals.componentStatus['sudoFound']}"))
+ self.callInMain.emit(lambda: self.loadingText.setText(_("Sudo found: {0}").format(globals.componentStatus['sudoFound'])))
except Exception as e:
print(e)
self.loadStatus += 1
@@ -251,58 +250,58 @@ def loadMainUI(self):
menu = QMenu("WingetUI")
globals.trayMenu = menu
- self.infoAction = QAction(f"WingetUI version {versionName}",menu)
+ self.infoAction = QAction(_("WingetUI version {0}").format(versionName), menu)
self.infoAction.setIcon(QIcon(getMedia("info")))
self.infoAction.setEnabled(False)
menu.addAction(self.infoAction)
- self.showAction = QAction("Show WingetUI",menu)
+ self.showAction = QAction(_("Show WingetUI"), menu)
self.showAction.setIcon(QIcon(getMedia("menu_show")))
menu.addAction(self.showAction)
self.trayIcon.setContextMenu(menu)
menu.addSeparator()
- self.dAction = QAction("Available updates",menu)
+ self.dAction = QAction(_("Available updates"), menu)
self.dAction.setIcon(QIcon(getMedia("menu_updates")))
self.dAction.setEnabled(False)
menu.addAction(self.dAction)
- self.updatesMenu = menu.addMenu("0 updates found")
+ self.updatesMenu = menu.addMenu(_("0 updates found"))
self.updatesMenu.menuAction().setIcon(QIcon(getMedia("list")))
self.updatesMenu.setParent(menu)
globals.trayMenuUpdatesList = self.updatesMenu
menu.addMenu(self.updatesMenu)
- globals.updatesHeader = QAction("App Name \tInstalled Version \t → \t New version", menu)
+ globals.updatesHeader = QAction(f"{_('App Name')} \t{_('Installed Version')} \t → \t {_('New version')}", menu)
globals.updatesHeader.setEnabled(False)
globals.updatesHeader.setIcon(QIcon(getMedia("version")))
self.updatesMenu.addAction(globals.updatesHeader)
- self.uaAction = QAction("Update all", menu)
+ self.uaAction = QAction(_("Update all"), menu)
self.uaAction.setIcon(QIcon(getMedia("menu_installall")))
menu.addAction(self.uaAction)
menu.addSeparator()
- self.iAction = QAction("Installed packages",menu)
+ self.iAction = QAction(_("Installed packages"),menu)
self.iAction.setIcon(QIcon(getMedia("menu_uninstall")))
self.iAction.setEnabled(False)
menu.addAction(self.iAction)
- self.installedMenu = menu.addMenu("0 packages found")
+ self.installedMenu = menu.addMenu(_("0 packages found"))
self.installedMenu.menuAction().setIcon(QIcon(getMedia("list")))
self.installedMenu.setParent(menu)
globals.trayMenuInstalledList = self.installedMenu
menu.addMenu(self.installedMenu)
menu.addSeparator()
- globals.installedHeader = QAction("App Name\tInstalled Version", menu)
+ globals.installedHeader = QAction(f"{_('App Name')}\t{_('Installed Version')}", menu)
globals.installedHeader.setIcon(QIcon(getMedia("version")))
globals.installedHeader.setEnabled(False)
self.installedMenu.addAction(globals.installedHeader)
self.quitAction = QAction(menu)
self.quitAction.setIcon(QIcon(getMedia("menu_close")))
- self.quitAction.setText("Quit")
+ self.quitAction.setText(_("Quit"))
self.quitAction.triggered.connect(lambda: (self.quit(), sys.exit(0)))
menu.addAction(self.quitAction)
@@ -334,7 +333,7 @@ def applyMenuStyle():
self.showAction.triggered.connect(self.window.showWindow)
self.uaAction.triggered.connect(self.window.updates.upgradeAllAction.trigger)
showWindow = self.showAction.trigger
- self.loadingText.setText(f"Latest details...")
+ self.loadingText.setText(_("Latest details..."))
if not self.isDaemon:
self.window.show()
if(self.window.isAdmin()):
diff --git a/wingetui/lang/__pycache__/lang_tools.cpython-310.pyc b/wingetui/lang/__pycache__/lang_tools.cpython-310.pyc
new file mode 100644
index 0000000000..da73a4f5c4
Binary files /dev/null and b/wingetui/lang/__pycache__/lang_tools.cpython-310.pyc differ
diff --git a/wingetui/lang/__pycache__/translated_percentage.cpython-310.pyc b/wingetui/lang/__pycache__/translated_percentage.cpython-310.pyc
new file mode 100644
index 0000000000..d7a4cf6b2a
Binary files /dev/null and b/wingetui/lang/__pycache__/translated_percentage.cpython-310.pyc differ
diff --git a/wingetui/lang/download_translations.py b/wingetui/lang/download_translations.py
new file mode 100644
index 0000000000..1259416454
--- /dev/null
+++ b/wingetui/lang/download_translations.py
@@ -0,0 +1,171 @@
+import sys
+import json
+import os
+import time
+
+sys.path.append('../')
+from lang_tools import *
+
+isAutoCommit = False
+isSomeChanges = False
+
+if len(sys.argv)>1:
+ if (sys.argv[1] == "--autocommit"):
+ isAutoCommit = True
+ else:
+ print("nocommit")
+ print(sys.argv[1])
+
+try:
+ apikey = open("APIKEY.txt", "r").read()
+ print(" API key found in APIKEY.txt")
+except FileNotFoundError:
+ apikey = os.environ.get("TOLGEE_KEY", "")
+ if (apikey == ""):
+ apikey = input("Write api key and press enter: ")
+
+apiurl = f"https://app.tolgee.io/v2/projects/1205/export?format=JSON&splitByScope=false&splitByScopeDelimiter=~&splitByScopeDepth=0&filterState=UNTRANSLATED&filterState=TRANSLATED&filterState=REVIEWED&zip=true&ak={apikey}"
+
+import os
+try:
+ import requests
+except ImportError:
+ os.system("pip install requests")
+ import requests
+import glob, time, shutil, zipfile
+
+
+print()
+print("-------------------------------------------------------")
+print()
+print(" Downloading updated translations...")
+
+
+response = requests.get(apiurl)
+if (not response.ok):
+ statusCode = response.status_code
+ print(f" Error {statusCode}: {response.text}")
+ if (statusCode == 403):
+ print(f" APIKEY is probably wrong!")
+ exit(1)
+f = open("langs.zip", "wb")
+f.write(response.content)
+langArchiveName = f.name
+f.close()
+
+
+print(" Download complete!")
+print()
+print("-------------------------------------------------------")
+print()
+print(" Extracting language files...")
+
+
+
+downloadedLanguages = []
+zip_file = zipfile.ZipFile(langArchiveName)
+
+for file in glob.glob('lang_*.json'): # If the downloaded zip file is valid, delete old language files and extract the new ones
+ os.remove(file)
+
+for name in zip_file.namelist():
+ lang = os.path.splitext(name)[0]
+ if (lang in languageRemap):
+ lang = languageRemap[lang]
+ newFilename = f"lang_{lang}.json"
+ downloadedLanguages.append(lang)
+
+ try:
+ zip_file.extract(name, "./")
+ os.replace(name, newFilename)
+
+ print(f" Extracted {newFilename}")
+ except KeyError as e:
+ print(type(name))
+ f = input(f" The file {name} was not expected to be in here. Please write the name for the file. It should follow the following structure: lang_[CODE].json: ")
+ zip_file.extract(f, "./")
+ os.replace(f, newFilename)
+ print(f" Extracted {f}")
+zip_file.close()
+downloadedLanguages.sort()
+os.remove("langs.zip")
+
+
+print(" Process complete!")
+print()
+print("-------------------------------------------------------")
+print()
+print(" Generating translations file...")
+
+
+langPerc = {}
+for lang in downloadedLanguages:
+ f = open(f"lang_{lang}.json", "r", encoding='utf-8')
+ data = json.load(f)
+ f.close()
+ c = 0
+ a = 0
+ for key, value in data.items():
+ c += 1
+ if (value != None):
+ a += 1
+ perc = "{:.0%}".format(a / c)
+ if (perc == "100%" or lang == "en"):
+ continue
+ langPerc[lang] = perc
+
+if (isAutoCommit):
+ os.system("git add .")
+countOfChanges = len(os.popen("git status -s").readlines())
+isSomeChanges = True if countOfChanges > 0 else False
+
+outputString = f"""
+# Autogenerated file, do not modify it!!!
+# The following list includes ONLY non-full translated files.
+
+untranslatedPercentage = {json.dumps(langPerc, indent=2)}
+"""
+
+f = open(f"translated_percentage.py", "w")
+f.write(outputString.strip())
+f.close()
+
+
+print(" Process complete!")
+print()
+print("-------------------------------------------------------")
+print()
+print(" Updating README.md...")
+
+
+"""
+readmeFilename = "../../README.md"
+
+f = open(readmeFilename, "r+", encoding="utf-8")
+skip = False
+data = ""
+for line in f.readlines():
+ if (line.startswith("")):
+ data += line + getMarkdownSupportLangs() + "\nLast updated: "+str(time.ctime(time.time()))+"\n"
+ print(" Text modified")
+ skip = True
+ if (line.startswith("")):
+ skip = False
+ if (not skip): data += line
+if (isSomeChanges):
+ f.seek(0)
+ f.write(data)
+ f.truncate()
+f.close()
+"""
+
+print(" Process complete!")
+print()
+print("-------------------------------------------------------")
+print()
+
+if (isAutoCommit):
+ if (not isSomeChanges):
+ os.system("git reset --hard") # prevent clean
+else:
+ os.system("pause")
diff --git a/wingetui/lang/lang_ca.json b/wingetui/lang/lang_ca.json
new file mode 100644
index 0000000000..4fa2aae77d
--- /dev/null
+++ b/wingetui/lang/lang_ca.json
@@ -0,0 +1,204 @@
+{
+ "{0} {1} failed" : "La {1} de {0} ha fallat",
+ "{0} apps can be updated" : "Es poden actualitzar {0} aplicacions",
+ "{0} failed" : "{0} fallida",
+ "{0} installation" : "Instal·lació de {0}",
+ "0 packages found" : "Cap paquet trobat",
+ "{0} packages found" : "{0} paquets trobats",
+ "{0} succeeded" : "{0} satisfactòria",
+ "0 updates found" : "Cap actualització trobada",
+ "{0} updates found" : "{0} actualitzacions trobades",
+ "{0} was {1} successfully!" : "{0} s'ha {1} correctament!",
+ "1 hour" : "1 hora",
+ "2 hours" : "2 hores",
+ "30 minutes" : "30 minuts",
+ "4 hours" : "4 hores",
+ "8 hours" : "8 hores",
+ "About Qt6" : "Sobre Qt6",
+ "About WingetUI" : "Sobre el WingetUI",
+ "About WingetUI version {0}" : "Sobre el WingetUi versió {0}",
+ "Add a bucket to scoop" : "Adefeix un bucket a l'Scoop",
+ "Allow parallel installs (NOT RECOMMENDED)" : "Permet la instal·lació paral·lela (NO RECOMANAT)",
+ "Application theme:" : "Tema de l'aplicació:",
+ "App Name" : "Nom de l'app",
+ "Are you sure?" : "N'esteu segur/a?",
+ "Author" : "Autor/a",
+ "Author:" : "Autor/a:",
+ "Autostart wingetUI in the notifications area" : "Inicia el WingetUI la l'àrea de notificacions",
+ "Available updates" : "Actualitzacions disponibles",
+ "Available updates: {0}" : "Actualitzacions disponibles: {0}",
+ "Available updates: {0}, not finished yet..." : "Actualitzacions disponibles: {0}, encara no hem acabat...",
+ "Blacklist apps" : "Ignora aquestes aplicacions",
+ "By Icons8" : "Per Icons8",
+ "Cancel" : "Cancel·la",
+ "Can't {0} {1}" : "No hem pogut {0} el {1}",
+ "Check for updates every:" : "Cerca actualitzacions cada:",
+ "Check for updates periodically" : "Cerca actualitzacions periòdicament",
+ "Checking for other running instances..." : "Comprovant si hi ha altres instàncies en execució...",
+ "Checking for updates..." : "Cercant actualitzacions...",
+ "Checking found instace(s)..." : "Comprovant instàncies trobades...",
+ "Clearing scoop cache..." : "Netejant la memòria cau de l'Scoop...",
+ "Close" : "Tanca",
+ "Close WingetUI to the notification area" : "Tanqueu el WingetUI a la safata del sistema",
+ "Component information" : "Informació dels components",
+ "Copy log to clipboard" : "Copia el registre al porta-retalls",
+ "Dark" : "Fosc",
+ "Description:" : "Descripció:",
+ "Directly install when double-clicking an item on the Discover Software tab (instead of showing the package info)" : "Instal·la directament en comptes de mostrar més informació sobre un paquet a la secció de \nDescobrir programari",
+ "Disable Scoop" : "Desactiveu l'Scoop",
+ "Disable Winget" : "Desactiveu el Winget",
+ "DISCLAIMER: NEITHER MICROSOFT NOR THE CREATORS OF WINGET UI STORE ARE RESPONSIBLE FOR THE DOWNLOADED SOFTWARE. PROCEED WITH CAUTION" : "ADVERTÈNCIA: NI MICROSOFT NI ELS CREADORS DE WINGETUI ENS FEM RESPONSABLES DEL PROGRAMARI DESCARREGAT. PROCEDIU AMB PREACUCIÓ",
+ "Discover packages" : "Descobrir programari",
+ "Do not update package indexes on launch" : "No actualitzeu els índexos de paquets en iniciar el WingetUI",
+ "Do you really want to uninstall {0}?" : "Realment voleu desinstal·lar el {0}",
+ "Enable scoop cleanup on launch" : "Activa la comanda scoop cleanup en iniciar",
+ "Export all" : "Exporta'ls tot",
+ "Export log as a file" : "Exporta el registre com a fitxer",
+ "Export selected packages to a file" : "Exporta els paquets sel·leccionats en un fitxer",
+ "Follow system color scheme" : "Segueix l'esquema de colors del sistema",
+ "Found" : "Trobat",
+ "Found 0 Packages" : "No s'ha trobat cap paquet",
+ "Found packages: {0}" : "S'han trobat {0} paquets",
+ "Found packages: {0}, not finished yet..." : "S'han trobat {0} paquets, però encara no hem acabat...",
+ "General preferences" : "Preferències generals",
+ "General Settings" : "Configuració General",
+ "Hide details" : "Amaga els detalls",
+ "Homepage" : "Lloc web",
+ "Homepage URL:" : "Enllaç del lloc web",
+ "Hooray! No updates were found!" : "Visca! No s'han trobat actualitzacions!",
+ "Icons" : "Icones",
+ "Ignore updates for this package" : "Ignora'n les actualitzacions",
+ "Import packages from a file" : "Importa paquets des d'un fitxer",
+ "install" : "instal·la",
+ "Install" : "Instal·la",
+ "installation" : "instal·lació",
+ "Installation canceled by user!" : "Instal·lació cancel·lada per l'usuari",
+ "Installation source" : "Font d'instal·lació",
+ "installed" : "instal·lat",
+ "Installed packages" : "Programari instal·lat",
+ "Installed Version" : "Versió instal·lada",
+ "Installer SHA256" : "SHA256 de l'instal·lador",
+ "Installer SHA256 (Latest version):" : "SHA256 de l'instal·lador (darrera versió)",
+ "Installer type" : "Tipus d'instal·lador",
+ "Installer type (Latest version):" : "Tipus d'instal·lador (darrera versió)",
+ "Installer URL" : "Enllaç de l'instal·lador",
+ "Installer URL (Latest version):" : "Enllaç de l'instal·lador (darrera versió)",
+ "installing" : "instal·lant",
+ "Install scoop" : "Instal·leu l'Scoop",
+ "Install selected package" : "Instal·leu el paquet seleccionat",
+ "Instant search" : "Cerca instantània",
+ "Interactive installation" : "Instal·lació interactiva",
+ "Interactive uninstall" : "Desinstal·lació interactiva",
+ "Interactive update" : "Actualització interactiva",
+ "Latest" : "Darrera",
+ "Latest details..." : "Darrers detalls...",
+ "Latest version" : "Darrera versió",
+ "Latest version:" : "Darrera versió:",
+ "License" : "Llicència",
+ "License:" : "Llicència:",
+ "Licenses" : "Llicències",
+ "Light" : "Clar",
+ "Loading..." : "Carregant...",
+ "Loading UI components..." : "Carregant els components de la interfície...",
+ "Loading WingetUI..." : "Carregant el WingetUI...",
+ "Locating scoop..." : "Trobant l'Scoop...",
+ "Locating sudo..." : "Trobant el sudo...",
+ "Locating winget..." : "Trobant el Winget...",
+ "Manifest" : "Manifest",
+ "Manifest:" : "Manifest:",
+ "MIT License" : "Llicència MIT",
+ "New version" : "Nova versió",
+ "New Version" : "Nova versió",
+ "No packages found matching the input criteria" : "No s'han trobat paquets amb els criteris actuals",
+ "Notification tray options" : "Opcions de la safata del sistema",
+ "OK" : "D'acord",
+ "Origin" : "Origen",
+ "Package ID" : "ID del paquet",
+ "Package managers preferences" : "Preferències dels administradors de paquets",
+ "Package name" : "Nom del paquet",
+ "Please wait..." : "Si us plau espereu...",
+ "Program ID:" : "ID del programa:",
+ "Project homepage" : "Pàgina web del projecte",
+ "PSF License" : "Llicència PSF",
+ "Publisher" : "Publicador",
+ "Publisher:" : "Publicador:",
+ "Quit" : "Tanca",
+ "Reload log" : "Recarrega el registre",
+ "Remove a bucket from scoop" : "Elimina un bucket de l'Scoop",
+ "Remove permanent data" : "Esborra les dades permanents",
+ "Reset blacklist" : "Reseteja la llista negra",
+ "Restart WingetUI" : "Reinicia el WingetUI",
+ "Run as admin" : "Executa com a administrador",
+ "Run as administrator" : "Executa com a administrador",
+ "Run the installer with administrator privileges" : "Executa l'instal·lador amb drets d'administrador",
+ "Scoop found: {0}" : "Scoop trobat: {0}",
+ "Search for available updates" : "Cerqueu a les actualitzacions trobades",
+ "Search for something on Winget or Scoop" : "Cerqueu al Winget i a l'Scoop",
+ "Searching for installed packages..." : "Cerqueu al programari instal·lat...",
+ "Searching for packages..." : "Cercant paquets...",
+ "Search on your software" : "Cercqueu al vostre programari",
+ "Select all" : "Selecciona-ho tot",
+ "Select none" : "No en seleccionis cap",
+ "Sent handshake. Waiting for instance listener's answer... ({0}%)" : "S'ha enviat el handshake. Esperant resposta de la instància... ({0}%)",
+ "Show a notification when there are available updates" : "Mostra una notificació quan s'hagin trobat actualitzacions",
+ "Show details" : "Mostra els detalls",
+ "Show info" : "Més informació",
+ "Show info about the package on the Updates tab" : "Mostra informació sobre el paquet a la secció d'actualitzacions en ser clicat dos cops",
+ "Show missing translation strings" : "Mostra el text que falta per a ser traduït",
+ "Show package info" : "Mostra informació sobre el paquet",
+ "Show scoop apps as lowercase" : "Mostra les aplicacions de l'Scoop en minúscula",
+ "Show unknown versions" : "Mostra les versions desconegudes",
+ "Show WingetUI" : "Mostra el WingetUI",
+ "Skip hash check" : "No comprovis el hash",
+ "Skip the hash check" : "Ignora la comprovació del hash",
+ "Software updates" : "Actualitzacions",
+ "Source" : "Origen",
+ "Starting daemons..." : "Iniciant fils de rerefons...",
+ "Starting installation..." : "Iniciant la instal·lació...",
+ "Startup options" : "Opcions d'inici",
+ "Status" : "Estat",
+ "Sudo found: {0}" : "Sudo trobat: {0}",
+ "The main goal of this project is to give a GUI Store to the most common CLI Package Managers for windows, such as Winget and Scoop." : "L'objectiu principal d'aquesta aplicació és de proveir a l'usuari d'una forma ràpida d'administrar el programari disponible als administradors de paquets més comuns per al Windows, com per exemple el Winget o l'Scoop",
+ "This project has no connection with the winget-cli official project, and it's totally unofficial." : "Aquest projecte no té cap tipus de vinculació amb el projecte winget-cli, i és completament no oficial",
+ "uninstall" : "desinstal·la",
+ "Uninstall" : "Desinstal·la",
+ "uninstallation" : "desinstal·lació",
+ "{} Uninstallation" : "Desinstal·lació del {0}",
+ "Uninstall canceled by user!" : "Desinstal·lació cancel·lada per l'usuari!",
+ "uninstalled" : "desinstal·lat",
+ "uninstalling" : "desinstal·lant",
+ "Uninstall package" : "Desinstal·la el paquet",
+ "Uninstall selected package" : "Desinstal·la el paquet seleccionat",
+ "Uninstall selected packages" : "Desinstal·la els paquets seleccionats",
+ "Uninstall with administrator privileges" : "Desinstal·la amb drets d'administrador",
+ "Unknown" : "Desconegut",
+ "Update" : "Actualitza",
+ "Update all" : "Actualitza-ho tot",
+ "updated" : "actualitzat",
+ "Updated scoop sources" : "S'han actualitzat els orígens de l'Scoop",
+ "Updated winget sources" : "S'han actualitzat els orígens del Winget",
+ "Update found!" : "Actualització disponible!",
+ "update(noun)" : "actualització",
+ "Updates found!" : "S'han trobat actualitzacions!",
+ "update(verb)" : "actualitzar",
+ "Update WingetUI automatically" : "Actualitza el WingetUI automàticament",
+ "updating" : "actualitzant",
+ "Updating scoop sources..." : "Actualitzant els orígens de l'Scoop...",
+ "Updating winget sources..." : "Actualitzant els orígens del Winget...",
+ "Upgrade all" : "Actualitza-ho tot",
+ "Upgrade selected" : "Actualitza la selecció",
+ "Use installed GSudo instead of the bundled one (requires app restart)" : "Utilitza el GSudo present al sistema en comptes del que inclou l'aplicació (requereix un reinici)",
+ "Version" : "Versió",
+ "Version:" : "Versió:",
+ "Waiting for other installations to finish..." : "Esperant a que acabin les altres instal·lacions...",
+ "We could not {0} {1}. Please try again later. Click on \"Show details\" to get the logs from the installer." : "No hem pogut {0} el {1}. Proveu-ho més tard. Cliqueu \"Mostra els detalls\" per a veure el registre de l'instal·lador.",
+ "We could not {0} {1}. Please try again later. Click on \"Show details\" to get the logs from the uninstaller." : "No hem pogut {0} el {1}. Proveu-ho més tard. Cliqueu \"Mostra els detalls\" per a veure el registre del desinstal·lador.",
+ "Winget found: {0}" : "Winget trobat: {0}",
+ "WingetUI - {0} {1}" : "WingetUI - {1} del {0}",
+ "WingetUI - {0} updates are available" : "WingetUI - s'han trobat {0} actualitzacions",
+ "WingetUI - 1 update is available" : "WingetUI - Hi ha una actualització disponible",
+ "WingetUI display language:" : "Idioma del WingetUI:",
+ "WingetUI log" : "Registre del WingetUI",
+ "WingetUI Settings" : "Configuració del WingetUI",
+ "WingetUI version {0}" : "WingetUI versió {0}"
+}
\ No newline at end of file
diff --git a/wingetui/lang/lang_en-US-POSIX.json b/wingetui/lang/lang_en-US-POSIX.json
new file mode 100644
index 0000000000..54ecf15fff
--- /dev/null
+++ b/wingetui/lang/lang_en-US-POSIX.json
@@ -0,0 +1,204 @@
+{
+ "{0} {1} failed" : "lol",
+ "{0} apps can be updated" : "lol",
+ "{0} failed" : "lol",
+ "{0} installation" : "lol",
+ "0 packages found" : "lol",
+ "{0} packages found" : "lol",
+ "{0} succeeded" : "lol",
+ "0 updates found" : "lol",
+ "{0} updates found" : "lol",
+ "{0} was {1} successfully!" : "lol",
+ "1 hour" : "lol",
+ "2 hours" : "lol",
+ "30 minutes" : "lol",
+ "4 hours" : "lol",
+ "8 hours" : "lol",
+ "About Qt6" : "lol",
+ "About WingetUI" : "lol",
+ "About WingetUI version {0}" : "lol",
+ "Add a bucket to scoop" : "lol",
+ "Allow parallel installs (NOT RECOMMENDED)" : "lol",
+ "Application theme:" : "lol",
+ "App Name" : "lol",
+ "Are you sure?" : "lol",
+ "Author" : "lol",
+ "Author:" : "lol",
+ "Autostart wingetUI in the notifications area" : "lol",
+ "Available updates" : "lol",
+ "Available updates: {0}" : "lol",
+ "Available updates: {0}, not finished yet..." : "lol",
+ "Blacklist apps" : "lol",
+ "By Icons8" : "lol",
+ "Cancel" : "lol",
+ "Can't {0} {1}" : "lol",
+ "Check for updates every:" : "lol",
+ "Check for updates periodically" : "lol",
+ "Checking for other running instances..." : "lol",
+ "Checking for updates..." : "lol",
+ "Checking found instace(s)..." : "lol",
+ "Clearing scoop cache..." : "lol",
+ "Close" : "lol",
+ "Close WingetUI to the notification area" : "lol",
+ "Component information" : "lol",
+ "Copy log to clipboard" : "lol",
+ "Dark" : "lol",
+ "Description:" : "lol",
+ "Directly install when double-clicking an item on the Discover Software tab (instead of showing the package info)" : "lol",
+ "Disable Scoop" : "lol",
+ "Disable Winget" : "lol",
+ "DISCLAIMER: NEITHER MICROSOFT NOR THE CREATORS OF WINGET UI STORE ARE RESPONSIBLE FOR THE DOWNLOADED SOFTWARE. PROCEED WITH CAUTION" : "lol",
+ "Discover packages" : "Descobriu programari",
+ "Do not update package indexes on launch" : "lol",
+ "Do you really want to uninstall {0}?" : "lol",
+ "Enable scoop cleanup on launch" : "lol",
+ "Export all" : "lol",
+ "Export log as a file" : "lol",
+ "Export selected packages to a file" : "lol",
+ "Follow system color scheme" : "lol",
+ "Found" : "lol",
+ "Found 0 Packages" : "lol",
+ "Found packages: {0}" : "lol",
+ "Found packages: {0}, not finished yet..." : "lol",
+ "General preferences" : "lol",
+ "General Settings" : "lol",
+ "Hide details" : "lol",
+ "Homepage" : "lol",
+ "Homepage URL:" : "lol",
+ "Hooray! No updates were found!" : "lol",
+ "Icons" : "lol",
+ "Ignore updates for this package" : null,
+ "Import packages from a file" : "lol",
+ "install" : "lol",
+ "Install" : "lol",
+ "installation" : "lol",
+ "Installation canceled by user!" : "lol",
+ "Installation source" : "lol",
+ "installed" : "lol",
+ "Installed packages" : "lol",
+ "Installed Version" : "lol",
+ "Installer SHA256" : "lol",
+ "Installer SHA256 (Latest version):" : "lol",
+ "Installer type" : "lol",
+ "Installer type (Latest version):" : "lol",
+ "Installer URL" : "lol",
+ "Installer URL (Latest version):" : "lol",
+ "installing" : "lol",
+ "Install scoop" : "lol",
+ "Install selected package" : "lol",
+ "Instant search" : "lol",
+ "Interactive installation" : "lol",
+ "Interactive uninstall" : "lol",
+ "Interactive update" : null,
+ "Latest" : "lol",
+ "Latest details..." : "lol",
+ "Latest version" : "lol",
+ "Latest version:" : "lol",
+ "License" : "lol",
+ "License:" : "lol",
+ "Licenses" : "lol",
+ "Light" : "lol",
+ "Loading..." : "lol",
+ "Loading UI components..." : "lol",
+ "Loading WingetUI..." : "lol",
+ "Locating scoop..." : "lol",
+ "Locating sudo..." : "lol",
+ "Locating winget..." : "lol",
+ "Manifest" : "lol",
+ "Manifest:" : "lol",
+ "MIT License" : "lol",
+ "New version" : null,
+ "New Version" : "lol",
+ "No packages found matching the input criteria" : "lol",
+ "Notification tray options" : "lol",
+ "OK" : "lol",
+ "Origin" : "lol",
+ "Package ID" : "lol",
+ "Package managers preferences" : "lol",
+ "Package name" : "lol",
+ "Please wait..." : "lol",
+ "Program ID:" : "lol",
+ "Project homepage" : "lol",
+ "PSF License" : "lol",
+ "Publisher" : "lol",
+ "Publisher:" : "lol",
+ "Quit" : "lol",
+ "Reload log" : "lol",
+ "Remove a bucket from scoop" : "lol",
+ "Remove permanent data" : null,
+ "Reset blacklist" : "lol",
+ "Restart WingetUI" : null,
+ "Run as admin" : "lol",
+ "Run as administrator" : null,
+ "Run the installer with administrator privileges" : "lol",
+ "Scoop found: {0}" : "lol",
+ "Search for available updates" : "lol",
+ "Search for something on Winget or Scoop" : "lol",
+ "Searching for installed packages..." : "lol",
+ "Searching for packages..." : "lol",
+ "Search on your software" : "lol",
+ "Select all" : "lol",
+ "Select none" : "lol",
+ "Sent handshake. Waiting for instance listener's answer... ({0}%)" : "lol",
+ "Show a notification when there are available updates" : "lol",
+ "Show details" : "lol",
+ "Show info" : null,
+ "Show info about the package on the Updates tab" : "lol",
+ "Show missing translation strings" : "lol",
+ "Show package info" : "lol",
+ "Show scoop apps as lowercase" : "lol",
+ "Show unknown versions" : "lol",
+ "Show WingetUI" : "lol",
+ "Skip hash check" : "lol",
+ "Skip the hash check" : "lol",
+ "Software updates" : "lol",
+ "Source" : "lol",
+ "Starting daemons..." : "lol",
+ "Starting installation..." : "lol",
+ "Startup options" : "lol",
+ "Status" : "lol",
+ "Sudo found: {0}" : "lol",
+ "The main goal of this project is to give a GUI Store to the most common CLI Package Managers for windows, such as Winget and Scoop." : "lol",
+ "This project has no connection with the winget-cli official project, and it's totally unofficial." : "lol",
+ "uninstall" : "lol",
+ "Uninstall" : null,
+ "uninstallation" : "lol",
+ "{} Uninstallation" : "lol",
+ "Uninstall canceled by user!" : "lol",
+ "uninstalled" : "lol",
+ "uninstalling" : "lol",
+ "Uninstall package" : null,
+ "Uninstall selected package" : "lol",
+ "Uninstall selected packages" : "lol",
+ "Uninstall with administrator privileges" : "lol",
+ "Unknown" : "lol",
+ "Update" : null,
+ "Update all" : "lol",
+ "updated" : null,
+ "Updated scoop sources" : "lol",
+ "Updated winget sources" : "lol",
+ "Update found!" : null,
+ "update(noun)" : null,
+ "Updates found!" : "lol",
+ "update(verb)" : null,
+ "Update WingetUI automatically" : "lol",
+ "updating" : null,
+ "Updating scoop sources..." : "lol",
+ "Updating winget sources..." : "lol",
+ "Upgrade all" : "lol",
+ "Upgrade selected" : "lol",
+ "Use installed GSudo instead of the bundled one (requires app restart)" : "lol",
+ "Version" : "lol",
+ "Version:" : "lol",
+ "Waiting for other installations to finish..." : "lol",
+ "We could not {0} {1}. Please try again later. Click on \"Show details\" to get the logs from the installer." : "lol",
+ "We could not {0} {1}. Please try again later. Click on \"Show details\" to get the logs from the uninstaller." : "lol",
+ "Winget found: {0}" : "lol",
+ "WingetUI - {0} {1}" : "lol",
+ "WingetUI - {0} updates are available" : "lol",
+ "WingetUI - 1 update is available" : null,
+ "WingetUI display language:" : null,
+ "WingetUI log" : "lol",
+ "WingetUI Settings" : "lol",
+ "WingetUI version {0}" : "lol"
+}
\ No newline at end of file
diff --git a/wingetui/lang/lang_en.json b/wingetui/lang/lang_en.json
new file mode 100644
index 0000000000..9e3fe40fa5
--- /dev/null
+++ b/wingetui/lang/lang_en.json
@@ -0,0 +1,204 @@
+{
+ "{0} {1} failed" : null,
+ "{0} apps can be updated" : null,
+ "{0} failed" : null,
+ "{0} installation" : null,
+ "0 packages found" : null,
+ "{0} packages found" : null,
+ "{0} succeeded" : null,
+ "0 updates found" : null,
+ "{0} updates found" : null,
+ "{0} was {1} successfully!" : null,
+ "1 hour" : null,
+ "2 hours" : null,
+ "30 minutes" : null,
+ "4 hours" : null,
+ "8 hours" : null,
+ "About Qt6" : null,
+ "About WingetUI" : null,
+ "About WingetUI version {0}" : null,
+ "Add a bucket to scoop" : null,
+ "Allow parallel installs (NOT RECOMMENDED)" : null,
+ "Application theme:" : null,
+ "App Name" : null,
+ "Are you sure?" : null,
+ "Author" : null,
+ "Author:" : null,
+ "Autostart wingetUI in the notifications area" : null,
+ "Available updates" : null,
+ "Available updates: {0}" : null,
+ "Available updates: {0}, not finished yet..." : null,
+ "Blacklist apps" : null,
+ "By Icons8" : null,
+ "Cancel" : null,
+ "Can't {0} {1}" : null,
+ "Check for updates every:" : null,
+ "Check for updates periodically" : null,
+ "Checking for other running instances..." : null,
+ "Checking for updates..." : null,
+ "Checking found instace(s)..." : null,
+ "Clearing scoop cache..." : null,
+ "Close" : null,
+ "Close WingetUI to the notification area" : null,
+ "Component information" : null,
+ "Copy log to clipboard" : null,
+ "Dark" : null,
+ "Description:" : null,
+ "Directly install when double-clicking an item on the Discover Software tab (instead of showing the package info)" : null,
+ "Disable Scoop" : null,
+ "Disable Winget" : null,
+ "DISCLAIMER: NEITHER MICROSOFT NOR THE CREATORS OF WINGET UI STORE ARE RESPONSIBLE FOR THE DOWNLOADED SOFTWARE. PROCEED WITH CAUTION" : null,
+ "Discover packages" : null,
+ "Do not update package indexes on launch" : null,
+ "Do you really want to uninstall {0}?" : null,
+ "Enable scoop cleanup on launch" : null,
+ "Export all" : null,
+ "Export log as a file" : null,
+ "Export selected packages to a file" : null,
+ "Follow system color scheme" : null,
+ "Found" : null,
+ "Found 0 Packages" : null,
+ "Found packages: {0}" : null,
+ "Found packages: {0}, not finished yet..." : null,
+ "General preferences" : null,
+ "General Settings" : null,
+ "Hide details" : null,
+ "Homepage" : null,
+ "Homepage URL:" : null,
+ "Hooray! No updates were found!" : null,
+ "Icons" : null,
+ "Ignore updates for this package" : null,
+ "Import packages from a file" : null,
+ "install" : null,
+ "Install" : null,
+ "installation" : null,
+ "Installation canceled by user!" : null,
+ "Installation source" : null,
+ "installed" : null,
+ "Installed packages" : null,
+ "Installed Version" : null,
+ "Installer SHA256" : null,
+ "Installer SHA256 (Latest version):" : null,
+ "Installer type" : null,
+ "Installer type (Latest version):" : null,
+ "Installer URL" : null,
+ "Installer URL (Latest version):" : null,
+ "installing" : null,
+ "Install scoop" : null,
+ "Install selected package" : null,
+ "Instant search" : null,
+ "Interactive installation" : null,
+ "Interactive uninstall" : null,
+ "Interactive update" : null,
+ "Latest" : null,
+ "Latest details..." : null,
+ "Latest version" : null,
+ "Latest version:" : null,
+ "License" : null,
+ "License:" : null,
+ "Licenses" : null,
+ "Light" : null,
+ "Loading..." : null,
+ "Loading UI components..." : null,
+ "Loading WingetUI..." : null,
+ "Locating scoop..." : null,
+ "Locating sudo..." : null,
+ "Locating winget..." : null,
+ "Manifest" : null,
+ "Manifest:" : null,
+ "MIT License" : null,
+ "New version" : null,
+ "New Version" : null,
+ "No packages found matching the input criteria" : null,
+ "Notification tray options" : null,
+ "OK" : null,
+ "Origin" : null,
+ "Package ID" : null,
+ "Package managers preferences" : null,
+ "Package name" : null,
+ "Please wait..." : null,
+ "Program ID:" : null,
+ "Project homepage" : null,
+ "PSF License" : null,
+ "Publisher" : null,
+ "Publisher:" : null,
+ "Quit" : null,
+ "Reload log" : null,
+ "Remove a bucket from scoop" : null,
+ "Remove permanent data" : null,
+ "Reset blacklist" : null,
+ "Restart WingetUI" : null,
+ "Run as admin" : null,
+ "Run as administrator" : null,
+ "Run the installer with administrator privileges" : null,
+ "Scoop found: {0}" : null,
+ "Search for available updates" : null,
+ "Search for something on Winget or Scoop" : null,
+ "Searching for installed packages..." : null,
+ "Searching for packages..." : null,
+ "Search on your software" : null,
+ "Select all" : null,
+ "Select none" : null,
+ "Sent handshake. Waiting for instance listener's answer... ({0}%)" : null,
+ "Show a notification when there are available updates" : null,
+ "Show details" : null,
+ "Show info" : null,
+ "Show info about the package on the Updates tab" : null,
+ "Show missing translation strings" : null,
+ "Show package info" : null,
+ "Show scoop apps as lowercase" : null,
+ "Show unknown versions" : null,
+ "Show WingetUI" : null,
+ "Skip hash check" : null,
+ "Skip the hash check" : null,
+ "Software updates" : null,
+ "Source" : null,
+ "Starting daemons..." : null,
+ "Starting installation..." : null,
+ "Startup options" : null,
+ "Status" : null,
+ "Sudo found: {0}" : null,
+ "The main goal of this project is to give a GUI Store to the most common CLI Package Managers for windows, such as Winget and Scoop." : null,
+ "This project has no connection with the winget-cli official project, and it's totally unofficial." : null,
+ "uninstall" : null,
+ "Uninstall" : null,
+ "uninstallation" : null,
+ "{} Uninstallation" : null,
+ "Uninstall canceled by user!" : null,
+ "uninstalled" : null,
+ "uninstalling" : null,
+ "Uninstall package" : null,
+ "Uninstall selected package" : null,
+ "Uninstall selected packages" : null,
+ "Uninstall with administrator privileges" : null,
+ "Unknown" : null,
+ "Update" : null,
+ "Update all" : null,
+ "updated" : null,
+ "Updated scoop sources" : null,
+ "Updated winget sources" : null,
+ "Update found!" : null,
+ "update(noun)" : "update",
+ "Updates found!" : null,
+ "update(verb)" : "update",
+ "Update WingetUI automatically" : null,
+ "updating" : null,
+ "Updating scoop sources..." : null,
+ "Updating winget sources..." : null,
+ "Upgrade all" : null,
+ "Upgrade selected" : null,
+ "Use installed GSudo instead of the bundled one (requires app restart)" : null,
+ "Version" : null,
+ "Version:" : null,
+ "Waiting for other installations to finish..." : null,
+ "We could not {0} {1}. Please try again later. Click on \"Show details\" to get the logs from the installer." : null,
+ "We could not {0} {1}. Please try again later. Click on \"Show details\" to get the logs from the uninstaller." : null,
+ "Winget found: {0}" : null,
+ "WingetUI - {0} {1}" : null,
+ "WingetUI - {0} updates are available" : null,
+ "WingetUI - 1 update is available" : null,
+ "WingetUI display language:" : null,
+ "WingetUI log" : null,
+ "WingetUI Settings" : null,
+ "WingetUI version {0}" : null
+}
\ No newline at end of file
diff --git a/wingetui/lang/lang_tools.py b/wingetui/lang/lang_tools.py
new file mode 100644
index 0000000000..8c8b5e3839
--- /dev/null
+++ b/wingetui/lang/lang_tools.py
@@ -0,0 +1,66 @@
+from os.path import exists
+from pathlib import Path
+
+
+languageReference = {
+ "default": "System language",
+ "ca" : "Catalan - Català",
+ "en" : "English - English",
+}
+
+
+languageRemap = {
+ "pt-PT": "pt_PT",
+ "pt-BR": "pt_BR",
+ "uk": "ua",
+ "zh-Hant-TW": "zh_TW",
+ "zh-Hans-CN": "zh_CN",
+}
+
+
+# ISO 3166-1
+languageFlagsRemap = {
+ "ar": "sa",
+ "bs": "ba",
+ "ca": "ad",
+ "cs": "cz",
+ "da": "dk",
+ "en": "gb",
+ "el": "gr",
+ "et": "ee",
+ "fa": "ir",
+ "he": "il",
+ "ja": "jp",
+ "ko": "kr",
+ "nb": "no",
+ "nn": "no",
+ "pt_BR": "br",
+ "pt_PT": "pt",
+ "si": "lk",
+ "zh_CN": "cn",
+ "zh_TW": "tw",
+ "vi": "vn",
+ "sr": "rs",
+ "sv": "se",
+}
+
+
+def getMarkdownSupportLangs():
+ from translated_percentage import untranslatedPercentage
+
+ readmeLangs = [
+ "| Language | Translated | |",
+ "| :-- | :-- | --- |",
+ ]
+
+ dir = str(Path(__file__).parent)
+ for lang, langName in languageReference.items():
+ if (not exists(f"{dir}/lang_{lang}.json")): continue
+ perc = untranslatedPercentage[lang] if (lang in untranslatedPercentage) else "100%"
+ if (perc == "0%"): continue
+ langName = languageReference[lang] if (lang in languageReference) else lang
+ flag = languageFlagsRemap[lang] if (lang in languageFlagsRemap) else lang
+ readmeLangs.append(f"| {langName} | {perc} |
|")
+ readmeLangs.append("")
+
+ return "\n".join(readmeLangs)
diff --git a/wingetui/lang/translated_percentage.py b/wingetui/lang/translated_percentage.py
new file mode 100644
index 0000000000..65e4e838d9
--- /dev/null
+++ b/wingetui/lang/translated_percentage.py
@@ -0,0 +1,6 @@
+# Autogenerated file, do not modify it!!!
+# The following list includes ONLY non-full translated files.
+
+untranslatedPercentage = {
+ "en-US-POSIX": "92%"
+}
\ No newline at end of file
diff --git a/wingetui/languages.py b/wingetui/languages.py
new file mode 100644
index 0000000000..7c802ce305
--- /dev/null
+++ b/wingetui/languages.py
@@ -0,0 +1,12 @@
+from lang.lang_tools import languageReference
+
+lang = {}
+englang = {}
+languages = {} # will be auto-generated
+
+## auto-generate map of files
+for key in languageReference.keys():
+ if (key != "default"):
+ languages[key] = f"lang_{key}.json"
+
+debugLang = False
diff --git a/wingetui/mainWindow.py b/wingetui/mainWindow.py
index 74a0f95af3..7b490dc3aa 100644
--- a/wingetui/mainWindow.py
+++ b/wingetui/mainWindow.py
@@ -6,6 +6,7 @@
import globals
+from tools import _
from uiSections import *
from storeEngine import *
@@ -23,7 +24,7 @@ def __init__(self):
super().__init__()
self.isWinDark = isDark()
self.callInMain.connect(lambda f: f())
- self.setWindowTitle("WingetUI: A Graphical User interface to manage Winget and Scoop packages")
+ self.setWindowTitle("WingetUI")
self.setMinimumSize(700, 560)
self.setObjectName("micawin")
self.setWindowIcon(QIcon(realpath+"/resources/icon.png"))
@@ -73,40 +74,22 @@ def loadWidgets(self) -> None:
self.discover = DiscoverSoftwareSection()
self.discover.setStyleSheet("QGroupBox{border-radius: 5px;}")
globals.discover = self.discover
- self.widgets[self.discover] = self.addTab(self.discover, "Discover Packages")
+ self.widgets[self.discover] = self.addTab(self.discover, _("Discover Packages"))
self.updates = UpdateSoftwareSection()
self.updates.setStyleSheet("QGroupBox{border-radius: 5px;}")
globals.updates = self.updates
- self.widgets[self.updates] = self.addTab(self.updates, "Software Updates")
+ self.widgets[self.updates] = self.addTab(self.updates, _("Software Updates"))
self.uninstall = UninstallSoftwareSection()
self.uninstall.setStyleSheet("QGroupBox{border-radius: 5px;}")
globals.uninstall = self.uninstall
- self.widgets[self.uninstall] = self.addTab(self.uninstall, "Installed Packages")
+ self.widgets[self.uninstall] = self.addTab(self.uninstall, _("Installed Packages"))
self.settingsSection = SettingsSection()
- self.widgets[self.settingsSection] = self.addTab(self.settingsSection, "WingetUI Settings", addToMenu=True, actionIcon="settings")
+ self.widgets[self.settingsSection] = self.addTab(self.settingsSection, _("WingetUI Settings"), addToMenu=True, actionIcon="settings")
self.aboutSection = AboutSection()
- self.widgets[self.aboutSection] = self.addTab(self.aboutSection, "About WingetUI", addToMenu=True, actionIcon="info")
+ self.widgets[self.aboutSection] = self.addTab(self.aboutSection, _("About WingetUI"), addToMenu=True, actionIcon="info")
self.aboutSection = DebuggingSection()
- self.widgets[self.aboutSection] = self.addTab(self.aboutSection, "WingetUI log", addToMenu=True, actionIcon="buggy")
+ self.widgets[self.aboutSection] = self.addTab(self.aboutSection, _("WingetUI log"), addToMenu=True, actionIcon="buggy")
- class Text(QPlainTextEdit):
- def __init__(self):
- super().__init__()
- self.setPlainText("click to show log")
-
- def mousePressEvent(self, e: QMouseEvent) -> None:
- self.setPlainText(buffer.getvalue())
- self.appendPlainText(errbuffer.getvalue())
- return super().mousePressEvent(e)
-
- def showEvent(self, e: QShowEvent) -> None:
- self.setPlainText(buffer.getvalue())
- self.appendPlainText(errbuffer.getvalue())
- return super().showEvent(e)
-
- p = Text()
- p.setReadOnly(True)
- #self.addTab(p, "Debugging log", addToMenu=True)
self.buttonLayout.addWidget(QWidget(), stretch=1)
vl = QVBoxLayout()
hl = QHBoxLayout()
@@ -198,11 +181,11 @@ def addTab(self, widget: QWidget, label: str, addToMenu: bool = False, actionIco
def warnAboutAdmin(self):
self.err = ErrorMessage(self)
errorData = {
- "titlebarTitle": f"WingetUI",
- "mainTitle": f"Administrator privileges",
- "mainText": f"It looks like you ran WingetUI as administrator, which is not recommended. You can still use the program, but we hightly recommend not running WingetUI with administrator privileges. Click on \"Show details\" to see why.",
- "buttonTitle": "Ok",
- "errorDetails": "There are two main reasons to not run WingetUI as administrator:\n The first one is that the Scoop package manager might cause problems with some commands when ran with administrator rights.\n The second one is that running WingetUI as administrator means that any package that you download will be ran as administrator (and this is not safe).\n Remeber that if you need to install a specific package as administrator, you can always right-click the item -> Install/Update/Uninstall as administrator.",
+ "titlebarTitle": _("WingetUI"),
+ "mainTitle": _("Administrator privileges"),
+ "mainText": _("It looks like you ran WingetUI as administrator, which is not recommended. You can still use the program, but we hightly recommend not running WingetUI with administrator privileges. Click on \"Show details\" to see why."),
+ "buttonTitle": _("Ok"),
+ "errorDetails": _("There are two main reasons to not run WingetUI as administrator:\n The first one is that the Scoop package manager might cause problems with some commands when ran with administrator rights.\n The second one is that running WingetUI as administrator means that any package that you download will be ran as administrator (and this is not safe).\n Remeber that if you need to install a specific package as administrator, you can always right-click the item -> Install/Update/Uninstall as administrator."),
"icon": QIcon(getMedia("infocolor")),
}
self.err.showErrorMessage(errorData, showNotification=False)
@@ -220,11 +203,11 @@ def closeEvent(self, event):
event.accept()
if(globals.pending_programs != []):
if getSettings("DisablesystemTray"):
- if(tools.MessageBox.question(self, "Warning", "There is an installation in progress. If you close WingetUI, the installation may fail and have unexpected results. Do you still want to close the application?", tools.MessageBox.No | tools.MessageBox.Yes, tools.MessageBox.No) == tools.MessageBox.Yes):
+ if(tools.MessageBox.question(self, _("Warning"), _("There is an installation in progress. If you close WingetUI, the installation may fail and have unexpected results. Do you still want to quit WingetUI?"), tools.MessageBox.No | tools.MessageBox.Yes, tools.MessageBox.No) == tools.MessageBox.Yes):
if globals.updatesAvailable:
self.hide()
globals.canUpdate = True
- globals.trayIcon.showMessage("Updating WingetUI", "WingetUI is being updated. When finished, WingetUI will restart itself", QIcon(getMedia("notif_info")))
+ globals.trayIcon.showMessage(_("Updating WingetUI"), _("WingetUI is being updated. When finished, WingetUI will restart itself"), QIcon(getMedia("notif_info")))
event.ignore()
else:
event.accept()
@@ -236,7 +219,7 @@ def closeEvent(self, event):
if globals.updatesAvailable:
self.hide()
globals.canUpdate = True
- globals.trayIcon.showMessage("Updating WingetUI", "WingetUI is being updated. When finished, WingetUI will restart itself", QIcon(getMedia("notif_info")))
+ globals.trayIcon.showMessage(_("Updating WingetUI"), _("WingetUI is being updated. When finished, WingetUI will restart itself"), QIcon(getMedia("notif_info")))
event.ignore()
else:
self.hide()
@@ -246,7 +229,7 @@ def closeEvent(self, event):
if globals.updatesAvailable:
self.hide()
globals.canUpdate = True
- globals.trayIcon.showMessage("Updating WingetUI", "WingetUI is being updated. When finished, WingetUI will restart itself", QIcon(getMedia("notif_info")))
+ globals.trayIcon.showMessage(_("Updating WingetUI"), _("WingetUI is being updated. When finished, WingetUI will restart itself"), QIcon(getMedia("notif_info")))
event.ignore()
else:
if getSettings("DisablesystemTray"):
diff --git a/wingetui/storeEngine.py b/wingetui/storeEngine.py
index 4ff81bf855..be029b7cd3 100644
--- a/wingetui/storeEngine.py
+++ b/wingetui/storeEngine.py
@@ -5,6 +5,7 @@
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from tools import *
+from tools import _
import globals
@@ -19,10 +20,10 @@ class PackageInstallerWidget(QGroupBox):
def __init__(self, title: str, store: str, version: list = [], parent=None, customCommand: str = "", args: list = [], packageId="", admin: bool = False, useId: bool = False, packageItem: TreeWidgetItemWithQAction = None):
super().__init__(parent=parent)
self.packageItem = packageItem
- self.actionDone = "installed"
- self.actionDoing = "installing"
- self.actionName = "installation"
- self.actionVerb = "install"
+ self.actionDone = _("installed")
+ self.actionDoing = _("installing")
+ self.actionName = _("installation")
+ self.actionVerb = _("install")
self.runAsAdmin = admin
self.useId = useId
self.adminstr = [sudoPath] if self.runAsAdmin else []
@@ -39,7 +40,7 @@ def __init__(self, title: str, store: str, version: list = [], parent=None, cust
self.cmdline_args = args
self.layout = QHBoxLayout()
self.layout.setContentsMargins(30, 10, 10, 10)
- self.label = QLabel(title+" Installation")
+ self.label = QLabel(_("{0} installation").format(title))
self.layout.addWidget(self.label)
self.layout.addSpacing(5)
self.progressbar = QProgressBar()
@@ -51,13 +52,13 @@ def __init__(self, title: str, store: str, version: list = [], parent=None, cust
self.layout.addWidget(self.progressbar, stretch=1)
self.info = QLineEdit()
self.info.setStyleSheet("color: grey; border-bottom: inherit;")
- self.info.setText("Waiting for other installations to finish...")
+ self.info.setText(_("Waiting for other installations to finish..."))
self.info.setReadOnly(True)
self.addInfoLine.connect(lambda text: self.info.setText(text))
self.finishInstallation.connect(self.finish)
self.layout.addWidget(self.info)
self.counterSignal.connect(self.counter)
- self.cancelButton = QPushButton(QIcon(realpath+"/resources/cancel.png"), "Cancel")
+ self.cancelButton = QPushButton(QIcon(realpath+"/resources/cancel.png"), _("Cancel"))
self.cancelButton.clicked.connect(self.cancel)
self.cancelButton.setFixedHeight(30)
self.info.setFixedHeight(30)
@@ -113,7 +114,7 @@ def runInstallation(self) -> None:
self.leftFast.stop()
self.rightSlow.stop()
self.rightFast.stop()
- self.addInfoLine.emit("Starting installation...")
+ self.addInfoLine.emit(_("Starting installation..."))
self.progressbar.setValue(0)
self.packageId = self.packageId.replace("…", "")
self.programName = self.programName.replace("…", "")
@@ -153,9 +154,9 @@ def cancel(self):
if not self.finishedInstallation:
subprocess.Popen("taskkill /im winget.exe /f", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell=True, cwd=os.getcwd(), env=os.environ).wait()
self.finishedInstallation = True
- self.info.setText("Installation canceled by user!")
+ self.info.setText(_("Installation canceled by user!"))
self.cancelButton.setEnabled(True)
- self.cancelButton.setText("Close")
+ self.cancelButton.setText(_("Close"))
self.cancelButton.setIcon(QIcon(realpath+"/resources/warn.png"))
self.cancelButton.clicked.connect(self.close)
self.onCancel.emit()
@@ -181,11 +182,11 @@ def finish(self, returncode: int, output: str = "") -> None:
except: pass
if not(self.canceled):
if(returncode == 0):
- self.callInMain.emit(lambda: globals.trayIcon.showMessage(f"{self.actionName.capitalize()} succeeded", f"{self.programName} was {self.actionDone} successfully!", QIcon(getMedia("notif_info"))))
+ self.callInMain.emit(lambda: globals.trayIcon.showMessage(_("{0} succeeded").format(self.actionName.capitalize()), _("{0} was {1} successfully!").format(self.programName, self.actionDone), QIcon(getMedia("notif_info"))))
self.cancelButton.setText("OK")
self.cancelButton.setIcon(QIcon(realpath+"/resources/tick.png"))
self.cancelButton.clicked.connect(self.close)
- self.info.setText(f"{self.programName} was {self.actionDone} successfully!")
+ self.info.setText(_("{0} was {1} successfully!").format(self.programName, self.actionDone))
self.progressbar.setValue(1000)
if type(self) == PackageInstallerWidget:
globals.uninstall.addItem(self.packageItem.text(0), self.packageItem.text(1), self.packageItem.text(2), self.packageItem.text(3)) # Add the package on the uninstaller
@@ -194,14 +195,14 @@ def finish(self, returncode: int, output: str = "") -> None:
msgBox = MessageBox(self)
msgBox.setWindowTitle("WingetUI")
msgBox.setText(f"{self.programName} was {self.actionDone} successfully.")
- msgBox.setInformativeText(f"You will need to restart the application in order to get the {self.programName} new packages")
+ msgBox.setInformativeText("You will need to restart the application in order to get the {self.programName} new packages")
msgBox.setStandardButtons(MessageBox.Ok)
msgBox.setDefaultButton(MessageBox.Ok)
msgBox.setIcon(MessageBox.Information)
msgBox.exec_()
else:
globals.trayIcon.setIcon(QIcon(getMedia("yellowicon")))
- self.cancelButton.setText("OK")
+ self.cancelButton.setText(_("OK"))
self.cancelButton.setIcon(QIcon(realpath+"/resources/warn.png"))
self.cancelButton.clicked.connect(self.close)
self.progressbar.setValue(1000)
@@ -209,25 +210,25 @@ def finish(self, returncode: int, output: str = "") -> None:
if(returncode == 2): # if the installer's hash does not coincide
errorData = {
"titlebarTitle": f"WingetUI - {self.programName} {self.actionName}",
- "mainTitle": f"{self.actionName.capitalize()} aborted",
- "mainText": f"The checksum of the installer does not coincide with the expected value, and the authenticity of the installer can't be verified. If you trust the publisher, {self.actionVerb} the package again skipping the hash check.",
- "buttonTitle": "Close",
+ "mainTitle": _("{0} aborted").format(self.actionName.capitalize()),
+ "mainText": _("The checksum of the installer does not coincide with the expected value, and the authenticity of the installer can't be verified. If you trust the publisher, {0} the package again skipping the hash check.").format(self.actionVerb),
+ "buttonTitle": _("Close"),
"errorDetails": output.replace("-\|/", "").replace("▒", "").replace("█", ""),
"icon": QIcon(getMedia("warn")),
- "notifTitle": f"Can't {self.actionVerb} {self.programName}",
- "notifText": f"The installer has an invalid checksum",
+ "notifTitle": _("Can't {0} {1}").format(self.actionVerb, self.programName),
+ "notifText": _("The installer has an invalid checksum"),
"notifIcon": QIcon(getMedia("notif_warn")),
}
else: # if there's a generic error
errorData = {
- "titlebarTitle": f"WingetUI - {self.programName} {self.actionName}",
- "mainTitle": f"{self.actionName.capitalize()} failed",
- "mainText": f"We could not {self.actionVerb} {self.programName}. Please try again later. Click on \"Show details\" to get the logs from the installer.",
- "buttonTitle": "Close",
+ "titlebarTitle": _("WingetUI - {0} {1}").format(self.programName, self.actionName),
+ "mainTitle": _("{0} failed").format(self.actionName.capitalize()),
+ "mainText": _("We could not {0} {1}. Please try again later. Click on \"Show details\" to get the logs from the installer.").format(self.actionVerb, self.programName),
+ "buttonTitle": _("Close"),
"errorDetails": output.replace("-\|/", "").replace("▒", "").replace("█", ""),
"icon": QIcon(getMedia("warn")),
- "notifTitle": f"Can't {self.actionVerb} {self.programName}",
- "notifText": f"{self.programName} {self.actionName} failed",
+ "notifTitle": _("Can't {0} {1}").format(self.actionVerb, self.programName),
+ "notifText": _("{0} {1} failed").format(self.programName.capitalize(), self.actionName),
"notifIcon": QIcon(getMedia("notif_warn")),
}
self.err.showErrorMessage(errorData)
@@ -277,10 +278,10 @@ class PackageUpdaterWidget(PackageInstallerWidget):
def __init__(self, title: str, store: str, version: list = [], parent=None, customCommand: str = "", args: list = [], packageId="", packageItem: TreeWidgetItemWithQAction = None, admin: bool = False, useId: bool = False):
super().__init__(title, store, version, parent, customCommand, args, packageId, admin, useId)
self.packageItem = packageItem
- self.actionDone = "updated"
- self.actionDoing = "updating"
- self.actionName = "update"
- self.actionVerb = "update"
+ self.actionDone = _("updated")
+ self.actionDoing = _("updating")
+ self.actionName = _("update(noun)")
+ self.actionVerb = _("update(verb)")
def startInstallation(self) -> None:
while self.installId != globals.current_program and not getSettings("AllowParallelInstalls"):
@@ -293,7 +294,7 @@ def runInstallation(self) -> None:
self.leftSlow.stop()
self.leftFast.stop()
self.rightSlow.stop()
- self.addInfoLine.emit("Applying update...")
+ self.addInfoLine.emit(_("Applying update..."))
self.rightFast.stop()
self.progressbar.setValue(0)
self.packageId = self.packageId.replace("…", "")
@@ -348,18 +349,18 @@ def __init__(self, title: str, store: str, useId=False, packageId = "", packageI
self.programName = title
self.packageId = packageId
super().__init__(parent=None, title=title, store=store, packageId=packageId, admin=admin, args=args, packageItem=packageItem)
- self.actionDone = "uninstalled"
+ self.actionDone = _("uninstalled")
self.removeData = removeData
- self.actionDoing = "uninstalling"
- self.actionName = "uninstallation"
- self.actionVerb = "uninstall"
+ self.actionDoing = _("uninstalling")
+ self.actionName = _("uninstallation")
+ self.actionVerb = _("uninstall")
self.finishedInstallation = True
self.runAsAdmin = admin
self.adminstr = [sudoPath] if self.runAsAdmin else []
self.store = store.lower()
self.setStyleSheet("QGroupBox{padding-top:15px; margin-top:-15px; border: none}")
self.setFixedHeight(50)
- self.label.setText(title+" Uninstallation")
+ self.label.setText(_("{} Uninstallation").format(title))
def startInstallation(self) -> None:
while self.installId != globals.current_program and not getSettings("AllowParallelInstalls"):
@@ -403,12 +404,12 @@ def cancel(self):
self.leftFast.stop()
self.rightSlow.stop()
self.rightFast.stop()
- self.info.setText("Installation canceled by user!")
+ self.info.setText(_("Uninstall canceled by user!"))
if not self.finishedInstallation:
subprocess.Popen("taskkill /im winget.exe /f", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell=True, cwd=os.getcwd(), env=os.environ).wait()
self.finishedInstallation = True
self.cancelButton.setEnabled(True)
- self.cancelButton.setText("Close")
+ self.cancelButton.setText(_("Close"))
self.cancelButton.setIcon(QIcon(realpath+"/resources/warn.png"))
self.cancelButton.clicked.connect(self.close)
self.onCancel.emit()
@@ -443,51 +444,29 @@ def finish(self, returncode: int, output: str = "") -> None:
if not(self.canceled):
if(returncode == 0):
self.callInMain.emit(lambda: globals.trayIcon.showMessage(f"{self.actionName.capitalize()} succeeded", f"{self.programName} was {self.actionDone} successfully!", QIcon(getMedia("notif_info"))))
- self.cancelButton.setText("OK")
+ self.cancelButton.setText(_("OK"))
self.cancelButton.setIcon(QIcon(realpath+"/resources/tick.png"))
self.cancelButton.clicked.connect(self.close)
- self.info.setText(f"{self.programName} was {self.actionDone} successfully!")
+ self.info.setText(f"{self.programName} was uninstalled successfully!")
self.progressbar.setValue(1000)
self.startCoolDown()
- if(self.store == "powershell"):
- msgBox = MessageBox(self)
- msgBox.setWindowTitle("WingetUI")
- msgBox.setText(f"{self.programName} was uninstalled successfully.")
- msgBox.setInformativeText(f"You will need to restart the application in order to get the {self.programName} new packages")
- msgBox.setStandardButtons(MessageBox.Ok)
- msgBox.setDefaultButton(MessageBox.Ok)
- msgBox.setIcon(MessageBox.Information)
- msgBox.exec_()
else:
globals.trayIcon.setIcon(QIcon(getMedia("yellowicon")))
- self.cancelButton.setText("OK")
+ self.cancelButton.setText(_("OK"))
self.cancelButton.setIcon(QIcon(realpath+"/resources/warn.png"))
self.cancelButton.clicked.connect(self.close)
self.progressbar.setValue(1000)
self.err = ErrorMessage(self.window())
- if(returncode == 2): # if the installer's hash does not coincide
- errorData = {
- "titlebarTitle": f"WingetUI - {self.programName} {self.actionName}",
- "mainTitle": f"{self.actionName.capitalize()} aborted",
- "mainText": f"The checksum of the installer does not coincide with the expected value, and the authenticity of the installer can't be verified. If you trust the publisher, {self.actionVerb} the package again skipping the hash check.",
- "buttonTitle": "Close",
- "errorDetails": output.replace("-\|/", "").replace("▒", "").replace("█", ""),
- "icon": QIcon(getMedia("warn")),
- "notifTitle": f"Can't {self.actionVerb} {self.programName}",
- "notifText": f"The installer has an invalid checksum",
- "notifIcon": QIcon(getMedia("notif_warn")),
- }
- else: # if there's a generic error
- errorData = {
- "titlebarTitle": f"WingetUI - {self.programName} {self.actionName}",
- "mainTitle": f"{self.actionName.capitalize()} failed",
- "mainText": f"We could not {self.actionVerb} {self.programName}. Please try again later. Click on \"Show details\" to get the logs from the installer.",
- "buttonTitle": "Close",
- "errorDetails": output.replace("-\|/", "").replace("▒", "").replace("█", ""),
- "icon": QIcon(getMedia("warn")),
- "notifTitle": f"Can't {self.actionVerb} {self.programName}",
- "notifText": f"{self.programName} {self.actionName} failed",
- "notifIcon": QIcon(getMedia("notif_warn")),
+ errorData = {
+ "titlebarTitle": _("WingetUI - {0} {1}").format(self.programName, self.actionName),
+ "mainTitle": _("{0} failed").format(self.actionName.capitalize()),
+ "mainText": _("We could not {0} {1}. Please try again later. Click on \"Show details\" to get the logs from the uninstaller.").format(self.actionVerb, self.programName),
+ "buttonTitle": _("Close"),
+ "errorDetails": output.replace("-\|/", "").replace("▒", "").replace("█", ""),
+ "icon": QIcon(getMedia("warn")),
+ "notifTitle": _("Can't {0} {1}").format(self.actionVerb, self.programName),
+ "notifText": _("{0} {1} failed").format(self.programName.capitalize(), self.actionName),
+ "notifIcon": QIcon(getMedia("notif_warn")),
}
self.err.showErrorMessage(errorData)
@@ -541,7 +520,7 @@ def __init__(self, parent = None):
self.layout = QVBoxLayout()
self.title = QLinkLabel()
self.title.setStyleSheet("font-size: 30pt;font-family: \"Segoe UI Variable Display\";font-weight: bold;")
- self.title.setText("Loading...")
+ self.title.setText(_("Loading..."))
fortyWidget = QWidget()
fortyWidget.setFixedWidth(120)
@@ -557,35 +536,35 @@ def __init__(self, parent = None):
self.hLayout = QHBoxLayout()
self.oLayout = QHBoxLayout()
- self.description = QLinkLabel("Description: Unknown")
+ self.description = QLinkLabel(_('Description:')+" "+_('Unknown'))
self.description.setWordWrap(True)
self.layout.addWidget(self.description)
- self.homepage = QLinkLabel("Homepage URL: Unknown")
+ self.homepage = QLinkLabel(_('Homepage URL:')+" "+_('Unknown'))
self.homepage.setWordWrap(True)
self.layout.addWidget(self.homepage)
- self.publisher = QLinkLabel("Publisher: Unknown")
+ self.publisher = QLinkLabel(_('Publisher:')+" "+_('Unknown'))
self.publisher.setWordWrap(True)
self.layout.addWidget(self.publisher)
- self.author = QLinkLabel("Author: Unknown")
+ self.author = QLinkLabel(_('Author:')+" "+_('Unknown'))
self.author.setWordWrap(True)
self.layout.addWidget(self.author)
self.layout.addStretch()
- self.license = QLinkLabel("License: Unknown")
+ self.license = QLinkLabel(_('License:')+" "+_('Unknown'))
self.license.setWordWrap(True)
self.layout.addWidget(self.license)
self.layout.addStretch()
hLayout = QHBoxLayout()
- self.versionLabel = QLinkLabel("Version: ")
+ self.versionLabel = QLinkLabel(_("Version:"))
self.versionCombo = CustomComboBox()
@@ -593,7 +572,7 @@ def __init__(self, parent = None):
self.versionCombo.setIconSize(QSize(24, 24))
self.versionCombo.setFixedHeight(35)
self.installButton = QPushButton()
- self.installButton.setText("Install")
+ self.installButton.setText(_("Install"))
self.installButton.setObjectName("AccentButton")
self.installButton.setIconSize(QSize(24, 24))
self.installButton.clicked.connect(self.install)
@@ -605,15 +584,15 @@ def __init__(self, parent = None):
optionsGroupBox = QGroupBox()
self.forceCheckbox = QCheckBox()
- self.forceCheckbox.setText("Skip hash check")
+ self.forceCheckbox.setText(_("Skip hash check"))
self.forceCheckbox.setChecked(False)
self.interactiveCheckbox = QCheckBox()
- self.interactiveCheckbox.setText("Interactive installation")
+ self.interactiveCheckbox.setText(_("Interactive installation"))
self.interactiveCheckbox.setChecked(False)
self.adminCheckbox = QCheckBox()
- self.adminCheckbox.setText("Run as admin")
+ self.adminCheckbox.setText(_("Run as admin"))
self.adminCheckbox.setChecked(False)
self.oLayout.addStretch()
@@ -638,29 +617,29 @@ def __init__(self, parent = None):
self.layout.addStretch()
- self.packageId = QLinkLabel("Program ID: Unknown")
+ self.packageId = QLinkLabel(_('Program ID:')+" "+_('Unknown'))
self.packageId.setWordWrap(True)
self.layout.addWidget(self.packageId)
- self.manifest = QLinkLabel("Manifest: Unknown")
+ self.manifest = QLinkLabel(_('Manifest:')+" "+_('Unknown'))
self.manifest.setWordWrap(True)
self.layout.addWidget(self.manifest)
- self.lastver = QLinkLabel("Latest version: Unknown")
+ self.lastver = QLinkLabel(_('Latest version:')+" "+_('Unknown'))
self.lastver.setWordWrap(True)
self.layout.addWidget(self.lastver)
- self.sha = QLinkLabel("Installer SHA256 (Latest version): Unknown")
+ self.sha = QLinkLabel(_('Installer SHA256 (Latest version):')+" "+_('Unknown'))
self.sha.setWordWrap(True)
self.layout.addWidget(self.sha)
- self.link = QLinkLabel("Installer URL (Latest version): Unknown")
+ self.link = QLinkLabel(_('Installer URL (Latest version):')+" "+_('Unknown'))
self.link.setWordWrap(True)
self.layout.addWidget(self.link)
- self.type = QLinkLabel("Installer type (Latest version): Unknown")
+ self.type = QLinkLabel(_('Installer type (Latest version):')+" "+_('Unknown'))
self.type.setWordWrap(True)
self.layout.addWidget(self.type)
self.storeLabel = QLinkLabel(f"Source: {self.store}")
self.storeLabel.setWordWrap(True)
self.layout.addWidget(self.storeLabel)
self.layout.addStretch()
- self.advert = QLinkLabel("ALERT: NEITHER MICROSOFT NOR THE CREATORS OF WINGETUI ARE RESPONSIBLE FOR THE DOWNLOADED SOFTWARE.")
+ self.advert = QLinkLabel(_("DISCLAIMER: NEITHER MICROSOFT NOR THE CREATORS OF WINGETUI ARE RESPONSIBLE FOR THE DOWNLOADED SOFTWARE."))
self.advert.setWordWrap(True)
self.layout.addWidget(self.advert)
@@ -737,7 +716,7 @@ def loadProgram(self, title: str, id: str, useId: bool, store: str, update: bool
self.installButton.setEnabled(False)
self.versionCombo.setEnabled(False)
self.isAnUpdate = update
- self.installButton.setText("Please wait...")
+ self.installButton.setText(_("Please wait..."))
store = store.lower()
self.title.setText(title)
@@ -748,19 +727,19 @@ def loadProgram(self, title: str, id: str, useId: bool, store: str, update: bool
self.interactiveCheckbox.setEnabled(False)
self.adminCheckbox.setChecked(False)
self.adminCheckbox.setEnabled(False)
- self.description.setText("Loading...")
- self.author.setText("Author: "+"Loading...")
- self.publisher.setText("Publisher: "+"Loading...")
- self.homepage.setText(f"Homepage: {'Loading...'}")
- self.license.setText(f"License: {'Loading...'} ({'Loading...'})")
- self.lastver.setText("Latest version: Loading...")
- self.sha.setText(f"Installer SHA256 (Latest version): {'Loading...'}")
- self.link.setText(f"Installer URL (Latest version): {'Loading...'}")
- self.type.setText(f"Installer type (Latest version): {'Loading...'}")
- self.packageId.setText(f"Package ID: {'Loading...'}")
- self.manifest.setText(f"Manifest: {'Loading...'}")
- self.storeLabel.setText(f"Source: {self.store.capitalize()}")
- self.versionCombo.addItems(["Loading..."])
+ self.description.setText(_("Loading..."))
+ self.author.setText(_("Author")+": "+_("Loading..."))
+ self.publisher.setText(f"{_('Publisher')}: "+_("Loading..."))
+ self.homepage.setText(f"{_('Homepage')}: {_('Loading...')}")
+ self.license.setText(f"{_('License')}: {_('Loading...')} ({_('Loading...')})")
+ self.lastver.setText(f"{_('Latest version')}: {_('Loading...')}")
+ self.sha.setText(f"{_('Installer SHA256')} ({_('Latest version')}): {_('Loading...')}")
+ self.link.setText(f"{_('Installer URL')} ({_('Latest version')}): {_('Loading...')}")
+ self.type.setText(f"{_('Installer type')} ({_('Latest version')}): {_('Loading...')}")
+ self.packageId.setText(f"{_('Package ID')}: {_('Loading...')}")
+ self.manifest.setText(f"{_('Manifest')}: {_('Loading...')}")
+ self.storeLabel.setText(f"{_('Source')}: {self.store.capitalize()}")
+ self.versionCombo.addItems([_("Loading...")])
self.finishedCount = 0
if(store.lower()=="winget"):
@@ -773,9 +752,9 @@ def printData(self, appInfo: dict) -> None:
if not("scoop" in self.store.lower()) or self.finishedCount > 1:
self.loadingProgressBar.hide()
if self.isAnUpdate:
- self.installButton.setText("Update")
+ self.installButton.setText(_("Update"))
else:
- self.installButton.setText("Install")
+ self.installButton.setText(_("Install"))
self.installButton.setEnabled(True)
self.versionCombo.setEnabled(True)
self.adminCheckbox.setEnabled(True)
@@ -784,19 +763,19 @@ def printData(self, appInfo: dict) -> None:
self.interactiveCheckbox.setEnabled(True)
self.title.setText(appInfo["title"])
self.description.setText(appInfo["description"])
- self.author.setText("Author: "+appInfo["author"])
- self.publisher.setText("Publisher: "+appInfo["publisher"])
- self.homepage.setText(f"Homepage: {appInfo['homepage']}")
- self.license.setText(f"License: {appInfo['license']} ({appInfo['license-url']})")
+ self.author.setText(f"{_('Author')}: "+appInfo["author"])
+ self.publisher.setText(f"{_('Publisher')}: "+appInfo["publisher"])
+ self.homepage.setText(f"{_('Homepage')}: {appInfo['homepage']}")
+ self.license.setText(f"{_('License')}: {appInfo['license']} ({appInfo['license-url']})")
try:
- self.lastver.setText(f"Latest version: {appInfo['versions'][0]}")
+ self.lastver.setText(f"{_('Latest version')}: {appInfo['versions'][0]}")
except IndexError:
- self.lastver.setText(f"Latest version: Unknown")
- self.sha.setText(f"Installer SHA256 (Latest version): {appInfo['installer-sha256']}")
- self.link.setText(f"Installer URL (Latest version): {appInfo['installer-url']}")
- self.type.setText(f"Installer type (Latest version): {appInfo['installer-type']}")
- self.packageId.setText(f"Package ID: {appInfo['id']}")
- self.manifest.setText(f"Manifest: {appInfo['manifest']}")
+ self.lastver.setText(_('Latest version:')+" "+_('Unknown'))
+ self.sha.setText(f"{_('Installer SHA256')} ({_('Latest version')}): {appInfo['installer-sha256']}")
+ self.link.setText(f"{_('Installer URL')} ({_('Latest version')}): {appInfo['installer-url']}")
+ self.type.setText(f"{_('Installer type')} ({_('Latest version')}): {appInfo['installer-type']}")
+ self.packageId.setText(f"{_('Package ID')}: {appInfo['id']}")
+ self.manifest.setText(f"{_('Manifest')}: {appInfo['manifest']}")
while self.versionCombo.count()>0:
self.versionCombo.removeItem(0)
try:
@@ -806,7 +785,7 @@ def printData(self, appInfo: dict) -> None:
def install(self):
title = self.title.text()
- packageId = self.packageId.text().replace('Package ID:', '').strip()
+ packageId = self.packageId.text().replace(_('Package ID')+":", '').strip()
print(f"🟢 Starting installation of package {title} with id {packageId}")
cmdline_args = []
if(self.forceCheckbox.isChecked()):
@@ -819,7 +798,7 @@ def install(self):
else:
if not "scoop" in self.store.lower():
cmdline_args.append("--silent")
- if(self.versionCombo.currentText()=="Latest"):
+ if(self.versionCombo.currentText()==_("Latest") or self.versionCombo.currentText() == "Latest"):
version = []
else:
version = ["--version", self.versionCombo.currentText()]
diff --git a/wingetui/tools.py b/wingetui/tools.py
index 711df70565..fce465ee7f 100644
--- a/wingetui/tools.py
+++ b/wingetui/tools.py
@@ -3,13 +3,14 @@
import winreg
import io
from threading import Thread
-import sys, time, subprocess, os
+import sys, time, subprocess, os, json, locale
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from win32mica import ApplyMica, MICAMODE
from urllib.request import urlopen
from versions import *
+from languages import *
import globals
@@ -19,6 +20,12 @@
old_stderr = sys.stderr
buffer = io.StringIO()
errbuffer = io.StringIO()
+settingsCache = {}
+installersWidget = None
+updatesAvailable = False
+
+missingTranslationList = []
+
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
sys.stdout = buffer = io.StringIO()
sys.stderr = errbuffer = io.StringIO()
@@ -28,6 +35,12 @@
else:
realpath = '/'.join(sys.argv[0].replace("\\", "/").split("/")[:-1])
+if not os.path.isdir(os.path.join(os.path.expanduser("~"), ".wingetui")):
+ try:
+ os.makedirs(os.path.join(os.path.expanduser("~"), ".wingetui"))
+ except:
+ pass
+
def cprint(*args) -> None:
print(*args, file=old_stdout)
@@ -38,15 +51,25 @@ def report(exception) -> None: # Exception reporter
cprint("🔴 "+line)
print(f"🔴 Note this traceback was caught by reporter and has been added to the log ({exception})")
-settingsCache = {}
-installersWidget = None
-updatesAvailable = False
-
-if not os.path.isdir(os.path.join(os.path.expanduser("~"), ".wingetui")):
+def _(s): # Translate function
+ global lang
try:
- os.makedirs(os.path.join(os.path.expanduser("~"), ".wingetui"))
- except:
- pass
+ t = lang[s]
+ return ("🟢"+t+"🟢" if debugLang else t) if t else f"🟡{s}🟡" if debugLang else eng_(s)
+ except KeyError:
+ if debugLang: print(s)
+ if not s in missingTranslationList:
+ missingTranslationList.append(s)
+ return f"🔴{eng_(s)}🔴" if debugLang else eng_(s)
+
+def eng_(s): # English translate function
+ try:
+ t = englang[s]
+ return t if t else s
+ except KeyError:
+ if debugLang:
+ print(s)
+ return s
def getSettings(s: str, cache = True):
global settingsCache
@@ -281,6 +304,7 @@ def __init__(self, emptystr: str = "") -> None:
op=QGraphicsOpacityEffect(self.label)
op.setOpacity(0.5)
self.label.setGraphicsEffect(op)
+ self.label.setAttribute(Qt.WA_TransparentForMouseEvents)
self.label.setAutoFillBackground(True)
font = self.label.font()
font.setBold(True)
@@ -448,7 +472,7 @@ def __init__(self, parent):
self.okButton = QPushButton()
self.okButton.setFixedHeight(30)
self.okButton.clicked.connect(self.delete)
- self.moreInfoButton = QPushButton("Show details")
+ self.moreInfoButton = QPushButton(_("Show details"))
self.moreInfoButton.setFixedHeight(30)
self.moreInfoButton.clicked.connect(self.moreInfo)
#hl.addStretch()
@@ -469,7 +493,7 @@ def delete(self):
def moreInfo(self):
spacingAdded = False
self.moreInfoTextArea.setVisible(not self.moreInfoTextArea.isVisible())
- self.moreInfoButton.setText("Hide details" if self.moreInfoTextArea.isVisible() else "Show details")
+ self.moreInfoButton.setText(_("Hide details") if self.moreInfoTextArea.isVisible() else _("Show details"))
if self.moreInfoTextArea.isVisible():
# show textedit
s = self.size()
@@ -737,6 +761,55 @@ def themeThread(ts):
Thread(target=themeThread, args=(ts,), daemon=True, name="UI Theme thread").start()
Thread(target=foregroundWindowThread, daemon=True, name="Tools: get foreground window").start()
+
+if getSettingsValue("PreferredLanguage") == "":
+ setSettingsValue("PreferredLanguage", "default")
+
+def loadLangFile(file: str, bundled: bool = False) -> dict:
+ try:
+ path = os.path.join(os.path.expanduser("~"), ".elevenclock/lang/"+file)
+ if not os.path.exists(path) or getSettings("DisableLangAutoUpdater") or bundled or True:
+ #print(f"🟡 Using bundled lang file (forced={bundled})")
+ path = getPath("../lang/"+file)
+ #else:
+ # print("🟢 Using cached lang file")
+ with open(path, "r", encoding='utf-8') as file:
+ return json.load(file)
+ except Exception as e:
+ report(e)
+ return {}
+
+t0 = time.time()
+
+langName = getSettingsValue("PreferredLanguage")
+try:
+ if (langName == "default"):
+ langName = locale.getdefaultlocale()[0]
+ langNames = [langName, langName[0:2]]
+ langFound = False
+ for ln in langNames:
+ if (ln in languages):
+ lang = loadLangFile(languages[ln]) | {"locale": ln}
+ langFound = True
+ #if not getSettings("DisableLangAutoUpdater"):
+ # Thread(target=updateLangFile, args=(languages[ln],), name=f"DAEMON: Update lang_{ln}.json").start()
+ break
+ if (langFound == False):
+ raise Exception(f"Value not found for {langNames}")
+except Exception as e:
+ report(e)
+ lang = loadLangFile(languages["en"]) | {"locale": "en"}
+ print("🔴 Unknown language")
+
+langName = lang['locale']
+
+try:
+ englang = loadLangFile(languages["en"], bundled=True) | {"locale": "en"}
+except Exception as e:
+ report(e)
+ englang = {"locale": "en"}
+
+print(f"It took {time.time()-t0} to load all language files")
if __name__ == "__main__":
diff --git a/wingetui/uiSections.py b/wingetui/uiSections.py
index 6b0f163ab7..9aacf4a277 100644
--- a/wingetui/uiSections.py
+++ b/wingetui/uiSections.py
@@ -6,8 +6,10 @@
from PySide6.QtWidgets import *
from tools import *
from storeEngine import *
+from lang.translated_percentage import untranslatedPercentage
import globals
+from tools import _
class DiscoverSoftwareSection(QWidget):
@@ -49,7 +51,7 @@ def __init__(self, parent = None):
hLayout = QHBoxLayout()
hLayout.setContentsMargins(25, 0, 25, 0)
- self.forceCheckBox = QCheckBox("Instant search")
+ self.forceCheckBox = QCheckBox(_("Instant search"))
self.forceCheckBox.setFixedHeight(30)
self.forceCheckBox.setLayoutDirection(Qt.RightToLeft)
self.forceCheckBox.setFixedWidth(98)
@@ -59,7 +61,7 @@ def __init__(self, parent = None):
self.forceCheckBox.clicked.connect(lambda v: setSettings("DisableInstantSearchOnInstall", bool(not v)))
self.query = CustomLineEdit()
- self.query.setPlaceholderText(" Search something on Winget or Scoop")
+ self.query.setPlaceholderText(" "+_("Search for something on Winget or Scoop"))
self.query.returnPressed.connect(self.filter)
self.query.textChanged.connect(lambda: self.filter() if self.forceCheckBox.isChecked() else print())
self.query.setFixedHeight(30)
@@ -84,7 +86,7 @@ def __init__(self, parent = None):
hLayout.addWidget(img)
v = QVBoxLayout()
- self.discoverLabel = QLabel("Discover Packages")
+ self.discoverLabel = QLabel(_("Discover Packages"))
self.discoverLabel.setStyleSheet(f"font-size: 30pt;font-family: \"Segoe UI Variable Display\";font-weight: bold;")
v.addWidget(self.discoverLabel)
@@ -101,7 +103,7 @@ def __init__(self, parent = None):
self.packageListScrollBar.setOrientation(Qt.Vertical)
self.packageList: TreeWidget = TreeWidget("a")
- self.packageList.setHeaderLabels(["Package Name", "Package ID", "Version", "Source"])
+ self.packageList.setHeaderLabels([_("Package Name"), _("Package ID"), _("Version"), _("Source")])
self.packageList.setColumnCount(4)
self.packageList.sortByColumn(0, Qt.AscendingOrder)
self.packageList.setSortingEnabled(True)
@@ -120,19 +122,19 @@ def showMenu(pos: QPoint):
contextMenu.setParent(self)
contextMenu.setStyleSheet("* {background: red;color: black}")
ApplyMenuBlur(contextMenu.winId().__int__(), contextMenu)
- inf = QAction("Show info")
+ inf = QAction(_("Show info"))
inf.triggered.connect(lambda: self.openInfo(self.packageList.currentItem().text(0), self.packageList.currentItem().text(1), self.packageList.currentItem().text(3), packageItem=self.packageList.currentItem()))
inf.setIcon(QIcon(getMedia("info")))
- ins1 = QAction("Install")
+ ins1 = QAction(_("Install"))
ins1.setIcon(QIcon(getMedia("newversion")))
ins1.triggered.connect(lambda: self.fastinstall(self.packageList.currentItem().text(0), self.packageList.currentItem().text(1), self.packageList.currentItem().text(3), packageItem=self.packageList.currentItem()))
- ins2 = QAction("Run as administrator")
+ ins2 = QAction(_("Run as administrator"))
ins2.setIcon(QIcon(getMedia("runasadmin")))
ins2.triggered.connect(lambda: self.fastinstall(self.packageList.currentItem().text(0), self.packageList.currentItem().text(1), self.packageList.currentItem().text(3), admin=True, packageItem=self.packageList.currentItem()))
- ins3 = QAction("Skip hash check")
+ ins3 = QAction(_("Skip hash check"))
ins3.setIcon(QIcon(getMedia("checksum")))
ins3.triggered.connect(lambda: self.fastinstall(self.packageList.currentItem().text(0), self.packageList.currentItem().text(1), self.packageList.currentItem().text(3), skiphash=True, packageItem=self.packageList.currentItem()))
- ins4 = QAction("Interactive installation")
+ ins4 = QAction(_("Interactive installation"))
ins4.setIcon(QIcon(getMedia("interactive")))
ins4.triggered.connect(lambda: self.fastinstall(self.packageList.currentItem().text(0), self.packageList.currentItem().text(1), self.packageList.currentItem().text(3), interactive=True, packageItem=self.packageList.currentItem()))
contextMenu.addAction(ins1)
@@ -202,11 +204,11 @@ def showMenu(pos: QPoint):
tooltips = {
- self.upgradeSelected: "Install selected package",
- inf: "Show package info",
- ins2: "Run the installer with administrator privileges",
- ins3: "Skip the hash check",
- ins4: "Interactive installation",
+ self.upgradeSelected: _("Install selected package"),
+ inf: _("Show package info"),
+ ins2: _("Run the installer with administrator privileges"),
+ ins3: _("Skip the hash check"),
+ ins4: _("Interactive installation"),
}
for action in [self.upgradeSelected, inf, ins2, ins3, ins4]:
@@ -216,7 +218,7 @@ def showMenu(pos: QPoint):
self.toolbar.addSeparator()
- self.importAction = QAction("Import packages from a file", self.toolbar)
+ self.importAction = QAction(_("Import packages from a file"), self.toolbar)
self.importAction.setIcon(QIcon(getMedia("import")))
self.importAction.triggered.connect(lambda: self.importPackages())
self.toolbar.addAction(self.importAction)
@@ -225,7 +227,7 @@ def showMenu(pos: QPoint):
self.toolbar.addWidget(TenPxSpacer())
self.toolbar.addWidget(TenPxSpacer())
- self.countLabel = QLabel("Searching for packages...")
+ self.countLabel = QLabel(_("Searching for packages..."))
self.packageList.label.setText(self.countLabel.text())
self.countLabel.setObjectName("greyLabel")
v.addWidget(self.countLabel)
@@ -303,7 +305,7 @@ def showMenu(pos: QPoint):
def importPackages(self):
try:
packageList = []
- file = QFileDialog.getOpenFileName(self, "Select package file", filter="JSON (*.json)")[0]
+ file = QFileDialog.getOpenFileName(self, _("Select package file"), filter="JSON (*.json)")[0]
if file != "":
f = open(file, "r")
contents = json.load(f)
@@ -331,7 +333,7 @@ def importPackages(self):
def finishLoadingIfNeeded(self, store: str) -> None:
if(store == "winget"):
- self.countLabel.setText("Found packages: "+str(self.packageList.topLevelItemCount())+", not finished yet...")
+ self.countLabel.setText(_("Found packages: {0}, not finished yet...").format(str(self.packageList.topLevelItemCount())))
if self.packageList.topLevelItemCount() == 0:
self.packageList.label.setText(self.countLabel.text())
else:
@@ -342,7 +344,7 @@ def finishLoadingIfNeeded(self, store: str) -> None:
self.searchButton.setEnabled(True)
self.query.setEnabled(True)
elif(store == "scoop"):
- self.countLabel.setText("Found packages: "+str(self.packageList.topLevelItemCount())+", not finished yet...")
+ self.countLabel.setText(_("Found packages: {0}, not finished yet...").format(str(self.packageList.topLevelItemCount())))
if self.packageList.topLevelItemCount() == 0:
self.packageList.label.setText(self.countLabel.text())
else:
@@ -355,7 +357,7 @@ def finishLoadingIfNeeded(self, store: str) -> None:
if(self.wingetLoaded and self.scoopLoaded):
self.filter()
self.loadingProgressBar.hide()
- self.countLabel.setText("Found packages: "+str(self.packageList.topLevelItemCount()))
+ self.countLabel.setText(_("Found packages: {0}").format(str(self.packageList.topLevelItemCount())))
self.packageList.label.setText("")
print("🟢 Total packages: "+str(self.packageList.topLevelItemCount()))
@@ -390,9 +392,9 @@ def filter(self) -> None:
if found == 0:
if self.packageList.label.text() == "":
self.packageList.label.show()
- self.packageList.label.setText("No packages found matching the input criteria")
+ self.packageList.label.setText(_("No packages found matching the input criteria"))
else:
- if self.packageList.label.text() == "No packages found matching the input criteria":
+ if self.packageList.label.text() == _("No packages found matching the input criteria"):
self.packageList.label.hide()
self.packageList.label.setText("")
self.packageList.scrollToItem(self.packageList.currentItem())
@@ -422,7 +424,7 @@ def reload(self) -> None:
self.query.setEnabled(False)
self.packageList.clear()
self.query.setText("")
- self.countLabel.setText("Searching for packages...")
+ self.countLabel.setText(_("Searching for packages..."))
self.packageList.label.setText(self.countLabel.text())
if not getSettings("DisableWinget"):
Thread(target=wingetHelpers.searchForPackage, args=(self.addProgram, self.finishLoading), daemon=True).start()
@@ -446,6 +448,10 @@ def destroy(self, destroyWindow: bool = ..., destroySubWindows: bool = ...) -> N
anim.deleteLater()
return super().destroy(destroyWindow, destroySubWindows)
+ def showEvent(self, event: QShowEvent) -> None:
+ self.forceCheckBox.setFixedWidth(self.forceCheckBox.sizeHint().width())
+ return super().showEvent(event)
+
class UpdateSoftwareSection(QWidget):
addProgram = Signal(str, str, str, str, str)
@@ -491,7 +497,7 @@ def __init__(self, parent = None):
hLayout.setContentsMargins(25, 0, 25, 0)
self.query = CustomLineEdit()
- self.query.setPlaceholderText(" Search available updates")
+ self.query.setPlaceholderText(" "+_("Search for available updates"))
self.query.returnPressed.connect(self.filter)
self.query.textChanged.connect(lambda: self.filter() if self.forceCheckBox.isChecked() else print())
self.query.setFixedHeight(30)
@@ -510,7 +516,7 @@ def __init__(self, parent = None):
sct = QShortcut(QKeySequence("Esc"), self)
sct.activated.connect(self.query.clear)
- self.forceCheckBox = QCheckBox("Instant search")
+ self.forceCheckBox = QCheckBox(_("Instant search"))
self.forceCheckBox.setFixedHeight(30)
self.forceCheckBox.setLayoutDirection(Qt.RightToLeft)
self.forceCheckBox.setFixedWidth(98)
@@ -525,7 +531,7 @@ def __init__(self, parent = None):
hLayout.addWidget(self.img)
v = QVBoxLayout()
- self.discoverLabel = QLabel("Software Updates")
+ self.discoverLabel = QLabel(_("Software Updates"))
self.discoverLabel.setStyleSheet(f"font-size: 30pt;font-family: \"Segoe UI Variable Display\";font-weight: bold;")
v.addWidget(self.discoverLabel)
@@ -541,7 +547,7 @@ def __init__(self, parent = None):
self.packageList = TreeWidget("ª")
self.packageList.setIconSize(QSize(24, 24))
self.packageList.setColumnCount(6)
- self.packageList.setHeaderLabels(["", "Package Name", "Package ID", "Installed Version", "New Version", "Source"])
+ self.packageList.setHeaderLabels(["", _("Package Name"), _("Package ID"), _("Installed Version"), _("New Version"), _("Source")])
self.packageList.setColumnWidth(0, 50)
self.packageList.setColumnWidth(1, 350)
self.packageList.setColumnWidth(2, 200)
@@ -564,22 +570,22 @@ def showMenu(pos: QPoint):
contextMenu.setParent(self)
contextMenu.setStyleSheet("* {background: red;color: black}")
ApplyMenuBlur(contextMenu.winId().__int__(), contextMenu)
- inf = QAction("Show info")
+ inf = QAction(_("Show info"))
inf.triggered.connect(lambda: self.openInfo(self.packageList.currentItem().text(1), self.packageList.currentItem().text(2), self.packageList.currentItem().text(5).lower(), self.packageList.currentItem()))
inf.setIcon(QIcon(getMedia("info")))
- ins1 = QAction("Update")
+ ins1 = QAction(_("Update"))
ins1.setIcon(QIcon(getMedia("newversion")))
ins1.triggered.connect(lambda: self.update(self.packageList.currentItem().text(1), self.packageList.currentItem().text(2), self.packageList.currentItem().text(5).lower(), packageItem=self.packageList.currentItem()))
- ins2 = QAction("Run as administrator")
+ ins2 = QAction(_("Run as administrator"))
ins2.setIcon(QIcon(getMedia("runasadmin")))
ins2.triggered.connect(lambda: self.update(self.packageList.currentItem().text(1), self.packageList.currentItem().text(2), self.packageList.currentItem().text(5).lower(), packageItem=self.packageList.currentItem(), admin=True))
- ins3 = QAction("Skip hash check")
+ ins3 = QAction(_("Skip hash check"))
ins3.setIcon(QIcon(getMedia("checksum")))
ins3.triggered.connect(lambda: self.update(self.packageList.currentItem().text(1), self.packageList.currentItem().text(2), self.packageList.currentItem().text(5).lower(), packageItem=self.packageList.currentItem(), skiphash=True))
- ins4 = QAction("Interactive update")
+ ins4 = QAction(_("Interactive update"))
ins4.setIcon(QIcon(getMedia("interactive")))
ins4.triggered.connect(lambda: self.update(self.packageList.currentItem().text(1), self.packageList.currentItem().text(2), self.packageList.currentItem().text(5).lower(), packageItem=self.packageList.currentItem(), interactive=True))
- ins5 = QAction("Uninstall package")
+ ins5 = QAction(_("Uninstall package"))
ins5.setIcon(QIcon(getMedia("menu_uninstall")))
ins5.triggered.connect(lambda: globals.uninstall.uninstall(self.packageList.currentItem().text(1), self.packageList.currentItem().text(2), self.packageList.currentItem().text(5), packageItem=self.packageList.currentItem()))
contextMenu.addAction(ins1)
@@ -589,7 +595,7 @@ def showMenu(pos: QPoint):
contextMenu.addAction(ins4)
contextMenu.addAction(ins3)
contextMenu.addSeparator()
- ins6 = QAction("Ignore updates for this package")
+ ins6 = QAction(_("Ignore updates for this package"))
ins6.setIcon(QIcon(getMedia("blacklist")))
ins6.triggered.connect(lambda: (setSettingsValue("BlacklistedUpdates", getSettingsValue("BlacklistedUpdates")+self.packageList.currentItem().text(2)+","), self.packageList.currentItem().setHidden(True)))
contextMenu.addAction(ins6)
@@ -687,11 +693,11 @@ def setAllSelected(checked: bool) -> None:
tooltips = {
- self.upgradeSelected: "Install selected package",
- inf: "Show package info",
- ins2: "Run the installer with administrator privileges",
- ins3: "Skip the hash check",
- ins4: "Interactive installation",
+ self.upgradeSelected: _("Install selected package"),
+ inf: _("Show package info"),
+ ins2: _("Run the installer with administrator privileges"),
+ ins3: _("Skip the hash check"),
+ ins4: _("Interactive installation"),
}
for action in [self.upgradeSelected, inf, ins2, ins3, ins4]:
@@ -702,10 +708,10 @@ def setAllSelected(checked: bool) -> None:
self.toolbar.addSeparator()
- self.upgradeAllAction = QAction(QIcon(getMedia("installall")), "Upgrade all", self.toolbar)
+ self.upgradeAllAction = QAction(QIcon(getMedia("installall")), _("Upgrade all"), self.toolbar)
self.upgradeAllAction.triggered.connect(lambda: self.updateAll())
self.toolbar.addAction(self.upgradeAllAction)
- self.upgradeSelectedAction = QAction(QIcon(getMedia("list")), "Upgrade selected", self.toolbar)
+ self.upgradeSelectedAction = QAction(QIcon(getMedia("list")), _("Upgrade selected"), self.toolbar)
self.upgradeSelectedAction.triggered.connect(lambda: self.updateSelected())
self.toolbar.addAction(self.upgradeSelectedAction)
@@ -719,19 +725,19 @@ def setAllSelected(checked: bool) -> None:
self.selectNoneAction.triggered.connect(lambda: setAllSelected(False))
self.toolbar.addAction(self.selectNoneAction)
self.toolbar.widgetForAction(self.selectNoneAction).setFixedSize(40, 45)
- self.toolbar.widgetForAction(self.selectNoneAction).setToolTip("Select none")
- self.toolbar.widgetForAction(self.selectAllAction).setToolTip("Select all")
+ self.toolbar.widgetForAction(self.selectNoneAction).setToolTip(_("Select none"))
+ self.toolbar.widgetForAction(self.selectAllAction).setToolTip(_("Select all"))
self.toolbar.addSeparator()
- self.selectAllAction = QAction(QIcon(getMedia("blacklist")), "Blacklist apps", self.toolbar)
+ self.selectAllAction = QAction(QIcon(getMedia("blacklist")), _("Blacklist apps"), self.toolbar)
self.selectAllAction.triggered.connect(lambda: blacklistSelectedPackages())
self.toolbar.addAction(self.selectAllAction)
- self.selectAllAction = QAction(QIcon(getMedia("undelete")), "Reset blacklist", self.toolbar)
+ self.selectAllAction = QAction(QIcon(getMedia("undelete")), _("Reset blacklist"), self.toolbar)
self.selectAllAction.triggered.connect(lambda: (setSettingsValue("BlacklistedUpdates", ""), self.reload()))
self.toolbar.addAction(self.selectAllAction)
- self.showUnknownSection = QCheckBox("Show unknown versions")
+ self.showUnknownSection = QCheckBox(_("Show unknown versions"))
self.showUnknownSection.setFixedHeight(30)
self.showUnknownSection.setLayoutDirection(Qt.RightToLeft)
self.showUnknownSection.setFixedWidth(190)
@@ -764,7 +770,7 @@ def updatelist(selff = None):
#h2Layout.addStretch()
#h2Layout.addWidget(self.showUnknownVersions)
- self.countLabel = QLabel("Checking for updates...")
+ self.countLabel = QLabel(_("Checking for updates..."))
self.packageList.label.setText(self.countLabel.text())
self.countLabel.setObjectName("greyLabel")
layout.addLayout(hLayout)
@@ -841,20 +847,20 @@ def updatelist(selff = None):
def finishLoadingIfNeeded(self, store: str) -> None:
if(store == "winget"):
- self.countLabel.setText("Available updates: "+str(self.packageList.topLevelItemCount())+", not finished yet...")
+ self.countLabel.setText(_("Available updates: {0}, not finished yet...").format(str(self.packageList.topLevelItemCount())))
if self.packageList.topLevelItemCount() == 0:
self.packageList.label.setText(self.countLabel.text())
else:
self.packageList.label.setText("")
- globals.trayMenuUpdatesList.menuAction().setText(f"{self.packageList.topLevelItemCount()} updates found")
+ globals.trayMenuUpdatesList.menuAction().setText(_("Available updates: {0}, not finished yet...").format(str(self.packageList.topLevelItemCount())))
self.wingetLoaded = True
self.reloadButton.setEnabled(True)
self.filter()
self.searchButton.setEnabled(True)
self.query.setEnabled(True)
elif(store == "scoop"):
- self.countLabel.setText("Available updates: "+str(self.packageList.topLevelItemCount())+", not finished yet...")
- globals.trayMenuUpdatesList.menuAction().setText(f"{self.packageList.topLevelItemCount()} updates found")
+ self.countLabel.setText(_("Available updates: {0}, not finished yet...").format(str(self.packageList.topLevelItemCount())))
+ globals.trayMenuUpdatesList.menuAction().setText(_("Available updates: {0}, not finished yet...").format(str(self.packageList.topLevelItemCount())))
if self.packageList.topLevelItemCount() == 0:
self.packageList.label.setText(self.countLabel.text())
else:
@@ -867,6 +873,7 @@ def finishLoadingIfNeeded(self, store: str) -> None:
if(self.wingetLoaded and self.scoopLoaded):
self.loadingProgressBar.hide()
self.loadingProgressBar.hide()
+ globals.trayMenuUpdatesList.menuAction().setText(_("Available updates: {0}").format(str(self.packageList.topLevelItemCount())))
count = 0
lastVisibleItem = None
for i in range(self.packageList.topLevelItemCount()):
@@ -876,15 +883,15 @@ def finishLoadingIfNeeded(self, store: str) -> None:
self.packageList.label.setText(str(count))
if not getSettings("DisableUpdatesNotifications"):
if count > 1:
- notify("Updates found!", f"{count} apps can be updated")
+ notify(_("Updates found!"), _("{0} apps can be updated").format(count))
elif count == 1:
- notify("Update found!", f"{lastVisibleItem.text(1)} can be updated")
+ notify(_("Update found!"), _("{0} can be updated").format(lastVisibleItem.text(1)))
if count > 0:
globals.trayIcon.setIcon(QIcon(getMedia("greenicon")))
else:
globals.trayIcon.setIcon(QIcon(getMedia("greyicon")))
self.updatePackageNumber()
- self.packageList.label.setText()
+ self.packageList.label.setText("")
self.filter()
self.updatelist()
if not getSettings("DisableAutoCheckforUpdates"):
@@ -947,9 +954,9 @@ def filter(self) -> None:
if found == 0:
if self.packageList.label.text() == "":
self.packageList.label.show()
- self.packageList.label.setText("No packages found matching the input criteria")
+ self.packageList.label.setText(_("No packages found matching the input criteria"))
else:
- if self.packageList.label.text() == "No packages found matching the input criteria":
+ if self.packageList.label.text() == _("No packages found matching the input criteria"):
self.packageList.label.hide()
self.packageList.label.setText("")
self.packageList.scrollToItem(self.packageList.currentItem())
@@ -959,15 +966,15 @@ def updatePackageNumber(self, showQueried: bool = False, foundResults: int = 0):
for item in self.packageList.findItems('', Qt.MatchContains, 1):
if not item.isHidden():
self.availableUpdates += 1
- self.countLabel.setText(f"Available updates: {self.availableUpdates}")
- globals.trayIcon.setToolTip("WingetUI" if self.availableUpdates == 0 else (f"WingetUI - {self.availableUpdates} update is available" if self.availableUpdates == 1 else f"WingetUI - {self.availableUpdates} updates are available") )
- globals.trayMenuUpdatesList.menuAction().setText(f"{self.availableUpdates} updates found")
+ self.countLabel.setText(_("Available updates: {0}").format(self.availableUpdates))
+ globals.trayIcon.setToolTip("WingetUI" if self.availableUpdates == 0 else (_("WingetUI - 1 update is available") if self.availableUpdates == 1 else _("WingetUI - {0} updates are available").format(self.availableUpdates)) )
+ globals.trayMenuUpdatesList.menuAction().setText(_("{0} updates found").format(self.availableUpdates))
if self.availableUpdates > 0:
self.packageList.label.hide()
self.packageList.label.setText("")
self.img.setPixmap(QIcon(getMedia("alert_laptop")).pixmap(QSize(64, 64)))
else:
- self.packageList.label.setText("Hooray! No updates were found!")
+ self.packageList.label.setText(_("Hooray! No updates were found!"))
self.packageList.label.show()
self.img.setPixmap(QIcon(getMedia("checked_laptop")).pixmap(QSize(64, 64)))
@@ -1029,7 +1036,7 @@ def reload(self) -> None:
for action in globals.trayMenuUpdatesList.actions():
globals.trayMenuUpdatesList.removeAction(action)
globals.trayMenuUpdatesList.addAction(globals.updatesHeader)
- self.countLabel.setText("Checking for updates...")
+ self.countLabel.setText(_("Checking for updates..."))
self.packageList.label.setText(self.countLabel.text())
self.blacklist = getSettingsValue("BlacklistedUpdates")
if not getSettings("DisableWinget"):
@@ -1054,6 +1061,10 @@ def destroy(self, destroyWindow: bool = ..., destroySubWindows: bool = ...) -> N
anim.deleteLater()
return super().destroy(destroyWindow, destroySubWindows)
+ def showEvent(self, event: QShowEvent) -> None:
+ self.forceCheckBox.setFixedWidth(self.forceCheckBox.sizeHint().width())
+ return super().showEvent(event)
+
class UninstallSoftwareSection(QWidget):
addProgram = Signal(str, str, str, str)
@@ -1098,7 +1109,7 @@ def __init__(self, parent = None):
#hLayout.setContentsMargins(25, 0, 25, 0)
self.query = CustomLineEdit()
- self.query.setPlaceholderText(" Search on your software")
+ self.query.setPlaceholderText(" "+_("Search on your software"))
self.query.returnPressed.connect(self.filter)
self.query.textChanged.connect(lambda: self.filter() if self.forceCheckBox.isChecked() else print())
self.query.setFixedHeight(30)
@@ -1118,7 +1129,7 @@ def __init__(self, parent = None):
sct.activated.connect(self.query.clear)
- self.forceCheckBox = QCheckBox("Instant search")
+ self.forceCheckBox = QCheckBox(_("Instant search"))
self.forceCheckBox.setFixedHeight(30)
self.forceCheckBox.setLayoutDirection(Qt.RightToLeft)
self.forceCheckBox.setFixedWidth(98)
@@ -1134,7 +1145,7 @@ def __init__(self, parent = None):
hLayout.addWidget(img)
v = QVBoxLayout()
- self.discoverLabel = QLabel("Installed Packages")
+ self.discoverLabel = QLabel(_("Installed Packages"))
self.discoverLabel.setStyleSheet(f"font-size: 30pt;font-family: \"Segoe UI Variable Display\";font-weight: bold;")
v.addWidget(self.discoverLabel)
@@ -1153,9 +1164,10 @@ def __init__(self, parent = None):
self.packageListScrollBar = CustomScrollBar()
self.packageListScrollBar.setOrientation(Qt.Vertical)
- self.packageList = TreeWidget("Found 0 Packages")
+ self.packageList = TreeWidget(_("Found 0 Packages"))
self.packageList.setIconSize(QSize(24, 24))
- self.headers = ["", "Package Name", "Package ID", "Installed Version", "Source"] # empty header added for checkbox
+ self.headers = ["", _("Package Name"), _("Package ID"), _("Installed Version"), _("Source")] # empty header added for checkbox
+
self.packageList.setColumnCount(len(self.headers))
self.packageList.setHeaderLabels(self.headers)
self.packageList.setColumnWidth(0, 46)
@@ -1195,19 +1207,19 @@ def showMenu(pos: QPoint):
contextMenu.setParent(self)
contextMenu.setStyleSheet("* {background: red;color: black}")
ApplyMenuBlur(contextMenu.winId().__int__(), contextMenu)
- ins1 = QAction("Uninstall")
+ ins1 = QAction(_("Uninstall"))
ins1.setIcon(QIcon(getMedia("menu_uninstall")))
ins1.triggered.connect(lambda: self.uninstall(self.packageList.currentItem().text(1), self.packageList.currentItem().text(2), self.packageList.currentItem().text(4), packageItem=self.packageList.currentItem()))
- ins2 = QAction("Run as administrator")
+ ins2 = QAction(_("Run as administrator"))
ins2.setIcon(QIcon(getMedia("runasadmin")))
ins2.triggered.connect(lambda: self.uninstall(self.packageList.currentItem().text(1), self.packageList.currentItem().text(2), self.packageList.currentItem().text(4), packageItem=self.packageList.currentItem(), admin=True))
- ins3 = QAction("Remove permanent data")
+ ins3 = QAction(_("Remove permanent data"))
ins3.setIcon(QIcon(getMedia("menu_close")))
ins3.triggered.connect(lambda: self.uninstall(self.packageList.currentItem().text(1), self.packageList.currentItem().text(2), self.packageList.currentItem().text(4), packageItem=self.packageList.currentItem(), removeData=True))
- ins5 = QAction("Interactive uninstall")
+ ins5 = QAction(_("Interactive uninstall"))
ins5.setIcon(QIcon(getMedia("interactive")))
ins5.triggered.connect(lambda: self.uninstall(self.packageList.currentItem().text(1), self.packageList.currentItem().text(2), self.packageList.currentItem().text(4), interactive=True))
- ins4 = QAction("Show package info")
+ ins4 = QAction(_("Show package info"))
ins4.setIcon(QIcon(getMedia("info")))
ins4.triggered.connect(lambda: self.openInfo(self.packageList.currentItem().text(1), self.packageList.currentItem().text(2), self.packageList.currentItem().text(4), self.packageList.currentItem()))
contextMenu.addAction(ins1)
@@ -1232,15 +1244,12 @@ def showMenu(pos: QPoint):
self.loadingProgressBar.setFixedHeight(4)
self.loadingProgressBar.setTextVisible(False)
self.loadingProgressBar.setStyleSheet("margin: 0px; margin-left: 15px;margin-right: 15px;")
-
layout = QVBoxLayout()
w = QWidget()
w.setLayout(layout)
w.setMaximumWidth(1300)
-
-
self.bodyWidget = QWidget()
l = QHBoxLayout()
l.addWidget(ScrollWidget(self.packageList), stretch=0)
@@ -1250,19 +1259,6 @@ def showMenu(pos: QPoint):
l.addWidget(self.packageListScrollBar)
self.bodyWidget.setLayout(l)
- #self.selectAllPkgsCheckBox = QCheckBox("Select all")
- #self.selectAllPkgsCheckBox.setFixedHeight(30)
- #self.selectAllPkgsCheckBox.setLayoutDirection(Qt.RightToLeft)
- ##self.selectAllPkgsCheckBox.setFixedWidth(140)
- #self.selectAllPkgsCheckBox.setStyleSheet("margin-top: 0px;")
- #self.selectAllPkgsCheckBox.setChecked(self.allPkgSelected)
- #self.selectAllPkgsCheckBox.clicked.connect(lambda v: self.selectAllInstalled())
-
- #self.exportSelectionButton = QPushButton("Export selection (beta)")
- #self.exportSelectionButton.setFixedWidth(300)
- #self.exportSelectionButton.setStyleSheet("margin-top: 0px;")
- #self.exportSelectionButton.clicked.connect(self.exportSelection)
-
self.toolbar = QToolBar(self)
self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
@@ -1281,9 +1277,9 @@ def showMenu(pos: QPoint):
tooltips = {
- self.upgradeSelected: "Uninstall selected package",
- ins2: "Uninstall with administrator privileges",
- ins5: "Interactive uninstall",
+ self.upgradeSelected: _("Uninstall selected package"),
+ ins2: _("Uninstall with administrator privileges"),
+ ins5: _("Interactive uninstall"),
}
for action in [self.upgradeSelected, ins2, ins5]:
@@ -1294,7 +1290,7 @@ def showMenu(pos: QPoint):
self.toolbar.addSeparator()
- self.upgradeSelectedAction = QAction(QIcon(getMedia("list")), "Uninstall selected packages", self.toolbar)
+ self.upgradeSelectedAction = QAction(QIcon(getMedia("list")), _("Uninstall selected packages"), self.toolbar)
self.upgradeSelectedAction.triggered.connect(lambda: self.uninstallSelected())
self.toolbar.addAction(self.upgradeSelectedAction)
@@ -1314,16 +1310,16 @@ def setAllSelected(checked: bool) -> None:
self.selectNoneAction.triggered.connect(lambda: setAllSelected(False))
self.toolbar.addAction(self.selectNoneAction)
self.toolbar.widgetForAction(self.selectNoneAction).setFixedSize(40, 45)
- self.toolbar.widgetForAction(self.selectNoneAction).setToolTip("Select none")
- self.toolbar.widgetForAction(self.selectAllAction).setToolTip("Select all")
+ self.toolbar.widgetForAction(self.selectNoneAction).setToolTip(_("Select none"))
+ self.toolbar.widgetForAction(self.selectAllAction).setToolTip(_("Select all"))
self.toolbar.addSeparator()
- self.exportAction = QAction(QIcon(getMedia("export")), "Export selected packages to a file", self.toolbar)
+ self.exportAction = QAction(QIcon(getMedia("export")), _("Export selected packages to a file"), self.toolbar)
self.exportAction.triggered.connect(lambda: self.exportSelection())
self.toolbar.addAction(self.exportAction)
- self.exportAction = QAction(QIcon(getMedia("export")), "Export all", self.toolbar)
+ self.exportAction = QAction(QIcon(getMedia("export")), _("Export all"), self.toolbar)
self.exportAction.triggered.connect(lambda: self.exportSelection(all=True))
self.toolbar.addAction(self.exportAction)
@@ -1335,7 +1331,7 @@ def setAllSelected(checked: bool) -> None:
- self.countLabel = QLabel("Searching for installed packages...")
+ self.countLabel = QLabel(_("Searching for installed packages..."))
self.packageList.label.setText(self.countLabel.text())
self.countLabel.setObjectName("greyLabel")
layout.addLayout(hLayout)
@@ -1424,9 +1420,9 @@ def uninstallSelected(self) -> None:
pass
conf = False
if len(toUninstall) == 1:
- conf = MessageBox.question(self, "Are you sure?", f"Do you really want to uninstall {toUninstall[0].text(1)}?", MessageBox.No | MessageBox.Yes, MessageBox.Yes) == MessageBox.Yes
+ conf = MessageBox.question(self, _("Are you sure?"), _("Do you really want to uninstall {0}?").format(toUninstall[0].text(1)), MessageBox.No | MessageBox.Yes, MessageBox.Yes) == MessageBox.Yes
elif len(toUninstall) > 1:
- conf = MessageBox.question(self, "Are you sure?", f"Do you really want to uninstall {len(toUninstall)} packages?", MessageBox.No | MessageBox.Yes, MessageBox.Yes) == MessageBox.Yes
+ conf = MessageBox.question(self, _("Are you sure?"), _("Do you really want to uninstall {0} packages?").format(len(toUninstall)), MessageBox.No | MessageBox.Yes, MessageBox.Yes) == MessageBox.Yes
if conf:
for program in toUninstall:
self.uninstall(program.text(1), program.text(2), program.text(4), packageItem=program, avoidConfirm=True)
@@ -1439,24 +1435,24 @@ def openInfo(self, title: str, id: str, store: str, packageItem: TreeWidgetItemW
def finishLoadingIfNeeded(self, store: str) -> None:
if(store == "winget"):
- self.countLabel.setText("Found packages: "+str(self.packageList.topLevelItemCount())+", not finished yet...")
+ self.countLabel.setText(_("Found packages: {0}, not finished yet...").format(str(self.packageList.topLevelItemCount())))
if self.packageList.topLevelItemCount() == 0:
self.packageList.label.setText(self.countLabel.text())
else:
self.packageList.label.setText("")
- globals.trayMenuInstalledList.setTitle(f"{self.packageList.topLevelItemCount()} packages found")
+ globals.trayMenuInstalledList.setTitle(_("{0} packages found").format(str(self.packageList.topLevelItemCount())))
self.wingetLoaded = True
self.reloadButton.setEnabled(True)
self.searchButton.setEnabled(True)
self.filter()
self.query.setEnabled(True)
elif(store == "scoop"):
- self.countLabel.setText("Found packages: "+str(self.packageList.topLevelItemCount())+", not finished yet...")
+ self.countLabel.setText(_("Found packages: {0}, not finished yet...").format(str(self.packageList.topLevelItemCount())))
if self.packageList.topLevelItemCount() == 0:
self.packageList.label.setText(self.countLabel.text())
else:
self.packageList.label.setText("")
- globals.trayMenuInstalledList.setTitle(f"{self.packageList.topLevelItemCount()} packages found")
+ globals.trayMenuInstalledList.setTitle(_("{0} packages found").format(str(self.packageList.topLevelItemCount())))
self.scoopLoaded = True
self.reloadButton.setEnabled(True)
self.filter()
@@ -1465,8 +1461,8 @@ def finishLoadingIfNeeded(self, store: str) -> None:
if(self.wingetLoaded and self.scoopLoaded):
self.filter()
self.loadingProgressBar.hide()
- globals.trayMenuInstalledList.setTitle(f"{self.packageList.topLevelItemCount()} packages found")
- self.countLabel.setText("Found packages: "+str(self.packageList.topLevelItemCount()))
+ globals.trayMenuInstalledList.setTitle(_("{0} packages found").format(str(self.packageList.topLevelItemCount())))
+ self.countLabel.setText(_("Found packages: {0}").format(str(self.packageList.topLevelItemCount())))
self.packageList.label.setText("")
print("🟢 Total packages: "+str(self.packageList.topLevelItemCount()))
@@ -1516,9 +1512,9 @@ def filter(self) -> None:
if found == 0:
if self.packageList.label.text() == "":
self.packageList.label.show()
- self.packageList.label.setText("No packages found matching the input criteria")
+ self.packageList.label.setText(_("No packages found matching the input criteria"))
else:
- if self.packageList.label.text() == "No packages found matching the input criteria":
+ if self.packageList.label.text() == _("No packages found matching the input criteria"):
self.packageList.label.hide()
self.packageList.label.setText("")
self.packageList.scrollToItem(self.packageList.currentItem())
@@ -1531,7 +1527,7 @@ def uninstall(self, title: str, id: str, store: str, packageItem: TreeWidgetItem
if avoidConfirm:
answer = True
else:
- answer = MessageBox.question(self, "Are you sure?", f"Do you really want to uninstall {title}?", MessageBox.No | MessageBox.Yes, MessageBox.Yes) == MessageBox.Yes
+ answer = MessageBox.question(self, _("Are you sure?"), _("Do you really want to uninstall {0}?").format(title), MessageBox.No | MessageBox.Yes, MessageBox.Yes) == MessageBox.Yes
if answer:
print("🔵 Uninstalling", id)
if not "scoop" in store.lower():
@@ -1548,7 +1544,7 @@ def reload(self) -> None:
self.query.setEnabled(False)
self.packageList.clear()
self.query.setText("")
- self.countLabel.setText("Searching for installed packages...")
+ self.countLabel.setText(_("Searching for installed packages..."))
self.packageList.label.setText(self.countLabel.text())
if not getSettings("DisableWinget"):
Thread(target=wingetHelpers.searchForInstalledPackage, args=(self.addProgram, self.finishLoading), daemon=True).start()
@@ -1620,7 +1616,7 @@ def exportSelection(self, all: bool = False) -> None:
"scoop": scoopExportSchema
}
- filename = QFileDialog.getSaveFileName(self, "Save File", "wingetui exported packages", filter='JSON (*.json)')
+ filename = QFileDialog.getSaveFileName(self, _("Save File"), _("wingetui exported packages"), filter='JSON (*.json)')
if filename[0] != "":
with open(filename[0], 'w') as f:
f.write(json.dumps(overAllSchema, indent=4))
@@ -1638,6 +1634,10 @@ def destroy(self, destroyWindow: bool = ..., destroySubWindows: bool = ...) -> N
anim.deleteLater()
return super().destroy(destroyWindow, destroySubWindows)
+ def showEvent(self, event: QShowEvent) -> None:
+ self.forceCheckBox.setFixedWidth(self.forceCheckBox.sizeHint().width())
+ return super().showEvent(event)
+
class AboutSection(QScrollArea):
def __init__(self, parent = None):
@@ -1659,7 +1659,7 @@ def __init__(self, parent = None):
self.setWidget(self.widget)
self.announcements = QAnnouncements()
self.layout.addWidget(self.announcements)
- title = QLabel("Component Information")
+ title = QLabel(_("Component Information"))
title.setStyleSheet(f"font-size: 40px;font-family: \"Segoe UI Variable Display\";font-weight: bold;")
self.layout.addWidget(title)
@@ -1673,48 +1673,49 @@ def __init__(self, parent = None):
table.setEnabled(False)
table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
table.setShowGrid(False)
- table.setHorizontalHeaderLabels(["Status", "Version"])
+ table.setHorizontalHeaderLabels([_("Status"), _("Version")])
table.setColumnWidth(1, 500)
table.verticalHeader().setFixedWidth(100)
table.setVerticalHeaderLabels(["Winget", " Scoop", " GSudo"])
- table.setItem(0, 0, QTableWidgetItem(str("Found" if globals.componentStatus["wingetFound"] else "Not found")))
+ table.setItem(0, 0, QTableWidgetItem(_("Found") if globals.componentStatus["wingetFound"] else _("Not found")))
table.setItem(0, 1, QTableWidgetItem(str(globals.componentStatus["wingetVersion"])))
- table.setItem(1, 0, QTableWidgetItem(str("Found" if globals.componentStatus["scoopFound"] else "Not found")))
+ table.setItem(1, 0, QTableWidgetItem(_("Found") if globals.componentStatus["scoopFound"] else _("Not found")))
table.setItem(1, 1, QTableWidgetItem(str(globals.componentStatus["scoopVersion"])))
- table.setItem(2, 0, QTableWidgetItem(str("Found" if globals.componentStatus["sudoFound"] else "Not found")))
+ table.setItem(2, 0, QTableWidgetItem(_("Found") if globals.componentStatus["sudoFound"] else _("Not found")))
table.setItem(2, 1, QTableWidgetItem(str(globals.componentStatus["sudoVersion"])))
table.setCornerWidget(QLabel(""))
table.setCornerButtonEnabled(True)
table.cornerWidget().setStyleSheet("background: transparent;")
self.layout.addWidget(table)
- title = QLabel("About WingetUI "+str(versionName)+"")
+ title = QLabel(_("About WingetUI version {0}").format(versionName))
title.setStyleSheet(f"font-size: 40px;font-family: \"Segoe UI Variable Display\";font-weight: bold;")
self.layout.addWidget(title)
- self.layout.addWidget(QLinkLabel())
- description = QLinkLabel(f"The main goal of this project is to create an intuitive UI to manage the most common CLI package managers for Windows, such as Winget and Scoop.\nThis project has no connection with the official Winget project — it's completely unofficial. ")
+ self.layout.addWidget(QLabel())
+
+ description = QLabel(_("The main goal of this project is to create an intuitive UI to manage the most common CLI package managers for Windows, such as Winget and Scoop.")+"\n"+_("This project has no connection with the winget-cli official project, and it's totally unofficial."))
self.layout.addWidget(description)
self.layout.addSpacing(5)
- self.layout.addWidget(QLinkLabel(f"Homepage: https://github.com/martinet101/WingetUI"))
+ self.layout.addWidget(QLinkLabel(f"{_('Homepage')}: https://github.com/martinet101/WingetUI"))
self.layout.addSpacing(30)
- self.layout.addWidget(QLinkLabel("Licenses:", "font-size: 22pt;font-family: \"Segoe UI Variable Display\";font-weight: bold;"))
+ self.layout.addWidget(QLinkLabel(f"{_('Licenses')}:", "font-size: 22pt;font-family: \"Segoe UI Variable Display\";font-weight: bold;"))
self.layout.addWidget(QLabel())
self.layout.addWidget(QLinkLabel(f"WingetUI: LGPL v2.1: https://github.com/martinet101/WinGetUI/blob/main/LICENSE"))
self.layout.addWidget(QLabel())
self.layout.addWidget(QLinkLabel(f"PySide6: LGPLv3: https://www.gnu.org/licenses/lgpl-3.0.html"))
- self.layout.addWidget(QLinkLabel(f"Python3: PSF License: https://docs.python.org/3/license.html#psf-license"))
+ self.layout.addWidget(QLinkLabel(f"Python3: {('PSF License')}: https://docs.python.org/3/license.html#psf-license"))
self.layout.addWidget(QLinkLabel())
- self.layout.addWidget(QLinkLabel(f"Winget: MIT License: https://github.com/microsoft/winget-cli/blob/master/LICENSE"))
+ self.layout.addWidget(QLinkLabel(f"Winget: {('MIT License')}: https://github.com/microsoft/winget-cli/blob/master/LICENSE"))
self.layout.addWidget(QLinkLabel(f"Scoop: Unlicense: https://github.com/lukesampson/scoop/blob/master/LICENSE"))
- self.layout.addWidget(QLinkLabel(f"GSudo: MIT License: https://github.com/gerardog/gsudo/blob/master/LICENSE.txt"))
+ self.layout.addWidget(QLinkLabel(f"GSudo: {('MIT License')}: https://github.com/gerardog/gsudo/blob/master/LICENSE.txt"))
self.layout.addWidget(QLinkLabel())
- self.layout.addWidget(QLinkLabel(f"Icons: By Icons8: https://icons8.com"))
+ self.layout.addWidget(QLinkLabel(f"{('Icons')}: {('By Icons8')}: https://icons8.com"))
self.layout.addWidget(QLinkLabel())
self.layout.addWidget(QLinkLabel())
- button = QPushButton("About Qt")
+ button = QPushButton(_("About Qt6"))
button.setFixedWidth(710)
button.setFixedHeight(25)
- button.clicked.connect(lambda: MessageBox.aboutQt(self, "WingetUI: About Qt"))
+ button.clicked.connect(lambda: MessageBox.aboutQt(self, _("WingetUI - About Qt6")))
self.layout.addWidget(button)
self.layout.addWidget(QLinkLabel())
self.layout.addStretch()
@@ -1746,27 +1747,109 @@ def __init__(self, parent = None):
self.announcements = QAnnouncements()
self.announcements.setMinimumWidth(800)
self.layout.addWidget(self.announcements)
- title = QLabel("WingetUI Settings")
+ title = QLabel(_("WingetUI Settings"))
+
title.setStyleSheet(f"font-size: 40px;font-family: \"Segoe UI Variable Display\";font-weight: bold;")
self.layout.addWidget(title)
self.layout.addSpacing(20)
- subtitle = QLabel("General preferences")
+ subtitle = QLabel(_("General preferences"))
subtitle.setStyleSheet(f"font-size: 25px;font-family: \"Segoe UI Variable Display\";font-weight: bold;")
self.layout.addWidget(subtitle)
self.layout.addWidget(QLabel())
- themeTextLabel = QLabel("Application theme:")
+ selectedLanguageLabel = QLabel(_("WingetUI display language:")+" (Language)") # The non-translated (Language) string is there to let people know what the language option is if you accidentaly change the language
+ selectedLanguageCombo = QComboBox()
+ selectedLanguageButton = QPushButton()
+ selectedLanguageButton.setObjectName("AccentButton")
+ selectedLanguageCombo.setFixedWidth(200)
+ selectedLanguageButton.setFixedWidth(200)
+ selectedLanguageButton.setFixedHeight(30)
+ selectedLanguageButton.setVisible(False)
+ selectedLanguageButton.setText(_("Restart WingetUI")+" (Restart)")
+
+ langListWithPercentage = []
+ langDictWithPercentage = {}
+ invertedLangDict = {}
+ for key, value in languageReference.items():
+ if (key in untranslatedPercentage):
+ perc = untranslatedPercentage[key]
+ if (perc == "0%"): continue
+ if not key in lang["locale"]:
+ langListWithPercentage.append(f"{value} ({perc})")
+ langDictWithPercentage[key] = f"{value} ({perc})"
+ invertedLangDict[f"{value} ({perc})"] = key
+ else:
+ k = len(lang.keys())
+ v = len([val for val in lang.values() if val != None])
+ perc = f"{int(v/k*100)}%"
+ langListWithPercentage.append(f"{value} ({perc})")
+ langDictWithPercentage[key] = f"{value} ({perc})"
+ invertedLangDict[f"{value} ({perc})"] = key
+ else:
+ invertedLangDict[value] = key
+ langDictWithPercentage[key] = value
+ langListWithPercentage.append(value)
+ try:
+ cprint(invertedLangDict)
+ selectedLanguageCombo.insertItems(0, langListWithPercentage)
+ selectedLanguageCombo.setCurrentIndex(langListWithPercentage.index(langDictWithPercentage[langName]))
+ except Exception as e:
+ report(e)
+ selectedLanguageCombo.insertItems(0, langListWithPercentage)
+
+ def changeLang():
+ selectedLanguageButton.setVisible(True)
+ i = selectedLanguageCombo.currentIndex()
+ selectedLang = invertedLangDict[selectedLanguageCombo.currentText()] # list(languageReference.keys())[i]
+ cprint(invertedLangDict[selectedLanguageCombo.currentText()])
+ setSettingsValue("PreferredLanguage", selectedLang)
+
+ def restartElevenClockByLangChange():
+ subprocess.run(str("start /B \"\" \""+sys.executable)+"\"", shell=True)
+ globals.app.quit()
+
+ selectedLanguageButton.clicked.connect(restartElevenClockByLangChange)
+ selectedLanguageCombo.currentTextChanged.connect(changeLang)
+
+ hl = QHBoxLayout()
+ hl.setContentsMargins(0, 0, 0, 0)
+ hl.addWidget(selectedLanguageLabel)
+ hl.addSpacing(20)
+ hl.addWidget(selectedLanguageCombo)
+ hl.addWidget(selectedLanguageButton)
+ hl.addStretch()
+ self.layout.addLayout(hl)
+
+ updateCheckBox = QCheckBox(_("Update WingetUI automatically"))
+ updateCheckBox.setChecked(not getSettings("DisableAutoUpdateWingetUI"))
+ updateCheckBox.clicked.connect(lambda v: setSettings("DisableAutoUpdateWingetUI", not bool(v)))
+ self.layout.addWidget(updateCheckBox)
+ changeDefaultInstallAction = QCheckBox(_("Directly install when double-clicking an item on the Discover Software tab (instead of showing the package info)"))
+ changeDefaultInstallAction.setChecked(getSettings("InstallOnDoubleClick"))
+ changeDefaultInstallAction.clicked.connect(lambda v: setSettings("InstallOnDoubleClick", bool(v)))
+ self.layout.addWidget(changeDefaultInstallAction)
+ changeDefaultUpdateAction = QCheckBox(_("Show info about the package on the Updates tab"))
+ changeDefaultUpdateAction.setChecked(not getSettings("DoNotUpdateOnDoubleClick"))
+ changeDefaultUpdateAction.clicked.connect(lambda v: setSettings("DoNotUpdateOnDoubleClick", bool(not v)))
+ self.layout.addWidget(changeDefaultUpdateAction)
+ dontUseBuiltInGsudo = QCheckBox(_("Use installed GSudo instead of the bundled one (requires app restart)"))
+ dontUseBuiltInGsudo.setChecked(getSettings("UseUserGSudo"))
+ dontUseBuiltInGsudo.clicked.connect(lambda v: setSettings("UseUserGSudo", bool(v)))
+ self.layout.addWidget(dontUseBuiltInGsudo)
+
+
+ themeTextLabel = QLabel(_("Application theme:"))
themes = {
- "Light": "light",
- "Dark": "dark",
- "Follow system color scheme": "auto"
+ _("Light"): "light",
+ _("Dark"): "dark",
+ _("Follow system color scheme"): "auto"
}
invertedThemes = {
- "light" : "Light",
- "dark" : "Dark",
- "auto" : "Follow system color scheme"
+ "light" : _("Light"),
+ "dark" : _("Dark"),
+ "auto" : _("Follow system color scheme")
}
themeText = CustomComboBox()
@@ -1776,7 +1859,7 @@ def __init__(self, parent = None):
try:
themeText.setCurrentText(invertedThemes[currentValue])
except KeyError:
- themeText.setCurrentText("Follow system color scheme")
+ themeText.setCurrentText(_("Follow system color scheme"))
except Exception as e:
report(e)
@@ -1789,73 +1872,56 @@ def __init__(self, parent = None):
hl.addWidget(themeText)
hl.addStretch()
-
self.layout.addLayout(hl)
- updateCheckBox = QCheckBox("Update WingetUI automatically")
- updateCheckBox.setChecked(not getSettings("DisableAutoUpdateWingetUI"))
- updateCheckBox.clicked.connect(lambda v: setSettings("DisableAutoUpdateWingetUI", not bool(v)))
- self.layout.addWidget(updateCheckBox)
- changeDefaultInstallAction = QCheckBox("Directly install when double-clicking an item on the Discover Packages tab (instead of showing the package info)")
- changeDefaultInstallAction.setChecked(getSettings("InstallOnDoubleClick"))
- changeDefaultInstallAction.clicked.connect(lambda v: setSettings("InstallOnDoubleClick", bool(v)))
- self.layout.addWidget(changeDefaultInstallAction)
- changeDefaultUpdateAction = QCheckBox("Show info about the package on the Software Updates tab")
- changeDefaultUpdateAction.setChecked(not getSettings("DoNotUpdateOnDoubleClick"))
- changeDefaultUpdateAction.clicked.connect(lambda v: setSettings("DoNotUpdateOnDoubleClick", bool(not v)))
- self.layout.addWidget(changeDefaultUpdateAction)
- dontUseBuiltInGsudo = QCheckBox("Use installed GSudo instead of the bundled one (requires app restart)")
- dontUseBuiltInGsudo.setChecked(getSettings("UseUserGSudo"))
- dontUseBuiltInGsudo.clicked.connect(lambda v: setSettings("UseUserGSudo", bool(v)))
- self.layout.addWidget(dontUseBuiltInGsudo)
self.layout.addWidget(QLabel())
- subtitle = QLabel("Startup options")
+ subtitle = QLabel(_("Startup options"))
subtitle.setStyleSheet(f"font-size: 25px;font-family: \"Segoe UI Variable Display\";font-weight: bold;")
self.layout.addWidget(subtitle)
- doCloseWingetUI = QCheckBox("Close WingetUI to the notification area")
+ doCloseWingetUI = QCheckBox(_("Close WingetUI to the notification area"))
doCloseWingetUI.setChecked(not getSettings("DisablesystemTray"))
doCloseWingetUI.clicked.connect(lambda v: setSettings("DisablesystemTray", not bool(v)))
self.layout.addWidget(doCloseWingetUI)
- doCloseWingetUI = QCheckBox("Autostart WingetUI in the notifications area")
+ doCloseWingetUI = QCheckBox(_("Autostart WingetUI in the notifications area"))
doCloseWingetUI.setChecked(not getSettings("DisableAutostart"))
doCloseWingetUI.clicked.connect(lambda v: setSettings("DisableAutostart", not bool(v)))
self.layout.addWidget(doCloseWingetUI)
- disableUpdateIndexes = QCheckBox("Do not update package indexes on launch")
+ disableUpdateIndexes = QCheckBox(_("Do not update package indexes on launch"))
disableUpdateIndexes.setChecked(getSettings("DisableUpdateIndexes"))
disableUpdateIndexes.clicked.connect(lambda v: setSettings("DisableUpdateIndexes", bool(v)))
self.layout.addWidget(disableUpdateIndexes)
- enableScoopCleanup = QCheckBox("Enable Scoop cleanup on launch")
+ enableScoopCleanup = QCheckBox(_("Enable Scoop cleanup on launch"))
enableScoopCleanup.setChecked(getSettings("EnableScoopCleanup"))
enableScoopCleanup.clicked.connect(lambda v: setSettings("EnableScoopCleanup", bool(v)))
self.layout.addWidget(enableScoopCleanup)
self.layout.addWidget(QLabel())
- subtitle = QLabel("Notification tray options")
+ subtitle = QLabel(_("Notification tray options"))
subtitle.setStyleSheet(f"font-size: 25px;font-family: \"Segoe UI Variable Display\";font-weight: bold;")
self.layout.addWidget(subtitle)
- checkForUpdates = QCheckBox("Check for updates periodically")
+ checkForUpdates = QCheckBox(_("Check for updates periodically"))
checkForUpdates.setChecked(not getSettings("DisableAutoCheckforUpdates"))
checkForUpdates.clicked.connect(lambda v: setSettings("DisableAutoCheckforUpdates", not bool(v)))
self.layout.addWidget(checkForUpdates)
- updatesFrequencyText = QLabel("Check for updates every:")
+ updatesFrequencyText = QLabel(_("Check for updates every:"))
times = {
- "30 minutes": "1800",
- "1 hour": "3600",
- "2 hours": "7200",
- "4 hours": "14400",
- "8 hours": "28800",
+ _("30 minutes"): "1800",
+ _("1 hour"): "3600",
+ _("2 hours"): "7200",
+ _("4 hours"): "14400",
+ _("8 hours"): "28800",
}
invertedTimes = {
- "1800" : "30 minutes",
- "3600" : "1 hour",
- "7200" : "2 hours",
- "14400": "4 hours",
- "28800": "8 hours",
+ "1800" : _("30 minutes"),
+ "3600" : _("1 hour"),
+ "7200" : _("2 hours"),
+ "14400": _("4 hours"),
+ "28800": _("8 hours"),
}
updatesFrequency = CustomComboBox()
@@ -1864,7 +1930,7 @@ def __init__(self, parent = None):
try:
updatesFrequency.setCurrentText(invertedTimes[currentValue])
except KeyError:
- updatesFrequency.setCurrentText("1 hour")
+ updatesFrequency.setCurrentText(_("1 hour"))
except Exception as e:
report(e)
@@ -1879,30 +1945,30 @@ def __init__(self, parent = None):
self.layout.addLayout(hl)
- notifyAboutUpdates = QCheckBox("Show a notification when there are available updates")
+ notifyAboutUpdates = QCheckBox(_("Show a notification when there are available updates"))
notifyAboutUpdates.setChecked(not getSettings("DisableUpdatesNotifications"))
notifyAboutUpdates.clicked.connect(lambda v: setSettings("DisableUpdatesNotifications", not bool(v)))
self.layout.addWidget(notifyAboutUpdates)
self.layout.addWidget(QLabel())
- subtitle = QLabel("Package manager preferences")
+ subtitle = QLabel(_("Package managers preferences"))
subtitle.setStyleSheet(f"font-size: 25px;font-family: \"Segoe UI Variable Display\";font-weight: bold;")
self.layout.addWidget(subtitle)
- parallelInstalls = QCheckBox("Allow parallel installs (NOT RECOMMENDED)")
+ parallelInstalls = QCheckBox(_("Allow parallel installs (NOT RECOMMENDED)"))
parallelInstalls.setChecked(getSettings("AllowParallelInstalls"))
parallelInstalls.clicked.connect(lambda v: setSettings("AllowParallelInstalls", bool(v)))
self.layout.addWidget(parallelInstalls)
- disableWinget = QCheckBox("Disable Winget")
+ disableWinget = QCheckBox(_("Disable Winget"))
disableWinget.setChecked(getSettings("DisableWinget"))
disableWinget.clicked.connect(lambda v: setSettings("DisableWinget", bool(v)))
self.layout.addWidget(disableWinget)
- disableScoop = QCheckBox("Disable Scoop")
+ disableScoop = QCheckBox(_("Disable Scoop"))
disableScoop.setChecked(getSettings("DisableScoop"))
disableScoop.clicked.connect(lambda v: setSettings("DisableScoop", bool(v)))
self.layout.addWidget(disableScoop)
- scoopPreventCaps = QCheckBox("Show Scoop apps as lowercase")
+ scoopPreventCaps = QCheckBox(_("Show Scoop apps as lowercase"))
scoopPreventCaps.setChecked(getSettings("LowercaseScoopApps"))
scoopPreventCaps.clicked.connect(lambda v: setSettings("LowercaseScoopApps", bool(v)))
self.layout.addWidget(scoopPreventCaps)
@@ -1912,17 +1978,18 @@ def __init__(self, parent = None):
self.layout.addWidget(QLabel())
l = QHBoxLayout()
+ button = QPushButton(_("Add a bucket to Scoop"))
button = QPushButton("Add a bucket to Scoop")
#button.setFixedWidth(350)
button.setFixedHeight(30)
button.clicked.connect(lambda: self.scoopAddExtraBucket())
l.addWidget(button)
- button = QPushButton("Remove a bucket from Scoop")
+ button = QPushButton(_("Remove a bucket from Scoop"))
#button.setFixedWidth(350)
button.setFixedHeight(30)
button.clicked.connect(lambda: self.scoopRemoveExtraBucket())
l.addWidget(button)
- button = QPushButton("Install Scoop")
+ button = QPushButton(_("Install Scoop"))
#button.setFixedWidth(350)
button.setFixedHeight(30)
button.clicked.connect(lambda: (setSettings("DisableScoop", False), disableScoop.setChecked(False), os.startfile(os.path.join(realpath, "resources/install_scoop.cmd"))))
@@ -1934,13 +2001,13 @@ def __init__(self, parent = None):
print("🟢 Settings tab loaded!")
def scoopAddExtraBucket(self) -> None:
- r = QInputDialog.getItem(self, "Scoop bucket manager", "What bucket do you want to add", ["main", "extras", "versions", "nirsoft", "php", "nerd-fonts", "nonportable", "java", "games"], 1, editable=False)
+ r = QInputDialog.getItem(self, _("Scoop bucket manager"), _("What bucket do you want to add"), ["main", "extras", "versions", "nirsoft", "php", "nerd-fonts", "nonportable", "java", "games"], 1, editable=False)
if r[1]:
print(r[0])
globals.installersWidget.addItem(PackageInstallerWidget(f"{r[0]} scoop bucket", "custom", customCommand=f"scoop bucket add {r[0]}"))
def scoopRemoveExtraBucket(self) -> None:
- r = QInputDialog.getItem(self, "Scoop bucket manager", "What bucket do you want to remove", ["main", "extras", "versions", "nirsoft", "php", "nerd-fonts", "nonportable", "java", "games"], 1, editable=False)
+ r = QInputDialog.getItem(self, _("Scoop bucket manager"), _("What bucket do you want to remove"), ["main", "extras", "versions", "nirsoft", "php", "nerd-fonts", "nonportable", "java", "games"], 1, editable=False)
if r[1]:
print(r[0])
globals.installersWidget.addItem(PackageInstallerWidget(f"{r[0]} scoop bucket", "custom", customCommand=f"scoop bucket rm {r[0]}"))
@@ -1961,17 +2028,24 @@ def contextMenuEvent(self, e: QContextMenuEvent) -> None:
menu.addSeparator()
a = QAction()
- a.setText(("Reload log"))
- a.triggered.connect(lambda: self.textEdit.setPlainText(buffer.getvalue()))
+ a.setText(_("Reload log"))
+ a.triggered.connect(lambda: self.setPlainText(buffer.getvalue()))
menu.addAction(a)
+
+ a4 = QAction()
+ a4.setText(_("Show missing translation strings"))
+ a4.triggered.connect(lambda: self.setPlainText('\n'.join(missingTranslationList)))#buffer.getvalue()))
+ menu.addAction(a4)
+
+
a2 = QAction()
- a2.setText(("Export log as a file"))
+ a2.setText(_("Export log as a file"))
a2.triggered.connect(lambda: saveLog())
menu.addAction(a2)
a3 = QAction()
- a3.setText(("Copy log to clipboard"))
+ a3.setText(_("Copy log to clipboard"))
a3.triggered.connect(lambda: copyLog())
menu.addAction(a3)
@@ -1992,14 +2066,14 @@ def contextMenuEvent(self, e: QContextMenuEvent) -> None:
self.textEdit.setPlainText(buffer.getvalue())
- reloadButton = QPushButton(("Reload log"))
+ reloadButton = QPushButton(_("Reload log"))
reloadButton.setFixedWidth(200)
reloadButton.clicked.connect(lambda: self.textEdit.setPlainText(buffer.getvalue()))
def saveLog():
try:
print("🔵 Saving log...")
- f = QFileDialog.getSaveFileName(self, "Save log", os.path.expanduser("~"), "Text file (.txt)")
+ f = QFileDialog.getSaveFileName(self, _("Export log"), os.path.expanduser("~"), f"{_('Text file')} (.txt)")
if f[0]:
fpath = f[0]
if not ".txt" in fpath.lower():
@@ -2017,7 +2091,7 @@ def saveLog():
report(e)
self.textEdit.setPlainText(buffer.getvalue())
- exportButtom = QPushButton(("Export log as a file"))
+ exportButtom = QPushButton(_("Export log as a file"))
exportButtom.setFixedWidth(200)
exportButtom.clicked.connect(lambda: saveLog())
@@ -2031,7 +2105,7 @@ def copyLog():
report(e)
self.textEdit.setPlainText(buffer.getvalue())
- copyButton = QPushButton(("Copy log to clipboard"))
+ copyButton = QPushButton(_("Copy log to clipboard"))
copyButton.setFixedWidth(200)
copyButton.clicked.connect(lambda: copyLog())