Compare commits

..

2 Commits

Author SHA1 Message Date
discollizard
a13ac6a0db added resources exhausted check to timeout 2024-06-24 00:29:22 -03:00
discollizard
68205a9aac basic infinite scroll added to catalogue page 2024-06-24 00:25:27 -03:00
245 changed files with 4026 additions and 11856 deletions

View File

@@ -1,4 +1,3 @@
MAIN_VITE_STEAMGRIDDB_API_KEY=YOUR_API_KEY MAIN_VITE_STEAMGRIDDB_API_KEY=YOUR_API_KEY
MAIN_VITE_API_URL=API_URL MAIN_VITE_API_URL=API_URL
MAIN_VITE_SENTRY_DSN=YOUR_SENTRY_DSN
SENTRY_AUTH_TOKEN=

View File

@@ -2,4 +2,3 @@ node_modules
dist dist
out out
.gitignore .gitignore
migration.stub

View File

@@ -27,7 +27,7 @@ body:
label: Expected behavior label: Expected behavior
description: A clear and concise description of what you expected to happen. description: A clear and concise description of what you expected to happen.
validations: validations:
required: false required: true
- type: textarea - type: textarea
id: screenshots id: screenshots
attributes: attributes:
@@ -56,12 +56,3 @@ body:
description: Please provide any additional information and context about your problem. description: Please provide any additional information and context about your problem.
validations: validations:
required: false required: false
- type: checkboxes
id: terms
attributes:
label: Before opening this Issue
options:
- label: I have searched the issues of this repository and believe that this is not a duplicate.
required: true
- label: I am aware that Hydra team does not offer any support or help regarding the downloaded games.
required: true

View File

@@ -22,36 +22,22 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: yarn run: yarn
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: 3.9
- name: Install dependencies
run: pip install -r requirements.txt
- name: Build with cx_Freeze
run: python torrent-client/setup.py build
- name: Build Linux - name: Build Linux
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
run: | run: yarn build:linux
sudo apt-get update
sudo apt-get install -y libarchive-tools
yarn build:linux
env: env:
MAIN_VITE_ONLINEFIX_USERNAME: ${{ secrets.ONLINEFIX_USERNAME }}
MAIN_VITE_ONLINEFIX_PASSWORD: ${{ secrets.ONLINEFIX_PASSWORD }}
MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_API_URL }} MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_API_URL }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
MAIN_VITE_SENTRY_DSN: ${{ vars.MAIN_VITE_SENTRY_DSN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build Windows - name: Build Windows
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
run: yarn build:win run: yarn build:win
env: env:
MAIN_VITE_ONLINEFIX_USERNAME: ${{ secrets.ONLINEFIX_USERNAME }}
MAIN_VITE_ONLINEFIX_PASSWORD: ${{ secrets.ONLINEFIX_PASSWORD }}
MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_API_URL }} MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_API_URL }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
MAIN_VITE_SENTRY_DSN: ${{ vars.MAIN_VITE_SENTRY_DSN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create artifact - name: Create artifact
@@ -68,4 +54,3 @@ jobs:
dist/*.tar.gz dist/*.tar.gz
dist/*.yml dist/*.yml
dist/*.blockmap dist/*.blockmap
dist/*.pacman

View File

@@ -1,6 +1,6 @@
name: Lint name: Lint
on: pull_request on: [pull_request, push]
jobs: jobs:
lint: lint:

View File

@@ -24,36 +24,22 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: yarn run: yarn
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: 3.9
- name: Install dependencies
run: pip install -r requirements.txt
- name: Build with cx_Freeze
run: python torrent-client/setup.py build
- name: Build Linux - name: Build Linux
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
run: | run: yarn build:linux
sudo apt-get update
sudo apt-get install -y libarchive-tools
yarn build:linux
env: env:
MAIN_VITE_ONLINEFIX_USERNAME: ${{ secrets.ONLINEFIX_USERNAME }}
MAIN_VITE_ONLINEFIX_PASSWORD: ${{ secrets.ONLINEFIX_PASSWORD }}
MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_API_URL }} MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_API_URL }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
MAIN_VITE_SENTRY_DSN: ${{ vars.MAIN_VITE_SENTRY_DSN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build Windows - name: Build Windows
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
run: yarn build:win run: yarn build:win
env: env:
MAIN_VITE_ONLINEFIX_USERNAME: ${{ secrets.ONLINEFIX_USERNAME }}
MAIN_VITE_ONLINEFIX_PASSWORD: ${{ secrets.ONLINEFIX_PASSWORD }}
MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_API_URL }} MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_API_URL }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
MAIN_VITE_SENTRY_DSN: ${{ vars.MAIN_VITE_SENTRY_DSN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Release - name: Release
@@ -71,6 +57,5 @@ jobs:
dist/*.tar.gz dist/*.tar.gz
dist/*.yml dist/*.yml
dist/*.blockmap dist/*.blockmap
dist/*.pacman
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

3
.gitignore vendored
View File

@@ -1,6 +1,6 @@
.vscode .vscode
node_modules node_modules
hydra-download-manager/ aria2/
fastlist.exe fastlist.exe
__pycache__ __pycache__
dist dist
@@ -9,4 +9,3 @@ out
*.log* *.log*
.env .env
.vite .vite
sentry.properties

View File

@@ -20,9 +20,6 @@
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md) [![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md) [![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
[![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md) [![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md)
[![de](https://img.shields.io/badge/lang-de-black)](README.de.md)
[![ita](https://img.shields.io/badge/lang-it-red)](README.it.md)
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
![Hydra Catalogue](./docs/screenshot.png) ![Hydra Catalogue](./docs/screenshot.png)
@@ -30,12 +27,11 @@
## Змест ## Змест
- [Змест](#змест)
- [Апісанне](#апісанне) - [Апісанне](#апісанне)
- [Асаблівасці](#асаблівасці) - [Асаблівасці](#асаблівасці)
- [Усталёўка](#усталёўка) - [Усталёўка](#усталёўка)
- [Уклад](#-уклад) - [Уклад](#contributing)
- [Далучайцеся да нашага Telegram](#-далучайцеся-да-нашага-telegram) - [Далучайцеся да нашага Telegram](#join-our-telegram)
- [Форк і кланаванне рэпазітара](#форк-і-кланаванне-рэпазітара) - [Форк і кланаванне рэпазітара](#форк-і-кланаванне-рэпазітара)
- [Спосабы ўнесці свой уклад](#спосабы-ўнесці-свой-уклад) - [Спосабы ўнесці свой уклад](#спосабы-ўнесці-свой-уклад)
- [Структура праекту](#структура-праекту) - [Структура праекту](#структура-праекту)
@@ -51,7 +47,6 @@
- [Зборка кліента BitTorrent](#зборка-кліента-bittorrent) - [Зборка кліента BitTorrent](#зборка-кліента-bittorrent)
- [Зборка прыкладання Electron](#зборка-прыкладання-electron) - [Зборка прыкладання Electron](#зборка-прыкладання-electron)
- [Удзельнікі](#удзельнікі) - [Удзельнікі](#удзельнікі)
- [Ліцэнзія](#ліцэнзія)
## Апісанне ## Апісанне

View File

@@ -1,185 +0,0 @@
<br>
<div align="center">
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
<h1 align="center">Hydra Launcher</h1>
<p align="center">
<strong>Hydra je herní launcher s vlastním vestavěným Bittorrent klientem.</strong>
</p>
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
[![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md)
[![de](https://img.shields.io/badge/lang-de-black)](README.de.md)
[![ita](https://img.shields.io/badge/lang-it-red)](README.it.md)
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
![Hydra Katalog](./docs/screenshot.png)
</div>
## Seznam obsahu
- [Seznam obsahu](#seznam-obsahu)
- [O projektu](#o-projektu)
- [Funkce](#funkce)
- [Instalace](#instalace)
- [Přispívání](#přispívání)
- [Připoj se na náš telegram](#připoj-se-na-náš-telegram)
- [Vytvořte fork a naklonujte svůj repozitář](#vytvořte-fork-a-naklonujte-svůj-repozitář)
- [Způsoby jak můžete přispět](#způsoby-jak-můžete-přispět)
- [Struktura projektu](#struktura-projektu)
- [Sestavení ze zdroje](#sestavení-ze-zdroje)
- [Instalace Node.js](#instalace-nodejs)
- [Instalace Yarn](#instalace-yarn)
- [Instalace Požadavků pro Node.js](#instalace-požadavků-pro-nodejs)
- [Instalace Pythonu 3.9](#instalace-pythonu-39)
- [Instalace Požadavků pro Python](#instalace-požadavků-pro-python)
- [Proměnné prostředí](#proměnné-prostředí)
- [Spuštění](#spuštění)
- [Sestavení](#sestavení)
- [Sestavení bittorrent klientu](#sestavení-bittorrent-klientu)
- [Sestavení electron aplikace](#sestavení-electron-aplikace)
- [Přispěvatelé](#přispěvatelé)
- [Licence](#licence)
## O projektu
**Hydra** je **Herní Launcher** s jeho vlastním vestavěným **BitTorrent Klientem**.
<br>
Launcher je napsán v TypeScriptu (Electron) a Pythonu, který má na starosti torrentovací systém za pomocí knihovny libtorrent.
## Funkce
- Vlastní vestavěný BitTorrent klient
- How Long To Beat (HLTB) integrace na stránce hry
- Vlastní místa pro uložení hry
- Windows a Linux podpora
- Časté aktualizace
- A další ...
## Instalace
Následuj kroky:
1. Stáhni nejnovější verzi Hydry ze stránky [Vydání](https://github.com/hydralauncher/hydra/releases/latest).
- Stáhni .exe, pokud chceš instalovat Hydru na Windows.
- Stáhni .deb nebo .rpm nebo .zip, pokud chceš instalovat Hydru na Linux. (záleží na tvé Linux distribuci)
2. Spusť stažený instalační soubor.
3. Užívej Hydru!
## <a name="contributing"> Přispívání
### <a name="join-our-telegram"></a> Připoj se na náš telegram
Vedeme diskuzi v našem [Telegramovém](https://t.me/hydralauncher) kanálu.
### Vytvořte fork a naklonujte svůj repozitář
1. Vytvoř fork repozitáře [(klikni sem pro vytvoření forku)](https://github.com/hydralauncher/hydra/fork)
2. Naklonuj kód forku `git clone https://github.com/tvoje_jméno/hydra`
3. Vytvoř nové odvětví (branch)
4. Odešli svoje změny
5. Odešli nový Pull Request
### Způsoby jak můžete přispět
- Překládání: Chceme, aby Hydra byla co nejvíce dostupná. Můžete přispět novým jazykem, nebo úpravou současného!
- Kód: Hydra je postavena na Typescriptu, Electronu a trochou Pythonu. Pokud chceš přispět, připoj se na náš [Telegram](https://t.me/hydralauncher)!
### Struktura projektu
- torrent-client: Používáme libtorrent, Pythonovou knihovnu, pro správu torrent stahování
- src/renderer: uživatelské rozhraní aplikace (UI)
- src/main: celá logika projektu
## Sestavení ze zdroje
### Instalace Node.js
Ujistěte se, že máte Node.js nainstalován na svém zařízení. Pokud ne, stáhněte ho, a nainstalujte z [nodejs.org](https://nodejs.org/).
### Instalace Yarn
Yarn je balíčkový správce pro Node.js. Pokud ještě nemáte yarn, můžete ho stáhnout za pomoci pokynů na [yarnpkg.com](https://classic.yarnpkg.com/lang/en/docs/install/).
### Instalace Požadavků pro Node.js
Jděte do složky projektu, otevřte v ní konzole a nainstalujte požadavky pro Node pomocí Yarn:
```bash
cd hydra
yarn
```
### Instalace Pythonu 3.9
Ujistěte se, že máte Python 3.9 nainstalován na svém zařízení. Můžete ho stáhnout z [python.org](https://www.python.org/downloads/release/python-3913/).
### Instalace Požadavků pro Python
Nainstalujte požadavky pro Python za pomoci pip:
```bash
pip install -r requirements.txt
```
## Proměnné prostředí
Budete potřebovat SteamGridDB API klíč, abyste mohli načítat ikony u her.
Jakmile ho máte, můžete zkopírovat, nebo přejmenovat `.env.example` soubor na `.env` a dát ho do `STEAMGRIDDB_API_KEY`.
## Spuštění
Jakmile máte vše nastaveno, můžete spustit jak Electron proces tak bittorrent client:
```bash
yarn dev
```
## Sestavení
### Sestavení bittorrent klientu
Sestavit bittorrent klient můžete pomocí:
```bash
python torrent-client/setup.py build
```
### Sestavení electron aplikace
Sestavit Electron aplikaci můžete pomocí následujících kroků:
Na Windows:
```bash
yarn build:win
```
Na Linux:
```bash
yarn build:linux
```
## Přispěvatelé
<a href="https://github.com/hydralauncher/hydra/graphs/contributors">
<img src="https://contrib.rocks/image?repo=hydralauncher/hydra" />
</a>
## Licence
Hydra je licencována pod [MIT Licencí](LICENSE).

View File

@@ -1,183 +0,0 @@
<br>
<div align="center">
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
<h1 align="center">Hydra Launcher</h1>
<p align="center">
<strong>Hydra ist ein Launcher für Spiele mit einem eigenen eingebetteten BitTorrent-Client.</strong>
</p>
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
[![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md)
[![de](https://img.shields.io/badge/lang-de-black)](README.de.md)
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
![Hydra Katalog](./docs/screenshot.png)
</div>
## Inhaltsverzeichnis
- [Über Hydra](#über-hydra)
- [Eigenschaften](#eigenschaften)
- [Installation](#installation)
- [Mitwirken](#mitwirken)
- [Tritt uns auf Telegram bei](#tritt-uns-auf-telegram-bei)
- [Forke und klone dein Repo](#forke-und-klone-dein-repo)
- [Wie du mitwirken kannst](#wie-du-mitwirken-kannst)
- [Projektstruktur](#projektstruktur)
- [Den Quellcode kompilieren](#den-quellcode-kompilieren)
- [Installiere Node.js](#installiere-nodejs)
- [Installiere Yarn](#installiere-yarn)
- [Installiere Node-Abhängigkeiten](#installiere-node-abhängigkeiten)
- [Installiere Python 3.9](#installiere-python-39)
- [Installiere Python-Abhängigkeiten](#installiere-python-abhängigkeiten)
- [Umgebungsvariablen](#umgebungsvariablen)
- [Ausführung](#ausführung)
- [Kompilation](#kompilation)
- [Kompiliere den BitTorrent-Client](#kompiliere-den-bittorrent-client)
- [Kompiliere die Electron-Applikation](#kompiliere-die-electron-applikation)
- [Mitwirkende](#mitwirkende)
## Über Hydra
**Hydra** ist ein **Launcher für Spiele** mit einem eigenen eingebetteten **BitTorrent-Client**.
<br>
Der Launcher ist in TypeScript (Electron) und Python, womit das Torrentingsystem durch Einsatz von libtorrent geregelt ist, geschrieben.
## Eigenschaften
- Eigener eingebetteter BitTorrent-Client
- How Long to Beat (HLTB) Integration auf der Spielseite
- Anpassbarkeit des Downloadverzeichnisses
- Unterstützung von Windows und Linux
- Regelmäßig aktualisiert
- Und mehr ...
## Installation
Die folgenden Schritte beschreiben den Installationsprozess:
1. Lade die neueste Version von Hydra von der [Releases](https://github.com/hydralauncher/hydra/releases/latest) Seite herunter.
- Für die Installation von Hydra auf Windows, wähle die .exe Datei.
- Für die Installation von Hydra auf Linux, wähle die .deb, .rpm oder .zip Datei. (Abhängig von deiner Linux-Distribution)
2. Führe die heruntergeladene Datei aus.
3. Genieße Hydra!
## Mitwirken
### Tritt uns auf Telegram bei
Wir konzentrieren unsere Diskussionen in unserem [Telegram](https://t.me/hydralauncher) Kanal.
### Forke und klone dein Repo
1. Forke das Repo [(Klicke hier, um direkt zu forken)](https://github.com/hydralauncher/hydra/fork)
2. Klone deinen geforketen Code `git clone https://github.com/dein_nutzername/hydra`
3. Erstelle einen neuen Branch
4. Pushe deine Commits
5. Stelle eine neue Pull-Anfrage
### Wie du mitwirken kannst
- Übersetzung: Wir wollen Hydra so vielen Menschen wie möglich zugänglich machen. Gerne kannst du uns helfen neue Sprachen zu übersetzen oder für Hydra bereits verfügbare Sprachen zu aktualisieren und verbessern.
- Code: Hydra ist mit TypeScript, Electron und etwas Python gebaut. Wenn du mitwirken möchtest, tritt unserem [Telegram](https://t.me/hydralauncher) bei!
### Projektstruktur
- torrent-client: Wir verwenden die Python-Bibliothek libtorrent zur Verwaltung von Torrent-Downloads.
- src/renderer: die UI der Applikation.
- src/main: sämtliche Logik liegt hier.
## Den Quellcode kompilieren
### Installiere Node.js
Stelle sicher, dass du Node.js auf deinem System installiert hast. Falls nicht, installiere es von [nodejs.org](https://nodejs.org/).
### Installiere Yarn
Yarn ist ein Packetmanager für Node.js. Sollte er dir fehlen, installiere ihn mithilfe der Anleitung auf [yarnpkg.com](https://classic.yarnpkg.com/lang/en/docs/install/).
### Installiere Node-Abhängigkeiten
Navigiere zum Projektverzeichnis und installiere die Node-Abhängigkeiten mit Yarn:
```bash
cd hydra
yarn
```
### Installiere Python 3.9
Stelle sicher, dass du Python 3.9 auf deinem System installiert hast. Ansonsten kannst du es von [python.org](https://www.python.org/downloads/release/python-3913/) herunterladen und installieren.
### Installiere Python-Abhängigkeiten
Installiere die benötigten Python-Abhängigkeiten mit pip:
```bash
pip install -r requirements.txt
```
## Umgebungsvariablen
Du wirst einen SteamGridDB API Schlüssel benötigen, um die Spielicons bei Installation abzurufen.
Sobald du einen hast, kannst du die .env.example Datei zu .env kopieren oder umbenennen und den Schlüssel bei STEAMGRIDDB_API_KEY einfügen.
## Ausführung
Sobald du alles eingerichtet hast, kannst du den folgenden Befehl nutzen, um sowohl den Electron-Prozess als auch den BitTorrent-Client zu starten:
```bash
yarn dev
```
## Kompilation
### Kompiliere den BitTorrent-Client
Kompiliere den BitTorrent-Client mit folgendem Befehl:
```bash
python torrent-client/setup.py build
```
### Kompiliere die Electron-Applikation
Kompiliere die Electron-Applikation mit folgendem Befehl:
Auf Windows:
```bash
yarn build:win
```
Auf Linux:
```bash
yarn build:linux
```
## Mitwirkende
<a href="https://github.com/hydralauncher/hydra/graphs/contributors">
<img src="https://contrib.rocks/image?repo=hydralauncher/hydra" />
</a>
## Lizenz
Hydra ist unter der [MIT Lizenz](LICENSE) lizensiert.

View File

@@ -13,16 +13,13 @@
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions) [![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases) [![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md) [![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md) [![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md) [![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md) [![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
[![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md) [![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md)
[![de](https://img.shields.io/badge/lang-de-black)](README.de.md)
[![ita](https://img.shields.io/badge/lang-it-red)](README.it.md)
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
![Hydra Catalogue](./docs/screenshot.png) ![Hydra Catalogue](./docs/screenshot.png)
@@ -30,12 +27,11 @@
## Tabla de Contenidos ## Tabla de Contenidos
- [Tabla de Contenidos](#tabla-de-contenidos)
- [Acerca de](#acerca-de) - [Acerca de](#acerca-de)
- [Caracteristicas](#caracteristicas) - [Características](#caracteristicas)
- [Instalacion](#instalacion) - [Instalación](#Instalacion)
- [Contribuir](#-contribuir) - [Contribuir](#contribuir)
- [Unete a nuestro Telegram](#-unete-a-nuestro-telegram) - [Únete a nuestro Telegram](#unete-a-nuestro-telegram)
- [Haz un fork y clona tu repositorio](#haz-un-fork-y-clona-tu-repositorio) - [Haz un fork y clona tu repositorio](#haz-un-fork-y-clona-tu-repositorio)
- [Maneras en las que puedes contribuir](#maneras-en-las-que-puedes-contribuir) - [Maneras en las que puedes contribuir](#maneras-en-las-que-puedes-contribuir)
- [Estructura del proyecto](#estructura-del-proyecto) - [Estructura del proyecto](#estructura-del-proyecto)
@@ -44,14 +40,13 @@
- [Instalar Yarn](#instalar-yarn) - [Instalar Yarn](#instalar-yarn)
- [Instalar Dependencias de Node](#instalar-dependencias-de-node) - [Instalar Dependencias de Node](#instalar-dependencias-de-node)
- [Instalar Python 3.9](#instalar-python-39) - [Instalar Python 3.9](#instalar-python-39)
- [Instalar Dependencias de Python](#instalar-dependencias-de-python) - [Instalar Dependencias de Python](#Instalar-dependencias-de-python)
- [Variables del Entorno](#variables-del-entorno) - [Variables del Entorno](#variables-del-entorno)
- [Ejecucion](#ejecucion) - [Ejecución](#ejecucion)
- [Compilacion](#compilacion) - [Compilación](#compilacion)
- [Compilar el cliente de bittorrent](#compilar-el-cliente-de-bittorrent) - [Compilar el cliente de bittorrent](#compilar-el-cliente-de-bittorrent)
- [Compilar la aplicacion Electron](#compilar-la-aplicacion-electron) - [Compilar la aplicación Electron](#compilar-la-aplicacion-electron)
- [Colaboradores](#colaboradores) - [Colaboradores](#colaboradores)
- [Licencia](#licencia)
## Acerca de ## Acerca de
@@ -88,7 +83,7 @@ Puedes unirte a nuestra conversación y discusiones en nuestro canal de [Telegra
### Haz un fork y clona tu repositorio ### Haz un fork y clona tu repositorio
1. Realiza un fork del repositorio [(Haz click acá para hacer un fork ahora)](https://github.com/hydralauncher/hydra/fork) 1. Rea;iza un fork del repositorio [(Haz click acá para hacer un fork ahora)](https://github.com/hydralauncher/hydra/fork)
2. Clona el código forkeado `git clone https://github.com/tu_nombredeusuario/hydra` 2. Clona el código forkeado `git clone https://github.com/tu_nombredeusuario/hydra`
3. Crea una nueva rama 3. Crea una nueva rama
4. Sube tus commits 4. Sube tus commits

View File

@@ -13,16 +13,13 @@
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions) [![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases) [![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md) [![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md) [![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md) [![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md) [![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
[![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md)
[![de](https://img.shields.io/badge/lang-de-black)](README.de.md)
[![ita](https://img.shields.io/badge/lang-it-red)](README.it.md)
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
![Catalogue Hydra](./docs/screenshot.png) ![Catalogue Hydra](./docs/screenshot.png)
@@ -30,7 +27,6 @@
## Table des Matières ## Table des Matières
- [Table des Matières](#table-des-matières)
- [À propos](#à-propos) - [À propos](#à-propos)
- [Fonctionnalités](#fonctionnalités) - [Fonctionnalités](#fonctionnalités)
- [Installation](#installation) - [Installation](#installation)
@@ -51,7 +47,6 @@
- [Compiler le client bittorrent](#compiler-le-client-bittorrent) - [Compiler le client bittorrent](#compiler-le-client-bittorrent)
- [Compiler l'application Electron](#compiler-lapplication-electron) - [Compiler l'application Electron](#compiler-lapplication-electron)
- [Contributeurs](#contributeurs) - [Contributeurs](#contributeurs)
- [License](#license)
## À propos ## À propos

View File

@@ -1,188 +0,0 @@
<br>
<div align="center">
[<img src="./resources/icon.png" width="144"/>](https://hydralauncher.site)
<h1 align="center">Hydra Launcher</h1>
<p align="center">
<strong>Hydra è un game launcher con il proprio client bittorrent e autogestore di repacks.</strong>
</p>
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
[![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md)
[![de](https://img.shields.io/badge/lang-de-black)](README.de.md)
[![ita](https://img.shields.io/badge/lang-it-red)](README.it.md)
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
![Hydra Catalogue](./docs/screenshot.png)
</div>
## Table of Contents
- [Table of Contents](#table-of-contents)
- [A proposito](#a-proposito)
- [Caratteristiche](#caratteristiche)
- [Installazione](#installazione)
- [Contribuire](#-contribuire)
- [Unisciti su Telegram](#-unisciti-su-telegram)
- [Forka e Clona la repository](#forka-e-clona-la-repository)
- [Modi in cui contribuire](#modi-in-cui-contribuire)
- [Struttura del Progetto](#struttura-del-progetto)
- [Compilazione](#compilazione)
- [Installa Node.js](#installa-nodejs)
- [Installa Yarn](#installa-yarn)
- [Installa le dipendenze Node](#installa-le-dipendenze-node)
- [Installa Python 3.9](#installa-python-39)
- [Installa le Dipendenze Python](#installa-le-dipendenze-python)
- [Variabili d'ambiente](#variabili-dambiente)
- [Esecuzione](#esecuzione)
- [Compilazione](#compilazione-1)
- [Compila il bittorrent](#compila-il-bittorrent)
- [Compila l'applicazione Electron](#compila-lapplicazione-electron)
- [Collaboratori](#collaboratori)
- [Licenza](#licenza)
## A proposito
**Hydra** è un **Game Launcher** con il proprio **Client BitTorrent** e **autogestore di repack**.
<br>
Il launcher è scritto in TypeScript (Electron) and Python, che gestisce il sistema di torrenting appoggiandosi a libtorrent.
## Caratteristiche
- Motore di ricerca automatizzato sulle fonti di repack dal [Megathread]("https://www.reddit.com/r/Piracy/wiki/megathread/")
- Client Bittorrent integrato
- Integrazione How Long To Beat (HLTB) nella pagina del gioco
- Percorso del download Personalizzato
- Notifiche di aggiornamenti sulla list dei repacks
- Supporto Windows e Linux
- Costantemente Aggiornato
- E molto altro ...
## Installazione
Segui i seguenti passi:
1. Scarica l'ultima versione di Hydra dalla pagina [Releases](https://github.com/hydralauncher/hydra/releases/latest).
- Scarica solo il file .exe per installare Hydra su Windows.
- Scarica il file .deb o .rpm o .zip per Linux. (Dipende dalla tua distro Linux)
2. Esegui il file scaricato.
3. Goditi Hydra!
## <a name="contribuire"> Contribuire
### <a name="unisciti-su-telegram"></a> Unisciti su Telegram
Puoi unirti alle nostre conversazioni sul canale [Telegram](https://t.me/hydralauncher).
### Forka e Clona la repository
1. Forka la repository [(clicca qui per forkare)](https://github.com/hydralauncher/hydra/fork)
2. Clona il tuo codice forkato `git clone https://github.com/your_username/hydra`
3. Crea un nuovo branch
4. Aggiungi le modifiche (push)
5. Invia la richiesta di pull
### Modi in cui contribuire
- Traduzione: Vogliamo rendere Hydra disponibile a più persone possibile. Sentiti libero di tradurre in altre lingue o aggiornare e migliorare quelle già disponibili su Hydra.
- Programmazione: Hydra è programmato in TypeScript, Electron e un po' di Python. Se intendi contribuire unisciti al nostro [Telegram](https://t.me/hydralauncher)!
### Struttura del Progetto
- client-torrent: Usiamo libtorrent, una libreria Python, per gestire i download dei torrent
- src/renderer: l'UI dell'applicazione
- src/main: tutta la logica qui.
## Compilazione
### Installa Node.js
Assicurati di avere Node.js installato sulla tua macchina. Scaricalo e installalo da [nodejs.org](https://nodejs.org/).
### Installa Yarn
Yarn è un gestore di pacchetti per Node.js. Se non hai ancora installato Yarn segui le istruzioni su [yarnpkg.com](https://classic.yarnpkg.com/lang/en/docs/install/).
### Installa le dipendenze Node
Naviga alla cartella del progetto e installa le dipendenze Node con Yarn:
```bash
cd hydra
yarn
```
### Installa Python 3.9
Assicurati di avere Python 3.9 installato. Puoi scaricarlo da [python.org](https://www.python.org/downloads/release/python-3913/).
### Installa le Dipendenze Python
Installa le dipendenze con pip:
```bash
pip install -r requirements.txt
```
## Variabili d'ambiente
Avrai bisogno di una chiave API SteamGridDB per poter caricare le icone di gioco.
Se intendi avere onlinefix come repacker dovrai aggiungere le tue credenziali al file .env
Una volta ottenuta, puoi copiare e rinominare il file `.env.example` a `.env` e metterlo in `STEAMGRIDDB_API_KEY`, `ONLINEFIX_USERNAME`, `ONLINEFIX_PASSWORD`.
## Esecuzione
Una volta impostato tutto, puoi eseguire il seguente comando per avviare il processo Electron e il client bittorrent:
```bash
yarn dev
```
## Compilazione
### Compila il bittorrent
Usa il comando:
```bash
python torrent-client/setup.py build
```
### Compila l'applicazione Electron
Usa il comando:
Per Windows:
```bash
yarn build:win
```
Per Linux:
```bash
yarn build:linux
```
## Collaboratori
<a href="https://github.com/hydralauncher/hydra/graphs/contributors">
<img src="https://contrib.rocks/image?repo=hydralauncher/hydra" />
</a>
## Licenza
Hydra è concesso in licenza secondo la [MIT License](LICENSE).

View File

@@ -7,22 +7,19 @@
<h1 align="center">Hydra Launcher</h1> <h1 align="center">Hydra Launcher</h1>
<p align="center"> <p align="center">
<strong>Hydra is a game launcher with its own embedded bittorrent client.</strong> <strong>Hydra is a game launcher with its own embedded bittorrent client and a self-managed repack scraper.</strong>
</p> </p>
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions) [![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases) [![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md) [![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md) [![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md) [![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md) [![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
[![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md) [![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md)
[![de](https://img.shields.io/badge/lang-de-black)](README.de.md)
[![ita](https://img.shields.io/badge/lang-it-red)](README.it.md)
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
![Hydra Catalogue](./docs/screenshot.png) ![Hydra Catalogue](./docs/screenshot.png)
@@ -30,12 +27,11 @@
## Table of Contents ## Table of Contents
- [Table of Contents](#table-of-contents)
- [About](#about) - [About](#about)
- [Features](#features) - [Features](#features)
- [Installation](#installation) - [Installation](#installation)
- [Contributing](#-contributing) - [Contributing](#contributing)
- [Join our Telegram](#-join-our-telegram) - [Join our Telegram](#join-our-telegram)
- [Fork and clone your repository](#fork-and-clone-your-repository) - [Fork and clone your repository](#fork-and-clone-your-repository)
- [Ways you can contribute](#ways-you-can-contribute) - [Ways you can contribute](#ways-you-can-contribute)
- [Project Structure](#project-structure) - [Project Structure](#project-structure)
@@ -51,19 +47,20 @@
- [Build the bittorrent client](#build-the-bittorrent-client) - [Build the bittorrent client](#build-the-bittorrent-client)
- [Build the Electron application](#build-the-electron-application) - [Build the Electron application](#build-the-electron-application)
- [Contributors](#contributors) - [Contributors](#contributors)
- [License](#license)
## About ## About
**Hydra** is a **Game Launcher** with its own embedded **BitTorrent Client**. **Hydra** is a **Game Launcher** with its own embedded **BitTorrent Client** and a **self-managed repack scraper**.
<br> <br>
The launcher is written in TypeScript (Electron) and Python, which handles the torrenting system by using libtorrent. The launcher is written in TypeScript (Electron) and Python, which handles the torrenting system by using libtorrent.
## Features ## Features
- Self-Managed repack scraper among all the most reliable websites on the [Megathread]("https://www.reddit.com/r/Piracy/wiki/megathread/")
- Own embedded bittorrent client - Own embedded bittorrent client
- How Long To Beat (HLTB) integration on game page - How Long To Beat (HLTB) integration on game page
- Downloads path customization - Downloads path customization
- Repack list update notifications
- Windows and Linux support - Windows and Linux support
- Constantly updated - Constantly updated
- And more ... - And more ...
@@ -137,8 +134,9 @@ pip install -r requirements.txt
## Environment variables ## Environment variables
You'll need an SteamGridDB API Key in order to fetch the game icons on installation. You'll need an SteamGridDB API Key in order to fetch the game icons on installation.
If you want to have onlinefix as a repacker you'll need to add your credentials to the .env
Once you have it, you can copy or rename the `.env.example` file to `.env` and put it on`STEAMGRIDDB_API_KEY`. Once you have it, you can copy or rename the `.env.example` file to `.env` and put it on`STEAMGRIDDB_API_KEY`, `ONLINEFIX_USERNAME`, `ONLINEFIX_PASSWORD`.
## Running ## Running

View File

@@ -13,16 +13,13 @@
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions) [![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases) [![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md) [![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md) [![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md) [![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md) [![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md) [![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
[![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md) [![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md)
[![de](https://img.shields.io/badge/lang-de-black)](README.de.md)
[![ita](https://img.shields.io/badge/lang-it-red)](README.it.md)
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
![Hydra Catalogue](./docs/screenshot.png) ![Hydra Catalogue](./docs/screenshot.png)
@@ -30,28 +27,26 @@
## Zawartość. ## Zawartość.
- [Zawartość.](#zawartość)
- [O nas](#o-nas) - [O nas](#o-nas)
- [Cechy](#cechy) - [Cechy.](#cechy)
- [Instalacja](#instalacja) - [Instalacja](#instalacja)
- [Dokonaj wpłaty](#-dokonaj-wpłaty) - [Dokonaj wpłaty](#dokonaj-wpłaty)
- [Dołącz do naszego kanału Telegram](#-dołącz-do-naszego-kanału-telegram) - [Dołącz do naszego kanału Telegram](#dołącz-do-naszego-kanału-telegram)
- [Rozwidlenie i sklonowanie repozytorium](#rozwidlenie-i-sklonowanie-repozytorium) - [Rozwidlenie i sklonowanie repozytorium](#rozwidlenie-i-sklonowanie-repozytorium)
- [Jak możesz pomóc](#jak-możesz-pomóc) - [Jak możesz wnieść swój wkład](#jak-możesz-pomóc)
- [Struktura projektu](#struktura-projektu) - [Struktura projektu](#struktura-projektu)
- [Utwórz kompilację z kodu źródłowego](#utwórz-kompilację-z-kodu-źródłowego) - [Utwórz kompilację z kodu źródłowego](#utwórz-kompilację-z-kodu-źródłowego)
- [Zainstaluj Node.js](#zainstaluj-nodejs) - [Instalacja Node.js](#zainstaluj-nodejs)
- [Zainstaluj Yarn](#zainstaluj-yarn) - [Instalacja Yarn](#zainstaluj-yarn)
- [Zainstaluj zależności Node](#zainstaluj-zależności-node) - [Instalacja Node zależności](#zainstaluj-zależności-node)
- [Zainstaluj Python 3.9](#zainstaluj-python-39) - [Instalacja Python 3.9](#zainstaluj-python-39)
- [Zainstaluj zależności Pythona](#zainstaluj-zależności-pythona) - [Instalacja Python zależności](#zainstaluj-zależności-pythona)
- [Zmienne środowiskowe](#zmienne-środowiskowe) - [Zmienne środowiskowe](#zmienne-środowiskowe)
- [Run](#run) - [Uruchomienie](#utwórz-kompilację-z-kodu-źródłowego)
- [Tworzenie kompilacji](#tworzenie-kompilacji) - [Tworzenie kompilacji](#tworzenie-kompilacji)
- [Zbuduj klienta bittorrent](#zbuduj-klienta-bittorrent) - [Tworzenie klienta bittorrent](#zbuduj-klienta-bittorrent)
- [Tworzenie aplikacji Electron](#tworzenie-aplikacji-electron) - [Tworzenie kompilacji aplikacji Electron](#tworzenie-aplikacji-electron)
- [Współtwórcy](#współtwórcy) - [Współtwórcy](#współtwórcy)
- [License](#license)
## O nas ## O nas

View File

@@ -13,16 +13,13 @@
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions) [![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases) [![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md) [![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md) [![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md) [![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md) [![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md) [![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
[![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md) [![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md)
[![de](https://img.shields.io/badge/lang-de-black)](README.de.md)
[![ita](https://img.shields.io/badge/lang-it-red)](README.it.md)
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
![Hydra Catalogue](./docs/screenshot.png) ![Hydra Catalogue](./docs/screenshot.png)
@@ -30,28 +27,26 @@
## Índice ## Índice
- [Índice](#índice) - [Sobre](#about)
- [Sobre](#-sobre) - [Recursos](#features)
- [Recursos](#-recursos) - [Instalação](#installation)
- [Instalação](#-instalação) - [Contribuindo](#contributing)
- [Contribuindo](#-contribuindo) - [Junte-se ao nosso Telegram](#join-our-telegram)
- [Junte-se ao nosso Telegram](#-junte-se-ao-nosso-telegram) - [Fork e clone seu repositorio](#fork-and-clone-your-repository)
- [Fork e clone o seu repositório](#-fork-e-clone-o-seu-repositório) - [Como contribuir](#ways-you-can-contribute)
- [Formas de contribuir](#-formas-de-contribuir) - [Estrutura do projeto](#project-structure)
- [Estrutura do Projeto](#-estrutura-do-projeto) - [Compile a partir do código-fonte](#build-from-source)
- [Compile a partir do código-fonte](#-compile-a-partir-do-código-fonte) - [Instale Node.js](#install-nodejs)
- [Instale Node.js](#-instale-nodejs) - [Instale Yarn](#install-yarn)
- [Instale Yarn](#-instale-yarn) - [Instale Node Dependencies](#install-node-dependencies)
- [Instale Dependencias do Node](#-instale-dependencias-do-node) - [Instale Python 3.9](#install-python-39)
- [Instale Python 3.9](#-instale-python-39) - [Instale Python Dependencies](#install-python-dependencies)
- [Instale Python Dependencies](#-instale-python-dependencies) - [variaveis de ambiente](#environment-variables)
- [Environment variables](#-environment-variables) - [Rodando o programa](#running)
- [Running](#-running) - [Compilando](#build)
- [Build](#-build) - [Compile o client bittorrent](#build-the-bittorrent-client)
- [Build the bittorrent client](#-build-the-bittorrent-client) - [Compile a aplicação Electron](#build-the-electron-application)
- [Build the Electron application](#-build-the-electron-application) - [Contribuidores](#contributors)
- [Contributors](#-contributors)
- [Licença](#-licença)
## <a name="about"> Sobre ## <a name="about"> Sobre

View File

@@ -13,16 +13,13 @@
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions) [![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases) [![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md) [![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md) [![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
[![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md) [![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md)
[![de](https://img.shields.io/badge/lang-de-black)](README.de.md)
[![ita](https://img.shields.io/badge/lang-it-red)](README.it.md)
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
![Hydra Catalogue](./docs/screenshot.png) ![Hydra Catalogue](./docs/screenshot.png)
@@ -30,12 +27,11 @@
## Содержание ## Содержание
- [Содержание](#содержание)
- [Описание](#описание) - [Описание](#описание)
- [Особенности](#особенности) - [Особенности](#особенности)
- [Установка](#установка) - [Установка](#установка)
- [Вклад](#-вклад) - [Вклад](#contributing)
- [Присоединяйтесь к нашему Telegram](#-присоединяйтесь-к-нашему-telegram) - [Присоединяйтесь к нашему Telegram](#join-our-telegram)
- [Форк и клонирование репозитория](#форк-и-клонирование-репозитория) - [Форк и клонирование репозитория](#форк-и-клонирование-репозитория)
- [Способы внести свой вклад](#способы-внести-свой-вклад) - [Способы внести свой вклад](#способы-внести-свой-вклад)
- [Структура проекта](#структура-проекта) - [Структура проекта](#структура-проекта)
@@ -51,7 +47,6 @@
- [Сборка клиента BitTorrent](#сборка-клиента-bittorrent) - [Сборка клиента BitTorrent](#сборка-клиента-bittorrent)
- [Сборка приложения Electron](#сборка-приложения-electron) - [Сборка приложения Electron](#сборка-приложения-electron)
- [Участники](#участники) - [Участники](#участники)
- [License](#license)
## Описание ## Описание

View File

@@ -13,16 +13,13 @@
[![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions) [![build](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)](https://github.com/hydralauncher/hydra/actions)
[![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases) [![release](https://img.shields.io/github/package-json/v/hydralauncher/hydra)](https://github.com/hydralauncher/hydra/releases)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![uk-UA](https://img.shields.io/badge/lang-uk--UA-blue)](README.uk-UA.md)
[![be](https://img.shields.io/badge/lang-be-orange)](README.be.md) [![be](https://img.shields.io/badge/lang-be-orange)](README.be.md)
[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md)
[![pl](https://img.shields.io/badge/lang-pl-white)](README.pl.md)
[![pt-BR](https://img.shields.io/badge/lang-pt--BR-green.svg)](README.pt-BR.md)
[![ru](https://img.shields.io/badge/lang-ru-yellow.svg)](README.ru.md)
[![es](https://img.shields.io/badge/lang-es-red)](README.es.md) [![es](https://img.shields.io/badge/lang-es-red)](README.es.md)
[![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md) [![fr](https://img.shields.io/badge/lang-fr-blue)](README.fr.md)
[![de](https://img.shields.io/badge/lang-de-black)](README.de.md)
[![ita](https://img.shields.io/badge/lang-it-red)](README.it.md)
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
![Hydra Catalogue](./docs/screenshot.png) ![Hydra Catalogue](./docs/screenshot.png)
@@ -30,12 +27,11 @@
## Зміст ## Зміст
- [Зміст](#зміст)
- [Про нас](#про-нас) - [Про нас](#про-нас)
- [Функції](#функції) - [Функції](#функції)
- [Встановлення](#встановлення) - [Встановлення](#встановлення)
- [Зробити свій внесок](#-зробити-свій-внесок) - [Зробити свій внесок](#contributing)
- [Приєднуйтесь до нашого Telegram](#-приєднуйтесь-до-нашого-telegram) - [Приєднуйтесь до нашого Telegram](#join-our-telegram)
- [Форк і клонування вашого репозиторію](#форк-і-клонування-вашого-репозиторію) - [Форк і клонування вашого репозиторію](#форк-і-клонування-вашого-репозиторію)
- [Як ви можете зробити свій внесок](#як-ви-можете-зробити-свій-внесок) - [Як ви можете зробити свій внесок](#як-ви-можете-зробити-свій-внесок)
- [Структура проекту](#структура-проекту) - [Структура проекту](#структура-проекту)
@@ -51,7 +47,6 @@
- [Зробіть білд bittorrent client](#зробіть-білд-bittorrent-client) - [Зробіть білд bittorrent client](#зробіть-білд-bittorrent-client)
- [Зробіть білд Electron застосунку](#зробіть-білд-electron-застосунку) - [Зробіть білд Electron застосунку](#зробіть-білд-electron-застосунку)
- [Контриб'ютори](#контрибютори) - [Контриб'ютори](#контрибютори)
- [License](#license)
## Про нас ## Про нас

View File

@@ -1,68 +0,0 @@
# Security Policy
## Purpose of the Policy
The purpose of this Security Policy is to ensure the security of our project and maintain the trust of the community.
## Who is Affected by the Policy
This policy applies to all members of our project community, including developers, testers, repository administrators, and users.
## Supported Versions
Use this section to tell people about which versions of your project are
currently being supported with security updates.
| Version | Supported |
| ------- | ------------------ |
| 2.0.x | :white_check_mark: |
| < 1.2.0 | :x: |
## Development Recommendations
### Best Practices
- Follow secure coding principles.
- Use well-established libraries and frameworks.
- Regularly update dependencies.
- Conduct thorough testing, including security-related tests.
### Unrecommended Practices
- Do not use known vulnerabilities that have not been patched.
- Do not publish sensitive information such as API keys or passwords.
- Do not vote for changes that degrade the security of the project.
### User-Generated Content
- Ensure that user-generated content does not contain hidden threats.
- Be cautious when handling user data.
### Community Interaction
- Treat each other with respect and politeness.
- Do not spread spam or spam bots.
- Follow community guidelines.
### Vulnerability Discovery and Reporting
- If you discover a vulnerability, report it as an issue on GitHub.
- Your report should contain detailed information about the vulnerability, including steps to resolve it.
### Reporting Method
To report a vulnerability, create a new issue on GitHub and use branch isolation to provide details about the vulnerability.
### Details to Provide
Please provide the following information about the vulnerability:
- Description of the vulnerability
- Steps to resolve the vulnerability
- Versions on which the vulnerability was found
- Code examples illustrating the vulnerability (if it is safe to do so)
### Expected Behavior
- If we accept the reported vulnerability, we will release a patch and update the security information on GitHub.
- If we reject the reported vulnerability, we will provide an explanation.

View File

@@ -3,8 +3,10 @@ productName: Hydra
directories: directories:
buildResources: build buildResources: build
extraResources: extraResources:
- hydra-download-manager - aria2
- seeds - seeds
- from: node_modules/ps-list/vendor/fastlist-0.3.0-x64.exe
to: fastlist.exe
- from: node_modules/create-desktop-shortcuts/src/windows.vbs - from: node_modules/create-desktop-shortcuts/src/windows.vbs
files: files:
- "!**/.vscode/*" - "!**/.vscode/*"
@@ -17,6 +19,7 @@ asarUnpack:
- resources/** - resources/**
win: win:
executableName: Hydra executableName: Hydra
requestedExecutionLevel: requireAdministrator
target: target:
- nsis - nsis
- portable - portable
@@ -29,6 +32,7 @@ nsis:
allowToChangeInstallationDirectory: true allowToChangeInstallationDirectory: true
portable: portable:
artifactName: ${name}-${version}-portable.${ext} artifactName: ${name}-${version}-portable.${ext}
requestExecutionLevel: admin
mac: mac:
entitlementsInherit: build/entitlements.mac.plist entitlementsInherit: build/entitlements.mac.plist
extendInfo: extendInfo:
@@ -44,7 +48,6 @@ linux:
- AppImage - AppImage
- snap - snap
- deb - deb
- pacman
- rpm - rpm
maintainer: electronjs.org maintainer: electronjs.org
category: Game category: Game

View File

@@ -6,16 +6,9 @@ import {
externalizeDepsPlugin, externalizeDepsPlugin,
} from "electron-vite"; } from "electron-vite";
import react from "@vitejs/plugin-react"; import react from "@vitejs/plugin-react";
import { sentryVitePlugin } from "@sentry/vite-plugin";
import { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin"; import { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin";
import svgr from "vite-plugin-svgr"; import svgr from "vite-plugin-svgr";
const sentryPlugin = sentryVitePlugin({
authToken: process.env.SENTRY_AUTH_TOKEN,
org: "hydra-launcher",
project: "hydra-launcher",
});
export default defineConfig(({ mode }) => { export default defineConfig(({ mode }) => {
loadEnv(mode); loadEnv(mode);
@@ -35,7 +28,7 @@ export default defineConfig(({ mode }) => {
"@shared": resolve("src/shared"), "@shared": resolve("src/shared"),
}, },
}, },
plugins: [externalizeDepsPlugin(), swcPlugin(), sentryPlugin], plugins: [externalizeDepsPlugin(), swcPlugin()],
}, },
preload: { preload: {
plugins: [externalizeDepsPlugin()], plugins: [externalizeDepsPlugin()],
@@ -51,7 +44,7 @@ export default defineConfig(({ mode }) => {
"@shared": resolve("src/shared"), "@shared": resolve("src/shared"),
}, },
}, },
plugins: [svgr(), react(), vanillaExtractPlugin(), sentryPlugin], plugins: [svgr(), react(), vanillaExtractPlugin()],
}, },
}; };
}); });

View File

@@ -1,6 +1,6 @@
{ {
"name": "hydralauncher", "name": "hydralauncher",
"version": "2.1.0", "version": "2.0.1",
"description": "Hydra", "description": "Hydra",
"main": "./out/main/index.js", "main": "./out/main/index.js",
"author": "Los Broxas", "author": "Los Broxas",
@@ -23,28 +23,27 @@
"start": "electron-vite preview", "start": "electron-vite preview",
"dev": "electron-vite dev", "dev": "electron-vite dev",
"build": "npm run typecheck && electron-vite build", "build": "npm run typecheck && electron-vite build",
"postinstall": "electron-builder install-app-deps", "postinstall": "electron-builder install-app-deps && node ./postinstall.cjs",
"build:unpack": "npm run build && electron-builder --dir", "build:unpack": "npm run build && electron-builder --dir",
"build:win": "electron-vite build && electron-builder --win", "build:win": "electron-vite build && electron-builder --win",
"build:mac": "electron-vite build && electron-builder --mac", "build:mac": "electron-vite build && electron-builder --mac",
"build:linux": "electron-vite build && electron-builder --linux", "build:linux": "electron-vite build && electron-builder --linux",
"prepare": "husky", "prepare": "husky",
"knex:migrate:make": "knex --knexfile src/main/knexfile.ts migrate:make --esm" "typeorm:migration-create": "yarn typeorm migration:create"
}, },
"dependencies": { "dependencies": {
"@electron-toolkit/preload": "^3.0.0", "@electron-toolkit/preload": "^3.0.0",
"@electron-toolkit/utils": "^3.0.0", "@electron-toolkit/utils": "^3.0.0",
"@fontsource/noto-sans": "^5.0.22", "@fontsource/fira-mono": "^5.0.13",
"@hookform/resolvers": "^3.9.0", "@fontsource/fira-sans": "^5.0.20",
"@primer/octicons-react": "^19.9.0", "@primer/octicons-react": "^19.9.0",
"@reduxjs/toolkit": "^2.2.3", "@reduxjs/toolkit": "^2.2.3",
"@sentry/electron": "^5.1.0",
"@vanilla-extract/css": "^1.14.2", "@vanilla-extract/css": "^1.14.2",
"@vanilla-extract/dynamic": "^2.1.1",
"@vanilla-extract/recipes": "^0.5.2", "@vanilla-extract/recipes": "^0.5.2",
"aria2": "^4.1.2",
"auto-launch": "^5.0.6", "auto-launch": "^5.0.6",
"axios": "^1.7.7", "axios": "^1.6.8",
"better-sqlite3": "^11.2.1", "better-sqlite3": "^9.5.0",
"check-disk-space": "^3.4.0", "check-disk-space": "^3.4.0",
"classnames": "^2.5.1", "classnames": "^2.5.1",
"color": "^4.2.3", "color": "^4.2.3",
@@ -54,27 +53,26 @@
"electron-log": "^5.1.4", "electron-log": "^5.1.4",
"electron-updater": "^6.1.8", "electron-updater": "^6.1.8",
"fetch-cookie": "^3.0.1", "fetch-cookie": "^3.0.1",
"file-type": "^19.0.0",
"flexsearch": "^0.7.43", "flexsearch": "^0.7.43",
"i18next": "^23.11.2", "i18next": "^23.11.2",
"i18next-browser-languagedetector": "^7.2.1", "i18next-browser-languagedetector": "^7.2.1",
"icojs": "^0.19.3", "icojs": "^0.19.3",
"iso-639-1": "3.1.2",
"jsdom": "^24.0.0", "jsdom": "^24.0.0",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"knex": "^3.1.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"lottie-react": "^2.4.0", "lottie-react": "^2.4.0",
"parse-torrent": "^11.0.16", "parse-torrent": "^11.0.16",
"piscina": "^4.5.1", "piscina": "^4.5.1",
"react-hook-form": "^7.53.0", "ps-list": "^8.1.1",
"react-i18next": "^14.1.0", "react-i18next": "^14.1.0",
"react-loading-skeleton": "^3.4.0", "react-loading-skeleton": "^3.4.0",
"react-redux": "^9.1.1", "react-redux": "^9.1.1",
"react-router-dom": "^6.22.3", "react-router-dom": "^6.22.3",
"sudo-prompt": "^9.2.1",
"typeorm": "^0.3.20", "typeorm": "^0.3.20",
"user-agents": "^1.1.193", "user-agents": "^1.1.193",
"yaml": "^2.4.1", "yaml": "^2.4.1",
"yup": "^1.4.0",
"zod": "^3.23.8" "zod": "^3.23.8"
}, },
"devDependencies": { "devDependencies": {
@@ -83,7 +81,6 @@
"@electron-toolkit/eslint-config-prettier": "^2.0.0", "@electron-toolkit/eslint-config-prettier": "^2.0.0",
"@electron-toolkit/eslint-config-ts": "^1.0.1", "@electron-toolkit/eslint-config-ts": "^1.0.1",
"@electron-toolkit/tsconfig": "^1.0.1", "@electron-toolkit/tsconfig": "^1.0.1",
"@sentry/vite-plugin": "^2.20.1",
"@swc/core": "^1.4.16", "@swc/core": "^1.4.16",
"@types/auto-launch": "^5.0.5", "@types/auto-launch": "^5.0.5",
"@types/color": "^3.0.6", "@types/color": "^3.0.6",
@@ -97,7 +94,7 @@
"@types/user-agents": "^1.0.4", "@types/user-agents": "^1.0.4",
"@vanilla-extract/vite-plugin": "^4.0.7", "@vanilla-extract/vite-plugin": "^4.0.7",
"@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react": "^4.2.1",
"electron": "^30.3.0", "electron": "^30.0.9",
"electron-builder": "^24.9.1", "electron-builder": "^24.9.1",
"electron-vite": "^2.0.0", "electron-vite": "^2.0.0",
"eslint": "^8.56.0", "eslint": "^8.56.0",
@@ -108,7 +105,6 @@
"prettier": "^3.2.4", "prettier": "^3.2.4",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"ts-node": "^10.9.2",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"vite": "^5.0.12", "vite": "^5.0.12",
"vite-plugin-svgr": "^4.2.0" "vite-plugin-svgr": "^4.2.0"

50
postinstall.cjs Normal file
View File

@@ -0,0 +1,50 @@
const { default: axios } = require("axios");
const util = require("node:util");
const fs = require("node:fs");
const exec = util.promisify(require("node:child_process").exec);
const downloadAria2 = async () => {
if (fs.existsSync("aria2")) {
console.log("Aria2 already exists, skipping download...");
return;
}
const file =
process.platform === "win32"
? "aria2-1.37.0-win-64bit-build1.zip"
: "aria2-1.37.0-1-x86_64.pkg.tar.zst";
const downloadUrl =
process.platform === "win32"
? `https://github.com/aria2/aria2/releases/download/release-1.37.0/${file}`
: "https://archlinux.org/packages/extra/x86_64/aria2/download/";
console.log(`Downloading ${file}...`);
const response = await axios.get(downloadUrl, { responseType: "stream" });
const stream = response.data.pipe(fs.createWriteStream(file));
stream.on("finish", async () => {
console.log(`Downloaded ${file}, extracting...`);
if (process.platform === "win32") {
await exec(`npx extract-zip ${file}`);
console.log("Extracted. Renaming folder...");
fs.renameSync(file.replace(".zip", ""), "aria2");
} else {
await exec(`tar --zstd -xvf ${file} usr/bin/aria2c`);
console.log("Extracted. Copying binary file...");
fs.mkdirSync("aria2");
fs.copyFileSync("usr/bin/aria2c", "aria2/aria2c");
fs.rmSync("usr", { recursive: true });
}
console.log(`Extracted ${file}, removing compressed downloaded file...`);
fs.rmSync(file);
});
};
downloadAria2();

View File

@@ -1,7 +0,0 @@
libtorrent
cx_Freeze
cx_Logging; sys_platform == 'win32'
lief; sys_platform == 'win32'
pywin32; sys_platform == 'win32'
psutil
Pillow

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "اَلْعَرَبِيَّةُ",
"home": { "home": {
"featured": "مميّز", "featured": "مميّز",
"trending": "شائع", "trending": "شائع",

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "беларуская мова",
"home": { "home": {
"featured": "Рэкамэндаванае", "featured": "Рэкамэндаванае",
"trending": "Актуальнае", "trending": "Актуальнае",

View File

@@ -1,256 +0,0 @@
{
"language_name": "Català",
"app": {
"successfully_signed_in": "Has entrat correctament"
},
"home": {
"featured": "Destacats",
"trending": "Populars",
"surprise_me": "Sorprèn-me",
"no_results": "No s'ha trobat res"
},
"sidebar": {
"catalogue": "Catàleg",
"downloads": "Baixades",
"settings": "Configuració",
"my_library": "Biblioteca",
"downloading_metadata": "{{title}} (S'estan baixant les metadades…)",
"paused": "{{title}} (Pausat)",
"downloading": "{{title}} ({{percentage}} - S'està baixant…)",
"filter": "Filtra la biblioteca",
"home": "Inici",
"queued": "{{title}} (En espera)",
"game_has_no_executable": "El joc encara no té un executable seleccionat",
"sign_in": "Entra"
},
"header": {
"search": "Cerca jocs",
"home": "Inici",
"catalogue": "Catàleg",
"downloads": "Baixades",
"search_results": "Resultats de la cerca",
"settings": "Configuració",
"version_available_install": "Hi ha disponible la versió {{version}}. Feu clic aquí per a reiniciar i instal·lar-la.",
"version_available_download": "Hi ha disponible la versió {{version}}. Feu clic aquí per a baixar-la."
},
"bottom_panel": {
"no_downloads_in_progress": "Cap baixada en curs",
"downloading_metadata": "S'estan baixant les metadades de: {{title}}…",
"downloading": "S'està baixant: {{title}}… ({{percentage}} complet) - Finalització: {{eta}} - {{speed}}",
"calculating_eta": "Descarregant {{title}}… ({{percentage}} completat) - Calculant el temps restant…",
"checking_files": "Comprovant els fitxers de {{title}}… ({{percentage}} completat)"
},
"catalogue": {
"next_page": "Pàgina següent",
"previous_page": "Pàgina anterior"
},
"game_details": {
"open_download_options": "Obre les opcions de baixada",
"download_options_zero": "No hi ha opcions de baixada",
"download_options_one": "{{count}} opció de baixada",
"download_options_other": "{{count}} opcions de baixada",
"updated_at": "Actualitzat: {{updated_at}}",
"install": "Instal·la",
"resume": "Reprèn",
"pause": "Pausa",
"cancel": "Cancel·la",
"remove": "Elimina",
"space_left_on_disk": "{{space}} lliures al disc",
"eta": "Finalitza en: {{eta}}",
"calculating_eta": "Calculant temps estimat…",
"downloading_metadata": "S'estan baixant les metadades…",
"filter": "Filtra els reempaquetats",
"requirements": "Requisits del sistema",
"minimum": "Mínims",
"recommended": "Recomanats",
"paused": "Paused",
"release_date": "Publicat el {{date}}",
"publisher": "Publicat per {{publisher}}",
"hours": "hores",
"minutes": "minuts",
"amount_hours": "{{amount}} hores",
"amount_minutes": "{{amount}} minuts",
"accuracy": "{{accuracy}}% de precisió",
"add_to_library": "Afegeix a la biblioteca",
"remove_from_library": "Elimina de la biblioteca",
"no_downloads": "No hi ha baixades disponibles",
"play_time": "Jugat durant {{amount}}",
"last_time_played": "Última partida: {{period}}",
"not_played_yet": "Encara no has jugat al {{title}}",
"next_suggestion": "Suggeriment següent",
"play": "Inicia",
"deleting": "S'està eliminant l'instal·lador…",
"close": "Tanca",
"playing_now": "S'està jugant",
"change": "Canvia",
"repacks_modal_description": "Tria quin reempaquetat vols baixar",
"select_folder_hint": "Per a canviar la carpeta predefinida, vés a la <0>Configuració</0>",
"download_now": "Baixa ara",
"no_shop_details": "No s'han pogut recuperar els detalls de la tenda.",
"download_options": "Opcions de baixada",
"download_path": "Ruta de baixada",
"previous_screenshot": "Captura anterior",
"next_screenshot": "Captura següent",
"screenshot": "Captura {{number}}",
"open_screenshot": "Obre la captura {{number}}",
"download_settings": "Configuració de descàrrega",
"downloader": "Descarregador",
"select_executable": "Selecciona",
"no_executable_selected": "No hi ha executable selccionat",
"open_folder": "Obre carpeta",
"open_download_location": "Visualitzar fitxers descarregats",
"create_shortcut": "Crear accés directe a l'escriptori",
"remove_files": "Elimina fitxers",
"remove_from_library_title": "Segur?",
"remove_from_library_description": "Això eliminarà el videojoc {{game}} del teu catàleg",
"options": "Opcions",
"executable_section_title": "Executable",
"executable_section_description": "Directori del fitxer des d'on s'executarà quan es cliqui a \"Executar\"",
"downloads_secion_title": "Descàrregues",
"downloads_section_description": "Comprova actualitzacions o altres versions del videojoc",
"danger_zone_section_title": "Zona de perill",
"danger_zone_section_description": "Elimina aquest videojoc del teu catàleg o els fitxers descarregats per Hydra",
"download_in_progress": "Descàrrega en progrés",
"download_paused": "Descàrrega en pausa",
"last_downloaded_option": "Opció de l'última descàrrega",
"create_shortcut_success": "Accés directe creat satisfactòriament",
"create_shortcut_error": "Error al crear l'accés directe"
},
"activation": {
"title": "Activa l'Hydra",
"installation_id": "ID d'instal·lació:",
"enter_activation_code": "Introdueix el codi d'activació",
"message": "Si no saps on demanar-ho, no ho hauries de tenir.",
"activate": "Activa",
"loading": "S'està carregant…"
},
"downloads": {
"resume": "Reprèn",
"pause": "Pausa",
"eta": "Finalització {{eta}}",
"paused": "Pausada",
"verifying": "S'està verificant…",
"completed": "Completada",
"removed": "No descarregat",
"cancel": "Cancel·la",
"filter": "Filtra els jocs baixats",
"remove": "Elimina",
"downloading_metadata": "S'estan baixant les metadades…",
"deleting": "S'està eliminant l'instal·lador…",
"delete": "Elimina l'instal·lador",
"delete_modal_title": "N'estàs segur?",
"delete_modal_description": "S'eliminaran de l'ordinador tots els fitxers d'instal·lació",
"install": "Instal·la",
"download_in_progress": "En progrés",
"queued_downloads": "Descàrregues en espera",
"downloads_completed": "Completat",
"queued": "En espera",
"no_downloads_title": "Buit",
"no_downloads_description": "No has descarregat res amb Hydra encara, però mai és tard per començar a fer-ho.",
"checking_files": "Comprovant fitxers…"
},
"settings": {
"downloads_path": "Ruta de baixades",
"change": "Actualitza",
"notifications": "Notificacions",
"enable_download_notifications": "Quan finalitzi una baixada",
"enable_repack_list_notifications": "Quan s'afegeixi un nou reempaquetat",
"real_debrid_api_token_label": "Testimoni de l'API de Real Debrid",
"quit_app_instead_hiding": "Tanca l'Hydra en compte de minimitzar-la a la safata",
"launch_with_system": "Inicia l'Hydra quan s'iniciï el sistema",
"general": "General",
"behavior": "Comportament",
"download_sources": "Fonts de descàrrega",
"language": "Idioma",
"real_debrid_api_token": "Testimoni API",
"enable_real_debrid": "Activa el Real Debrid",
"real_debrid_description": "Real-Debrid és un programa de descàrrega sense restriccions que us permet descarregar fitxers a l'instant i al màxim de la vostra velocitat d'Internet.",
"real_debrid_invalid_token": "Invalida el testimoni de l'API",
"real_debrid_api_token_hint": "Pots obtenir la teva clau de l'API <0>aquí</0>.",
"real_debrid_free_account_error": "L'usuari \"{{username}}\" és un compte gratuït. Si us plau subscriu-te a Real-Debrid",
"real_debrid_linked_message": "Compte \"{{username}}\" vinculat",
"save_changes": "Desa els canvis",
"changes_saved": "Els canvis s'han desat correctament",
"download_sources_description": "Hydra buscarà els enllaços de descàrrega d'aquestes fonts. L'URL d'origen ha de ser un enllaç directe a un fitxer .json que contingui els enllaços de descàrrega.",
"validate_download_source": "Valida",
"remove_download_source": "Elimina",
"add_download_source": "Afegeix font",
"download_count_zero": "No hi ha baixades a la llista",
"download_count_one": "{{countFormatted}} a la llista de baixades",
"download_count_other": "{{countFormatted}} baixades a la llista",
"download_options_zero": "No hi ha cap descàrrega disponible",
"download_options_one": "{{countFormatted}} descàrrega disponible",
"download_options_other": "{{countFormatted}} baixades disponibles",
"download_source_url": "Descarrega l'URL de la font",
"add_download_source_description": "Inseriu la URL que conté el fitxer .json",
"download_source_up_to_date": "Actualitzat",
"download_source_errored": "S'ha produït un error",
"sync_download_sources": "Sincronitza fonts",
"removed_download_source": "S'ha eliminat la font de descàrrega",
"added_download_source": "Added download source",
"download_sources_synced": "Totes les fonts de descàrrega estan sincronitzades",
"insert_valid_json_url": "Insereix una URL JSON vàlida",
"found_download_option_zero": "No s'ha trobat cap opció de descàrrega",
"found_download_option_one": "S'ha trobat l'opció de baixada de {{countFormatted}}",
"found_download_option_other": "S'han trobat {{countFormatted}} opcions de baixada",
"import": "Import"
},
"notifications": {
"download_complete": "La baixada ha finalitzat",
"game_ready_to_install": "{{title}} ja es pot instal·lar",
"repack_list_updated": "S'ha actualitzat la llista de reempaquetats",
"repack_count_one": "S'ha afegit {{count}} reempaquetat",
"repack_count_other": "S'han afegit {{count}} reempaquetats",
"new_update_available": "Versió {{version}} disponible",
"restart_to_install_update": "Reinicieu Hydra per instal·lar l'actualització"
},
"system_tray": {
"open": "Obre l'Hydra",
"quit": "Tanca"
},
"game_card": {
"no_downloads": "No hi ha baixades disponibles"
},
"binary_not_found_modal": {
"title": "Programes no instal·lats",
"description": "No s'ha trobat els executables del Wine o el Lutris al sistema.",
"instructions": "Comprova quina és la manera correcta d'instal·lar qualsevol d'ells en la teva distribució de Linux perquè el joc pugui executar-se amb normalitat."
},
"modal": {
"close": "Botó de tancar"
},
"forms": {
"toggle_password_visibility": "Commuta la visibilitat de la contrasenya"
},
"user_profile": {
"amount_hours": "{{amount}} hores",
"amount_minutes": "{{amount}} minuts",
"last_time_played": "Última partida {{period}}",
"activity": "Activitat recent",
"library": "Biblioteca",
"total_play_time": "Temps total de joc:{{amount}}",
"no_recent_activity_title": "Hmmm… encara no res",
"no_recent_activity_description": "No has jugat a cap joc recentment. És el moment de canviar-ho!",
"display_name": "Nom de visualització",
"saving": "Desant",
"save": "Desa",
"edit_profile": "Edita el Perfil",
"saved_successfully": "S'ha desat correctament",
"try_again": "Siusplau torna-ho a provar",
"sign_out_modal_title": "Segur?",
"cancel": "Cancel·la",
"successfully_signed_out": "S'ha tancat la sessió correctament",
"sign_out": "Tanca sessió",
"playing_for": "Jugant per {{amount}}",
"sign_out_modal_text": "La vostra biblioteca està enllaçada amb el vostre compte actual. Quan tanqueu la sessió, la vostra biblioteca ja no serà visible i cap progrés no es desarà. Voleu continuar amb tancar la sessió?",
"add_friends": "Afegeix amics",
"add": "Afegeix",
"friend_code": "Codi de l'amic",
"see_profile": "Veure Perfil",
"sending": "Enviant",
"friend_request_sent": "Sol·licitud d'amistat enviada",
"friends": "Amistats",
"friends_list": "Llista d'amistats",
"user_not_found": "Usuari no trobat"
}
}

View File

@@ -1,272 +0,0 @@
{
"language_name": "Čeština",
"app": {
"successfully_signed_in": "Úspěšně přihlášen"
},
"home": {
"featured": "Doporučené",
"trending": "Trendy",
"surprise_me": "Překvap mě",
"no_results": "Výsledek nenalezen"
},
"sidebar": {
"catalogue": "Katalog",
"downloads": "Stažené",
"settings": "Nastavení",
"my_library": "Moje knihovna",
"downloading_metadata": "{{title}} (Stahuji metadata…)",
"paused": "{{title}} (Pozastaveno)",
"downloading": "{{title}} ({{percentage}} - Stahuji…)",
"filter": "Filtrovat knihovnu",
"home": "Domov",
"queued": "{{title}} (V řadě)",
"game_has_no_executable": "Hra nemá zvolen žádný spustitelný soubor",
"sign_in": "Přihlásit se"
},
"header": {
"search": "Vyhledat hry",
"home": "Domov",
"catalogue": "Katalog",
"downloads": "Stažené",
"search_results": "Výsledky vyhledávání",
"settings": "Nastavení",
"version_available_install": "Je dostupná nová verze: {{version}}. Klikni sem pro restart a instalaci.",
"version_available_download": "Je dostupná nová verze: {{version}}. Klikni sem pro stažení."
},
"bottom_panel": {
"no_downloads_in_progress": "Neprobíhá žádné stahování",
"downloading_metadata": "Stahuji metadata: {{title}}…",
"downloading": "Stahuji {{title}}… ({{percentage}} staženo) - Odhadovaný čas {{eta}} - {{speed}}",
"calculating_eta": "Stahuji {{title}}… ({{percentage}} staženo) - Počítám zbývající čas…",
"checking_files": "Kontroluji soubory: {{title}}… ({{percentage}} ověřeno)"
},
"catalogue": {
"next_page": "Další strana",
"previous_page": "Předchozí strana"
},
"game_details": {
"open_download_options": "Otevřít možnosti stahování",
"download_options_zero": "Žádné možnosti stahování",
"download_options_one": "{{count}} možnost stažení",
"download_options_other": "{{count}} možnosti stažení",
"updated_at": "Aktualizováno {{updated_at}}",
"install": "Instalovat",
"resume": "Obnovit",
"pause": "Pozastavit",
"cancel": "Zrušit",
"remove": "Odebrat",
"space_left_on_disk": "{{space}} zbývá na disku",
"eta": "Odhadovaný čas: {{eta}}",
"calculating_eta": "Počítám zbývající čas…",
"downloading_metadata": "Stahuji metadata…",
"filter": "Filtrovat repacky",
"requirements": "Systémové požadavky",
"minimum": "Minimální",
"recommended": "Doporučené",
"paused": "Pozastaveno",
"release_date": "Datum vydání: {{date}}",
"publisher": "Publikováno: {{publisher}}",
"hours": "hodiny",
"minutes": "minuty",
"amount_hours": "{{amount}} hodin",
"amount_minutes": "{{amount}} minut",
"accuracy": "Přesnost {{accuracy}}%",
"add_to_library": "Přidat do knihovny",
"remove_from_library": "Odebrat z knihovny",
"no_downloads": "Žádné možnosti stahování nejsou dostupné",
"play_time": "Odehraný čas: {{amount}}",
"last_time_played": "Naposledy hráno {{period}}",
"not_played_yet": "Ješte jste nehráli {{title}}",
"next_suggestion": "Další doporučení",
"play": "Hrát",
"deleting": "Odstraňuji instalační program…",
"close": "Zavřít",
"playing_now": "Právě hraje",
"change": "Změnit",
"repacks_modal_description": "Vyber repack který chceš stáhnout",
"select_folder_hint": "Pro změnu základní složky, jdi do <0>Nastavení</0>",
"download_now": "Stáhnout",
"no_shop_details": "Nepodařilo se mi načíst informace o obchodu.",
"download_options": "Možnosti stahování",
"download_path": "Umístění stahování",
"previous_screenshot": "Předchozí snímek obrazovky",
"next_screenshot": "Následující snímek obrazovky",
"screenshot": "Snímek obrazovky {{number}}",
"open_screenshot": "Otevřít snímek obrazovky {{number}}",
"download_settings": "Nastavení stahování",
"downloader": "Správce stahování",
"select_executable": "Vybrat",
"no_executable_selected": "Nebyl vybrán spustitelný soubor",
"open_folder": "Otevřít složku",
"open_download_location": "Zobrazit stažené soubory",
"create_shortcut": "Vytvořit zástupce na ploše",
"remove_files": "Odebrat soubory",
"remove_from_library_title": "Jste si jisti?",
"remove_from_library_description": "Tohle odstraní {{game}} z vaší knihovny",
"options": "Možnosti",
"executable_section_title": "Spustitelné",
"executable_section_description": "Umístění souboru který bude spuštěn při kliknutí na \"Hrát\"",
"downloads_secion_title": "Stažené soubory",
"downloads_section_description": "Zkontrolovat jestli není nová / odlišná verze hry",
"danger_zone_section_title": "Nebezpečná zóna",
"danger_zone_section_description": "Odebrat hru z knihovny / soubory stažené Hydrou",
"download_in_progress": "Probíhá stahování",
"download_paused": "Stahování pozastaveno",
"last_downloaded_option": "Poslední stažená možnost",
"create_shortcut_success": "Zástupce vytvořen úspěšně",
"create_shortcut_error": "Chyba při pokusu vytvořit zástupce"
},
"activation": {
"title": "Aktivovat hydru",
"installation_id": "ID instalace:",
"enter_activation_code": "Zadej svůj aktivační kód",
"message": "Pokud nevíš, kde ten kód sehnat, tak by jsi k tomuhle neměl mít přístup.",
"activate": "Aktivovat",
"loading": "Načítání…"
},
"downloads": {
"resume": "Pokračovat",
"pause": "Pozastavit",
"eta": "Odhadovaný čas: {{eta}}",
"paused": "Pozastaveno",
"verifying": "Ověřuji…",
"completed": "Hotovo",
"removed": "Není staženo",
"cancel": "Zrušit",
"filter": "Filtrovat stažené hry",
"remove": "Odebrat",
"downloading_metadata": "Stahuji metadata…",
"deleting": "Odstraňuji instalační program…",
"delete": "Odebrat instalační program",
"delete_modal_title": "Jste si jisti?",
"delete_modal_description": "Tohle odstraní všechny instalační soubory",
"install": "Instalovat",
"download_in_progress": "Probíhá stahování",
"queued_downloads": "Stahování v řadě",
"downloads_completed": "Dokončeno",
"queued": "V řadě",
"no_downloads_title": "Prázdno..",
"no_downloads_description": "Ještě jsi zatím nic nestáhl přes Hydru, ale furt není pozdě začít.",
"checking_files": "Kontroluji soubory…"
},
"settings": {
"downloads_path": "Umístění stahování",
"change": "Aktualizovat",
"notifications": "Upozornění",
"enable_download_notifications": "Až bude stahování dokončeno",
"enable_repack_list_notifications": "Když bude přidán nový repack",
"real_debrid_api_token_label": "Real-Debrid API token",
"quit_app_instead_hiding": "Nezavírat Hydru při zavření okna",
"launch_with_system": "Spustit Hydru při startu systému",
"general": "Hlavní",
"behavior": "Chování",
"download_sources": "Zdroje stahování",
"language": "Jazyk",
"real_debrid_api_token": "API Token",
"enable_real_debrid": "Povolit Real-Debrid",
"real_debrid_description": "Real-Debrid je neomezený správce stahování, který umožňuje stahovat soubory v nejvyšší rychlosti vašeho internetu.",
"real_debrid_invalid_token": "Neplatný API token",
"real_debrid_api_token_hint": "API token můžeš sehnat <0>zde</0>",
"real_debrid_free_account_error": "Účet \"{{username}}\" má základní úroveň. Prosím předplaťte si Real-Debrid",
"real_debrid_linked_message": "Účet \"{{username}}\" je propojen",
"save_changes": "Uložit změny",
"changes_saved": "Změny úspěšně uloženy",
"download_sources_description": "Hydra bude odsud sbírat soubory. Zdrojový odkaz musí být .json soubor obsahující odkazy na soubory.",
"validate_download_source": "Ověřit",
"remove_download_source": "Odebrat",
"add_download_source": "Přidat zdroj",
"download_count_zero": "Žádná možnost stažení",
"download_count_one": "{{countFormatted}} možnost stažení",
"download_count_other": "{{countFormatted}} možnosti stažení",
"download_source_url": "Stáhnout zdrojový odkaz",
"add_download_source_description": "Zadej odkaz odkazující na .json soubor",
"download_source_up_to_date": "Aktuální",
"download_source_errored": "Chyba",
"sync_download_sources": "Synchronizovat zdroje",
"removed_download_source": "Zdroj odebrán",
"added_download_source": "Zdroj přidán",
"download_sources_synced": "Všechny zdroje jsou synchronizovány",
"insert_valid_json_url": "Zadej platnou JSON adresu",
"found_download_option_zero": "Nenalezena žádná možnost stahování",
"found_download_option_one": "Nalezena {{countFormatted}} možnost stahování",
"found_download_option_other": "Nalezeny {{countFormatted}} možnosti stahování",
"import": "Importovat"
},
"notifications": {
"download_complete": "Stahování dokončeno",
"game_ready_to_install": "{{title}} je připraveno k instalaci",
"repack_list_updated": "Seznam repacků byl aktualizován",
"repack_count_one": "{{count}} repack přidán",
"repack_count_other": "{{count}} repacky přidány",
"new_update_available": "Version {{version}} je dostupná",
"restart_to_install_update": "Restartuj Hydru pro aktualizaci"
},
"system_tray": {
"open": "Otevřít Hydru",
"quit": "Odejít"
},
"game_card": {
"no_downloads": "Žádné možnosti stahování nenalezeny"
},
"binary_not_found_modal": {
"title": "Programy nenainstalovány",
"description": "Spustitelné soubory Wine nebo Lutris nebyly nalezeny ve vašem systému",
"instructions": "Zkonstroluj oficiální cestu jak je nainstalovat na tvoji Linux Distribuci, aby hry mohly běžet normálně"
},
"modal": {
"close": "Tlačítko zavřít"
},
"forms": {
"toggle_password_visibility": "Přepnout viditelnost hesla"
},
"user_profile": {
"amount_hours": "{{amount}} hodin",
"amount_minutes": "{{amount}} minut",
"last_time_played": "Naposledy hráno {{period}}",
"activity": "Nedávná aktivita",
"library": "Knihovna",
"total_play_time": "Celkový odehraný čas: {{amount}}",
"no_recent_activity_title": "Hmmm… nic tu není",
"no_recent_activity_description": "V poslední době si nehrál žádnout hru, můžeš to ale napravit!",
"display_name": "Zobrazované jméno",
"saving": "Ukládání",
"save": "Uložit",
"edit_profile": "Upravit profil",
"saved_successfully": "Úspěšně uloženo",
"try_again": "Prosím, zkuste to znovu",
"sign_out_modal_title": "Jste si jisti?",
"cancel": "Zrušit",
"successfully_signed_out": "Úspěšně odhlášeno",
"sign_out": "Odhlásit se",
"playing_for": "Hraje po: {{amount}}",
"sign_out_modal_text": "Vaše knihovna je propojena s vaším současným účtem. Po odhlášení vaše knihovna již nebude vidět, a postup nebude uložen. Pokračovat?",
"add_friends": "Přidat přátele",
"add": "Přidat",
"friend_code": "Kód přítele",
"see_profile": "Zobrazit profil",
"sending": "Odesílání",
"friend_request_sent": "Žádost odeslána",
"friends": "Přátelé",
"friends_list": "Seznam přátel",
"user_not_found": "Uživatel nenalezen",
"block_user": "Zablokovat uživatele",
"add_friend": "Přidat přítele",
"request_sent": "Žádost odeslána",
"request_received": "Žádost obdržena",
"accept_request": "Přijmout žádost",
"ignore_request": "Ignorovat žádost",
"cancel_request": "Zrušit žádost",
"undo_friendship": "Odvolat přátelství",
"request_accepted": "Žádost přijata",
"user_blocked_successfully": "Uživatel úspěšně zablokován",
"user_block_modal_text": "Tohle zablokuje {{displayName}}",
"blocked_users": "Zablokovaní uživatelé",
"unblock": "Odblokovat",
"no_friends_added": "Nemáš přidané žádné přátele",
"pending": "Odchozí",
"no_pending_invites": "Nemáte žádné příchozí žádosti",
"no_blocked_users": "Nemáte nikoho zablokovaného",
"friend_code_copied": "Kód přítele zkopírován",
"undo_friendship_modal_text": "Tímto zrušíte své přátelství s {{displayName}}"
}
}

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "Dansk",
"home": { "home": {
"featured": "Anbefalet", "featured": "Anbefalet",
"trending": "Trender", "trending": "Trender",

View File

@@ -1,272 +0,0 @@
{
"language_name": "Deutsch",
"app": {
"successfully_signed_in": "Erfolgreich angemeldet"
},
"home": {
"featured": "Empfohlen",
"trending": "Beliebt",
"surprise_me": "Überrasche mich",
"no_results": "Keine Ergebnisse gefunden"
},
"sidebar": {
"catalogue": "Katalog",
"downloads": "Downloads",
"settings": "Einstellungen",
"my_library": "Meine Bibliothek",
"downloading_metadata": "{{title}} (Metadaten werden heruntergeladen…)",
"paused": "{{title}} (Pausiert)",
"downloading": "{{title}} ({{percentage}} - Wird heruntergeladen…)",
"filter": "Bibliothek filtern",
"home": "Home",
"queued": "{{title}} (In Warteschlange)",
"game_has_no_executable": "Spiel hat keine ausführbare Datei gewählt",
"sign_in": "Anmelden"
},
"header": {
"search": "Spiele suchen",
"home": "Home",
"catalogue": "Katalog",
"downloads": "Downloads",
"search_results": "Suchergebnisse",
"settings": "Einstellungen",
"version_available_install": "Version {{version}} verfügbar. Klicke hier, um neuzustarten und sie zu installieren.",
"version_available_download": "Version {{version}} verfügbar. Klicke hier, um sie herunterzuladen."
},
"bottom_panel": {
"no_downloads_in_progress": "Keine aktive Downloads",
"downloading_metadata": "Metadaten von {{title}} werden heruntergeladen…",
"downloading": "{{title}} wird heruntergeladen… ({{percentage}} abgeschlossen) - Abschluss {{eta}} - {{speed}}",
"calculating_eta": "{{title}} wird heruntergeladen… ({{percentage}} abgeschlossen) - Verbleibende Zeit wird berechnet…",
"checking_files": "Prüfe Dateien von {{title}}… ({{percentage}} abgeschlossen)"
},
"catalogue": {
"next_page": "Nächste Seite",
"previous_page": "Vorherige Seite"
},
"game_details": {
"open_download_options": "Download-Optionen öffnen",
"download_options_zero": "Keine Download-Optionen",
"download_options_one": "{{count}} Download-Option",
"download_options_other": "{{count}} Download-Optionen",
"updated_at": "Aktualisiert {{updated_at}}",
"install": "Installieren",
"resume": "Fortfahren",
"pause": "Pausieren",
"cancel": "Abbrechen",
"remove": "Entfernen",
"space_left_on_disk": "{{space}} auf Festplatte verfügbar",
"eta": "Abschluss {{eta}}",
"calculating_eta": "Verbleibende Zeit wird berechnet…",
"downloading_metadata": "Metadaten werden heruntergeladen…",
"filter": "Repacks filtern",
"requirements": "Systemanforderungen",
"minimum": "Minimum",
"recommended": "Empfohlen",
"paused": "Pausiert",
"release_date": "Veröffentlicht am {{date}}",
"publisher": "Veröffentlicht von {{publisher}}",
"hours": "Stunden",
"minutes": "Minuten",
"amount_hours": "{{amount}} Stunden",
"amount_minutes": "{{amount}} Minuten",
"accuracy": "{{accuracy}}% Genauigkeit",
"add_to_library": "Zu Bibliothek hinzufügen",
"remove_from_library": "Von Bibliothek entfernen",
"no_downloads": "Keine Downloads verfügbar",
"play_time": "{{amount}} lang gespielt",
"last_time_played": "Zuletzt gespielt {{period}}",
"not_played_yet": "{{title}} wurde noch nicht gespielt",
"next_suggestion": "Nächste Empfehlung",
"play": "Spielen",
"deleting": "Installer wird gelöscht…",
"close": "Schließen",
"playing_now": "Spielt jetzt",
"change": "Ändern",
"repacks_modal_description": "Wähle das Repack, das du herunterladen möchtest",
"select_folder_hint": "Um das Standardverzeichnis zu ändern, gehe zu den <0>Einstellungen</0>",
"download_now": "Jetzt herunterladen",
"no_shop_details": "Shop-Details konnten nicht abgerufen werden.",
"download_options": "Download-Optionen",
"download_path": "Download-Verzeichnis",
"previous_screenshot": "Vorheriger Screenshot",
"next_screenshot": "Nächster Screenshot",
"screenshot": "Screenshot {{number}}",
"open_screenshot": "Screenshot {{number}} öffnen",
"download_settings": "Download-Einstellungen",
"downloader": "Downloader",
"select_executable": "Auswählen",
"no_executable_selected": "Keine ausführbare Datei gewählt",
"open_folder": "Verzeichnis öffnen",
"open_download_location": "Heruntergeladene Dateien anzeigen",
"create_shortcut": "Desktop-Verknüpfung erstellen",
"remove_files": "Dateien entfernen",
"remove_from_library_title": "Bist du dir sicher?",
"remove_from_library_description": "Dies wird {{game}} aus deiner Bibliothek entfernen",
"options": "Optionen",
"executable_section_title": "Ausführbare Datei",
"executable_section_description": "Pfad der Datei, die bei Klick auf \"Play\" ausgeführt wird",
"downloads_secion_title": "Downloads",
"downloads_section_description": "Sieh dir Updates oder andere Versionen dieses Spiels an",
"danger_zone_section_title": "Gefahrenzone",
"danger_zone_section_description": "Entferne dieses Spiel aus deiner Bibliothek oder die von Hydra heruntergeladenen Dateien",
"download_in_progress": "Download erfolgt",
"download_paused": "Download ist pausiert",
"last_downloaded_option": "Letzte Download-Option",
"create_shortcut_success": "Verknüpfung erfolgreich erstellt",
"create_shortcut_error": "Fehler bei Erstellung von Verknüpfung"
},
"activation": {
"title": "Hydra aktivieren",
"installation_id": "Installations ID:",
"enter_activation_code": "Aktivierungscode eingeben",
"message": "Wenn du nicht weißt wo du fragen musst, solltest du dies nicht haben.",
"activate": "Aktivieren",
"loading": "Lädt…"
},
"downloads": {
"resume": "Fortfahren",
"pause": "Pause",
"eta": "Abschluss {{eta}}",
"paused": "Pausiert",
"verifying": "Verifiziere…",
"completed": "Abgeschlossen",
"removed": "Nicht heruntergeladen",
"cancel": "Abbrechen",
"filter": "Heruntergeladene Spiele filtern",
"remove": "Entfernen",
"downloading_metadata": "Metadaten werden heruntergeladen…",
"deleting": "Installer wird entfernt…",
"delete": "Installer entfernen",
"delete_modal_title": "Bist du dir sicher?",
"delete_modal_description": "Dies wird alle Installationsdateien von deinem Computer entfernen",
"install": "Installieren",
"download_in_progress": "Läuft",
"queued_downloads": "Downloads in Warteschlange",
"downloads_completed": "Abgeschlossen",
"queued": "In Warteschlange",
"no_downloads_title": "Welch Leere",
"no_downloads_description": "Du hast mit Hydra noch nichts heruntergeladen, aber es ist nie zu spät anzufangen.",
"checking_files": "Dateien werden überprüft…"
},
"settings": {
"downloads_path": "Download-Pfad",
"change": "Aktualisieren",
"notifications": "Benachrichtigungen",
"enable_download_notifications": "Wenn ein Download abgeschlossen wird",
"enable_repack_list_notifications": "Wenn ein neues Repack hinzugefügt wird",
"real_debrid_api_token_label": "Real-Debrid API Token",
"quit_app_instead_hiding": "Hydra verlassen statt minimieren beim Schließen",
"launch_with_system": "Hydra bei Systemstart starten",
"general": "Allgemein",
"behavior": "Verhalten",
"download_sources": "Download-Quellen",
"language": "Sprache",
"real_debrid_api_token": "API Token",
"enable_real_debrid": "Real-Debrid aktivieren",
"real_debrid_description": "Real-Debrid ist ein unrestriktiver Downloader, der es dir ermöglicht Dateien sofort und mit deiner maximalen Internetgeschwindigkeit herunterzuladen.",
"real_debrid_invalid_token": "API token nicht gültig",
"real_debrid_api_token_hint": "<0>Hier</0> kannst du dir deinen API Token holen",
"real_debrid_free_account_error": "Das Konto \"{{username}}\" ist ein gratis account. Bitte abonniere Real-Debrid",
"real_debrid_linked_message": "Konto \"{{username}}\" verknüpft",
"save_changes": "Änderungen speichern",
"changes_saved": "Änderungen erfolgreich gespeichert",
"download_sources_description": "Hydra wird die Download-Links von diesen Quellen abrufen. Die Quell-URL muss ein direkter Link zu einer .json Datei, welche die Download-Links enthält, sein.",
"validate_download_source": "Validieren",
"remove_download_source": "Entfernen",
"add_download_source": "Quelle hinzufügen",
"download_count_zero": "Keine Download-Option",
"download_count_one": "{{countFormatted}} Download-Option",
"download_count_other": "{{countFormatted}} Download-Optionen",
"download_source_url": "Download Quell-URL",
"add_download_source_description": "Füge die URL, welche die .json Datei enthält, ein",
"download_source_up_to_date": "Auf aktuellem Stand",
"download_source_errored": "Fehlgeschlagen",
"sync_download_sources": "Quellen synchronisieren",
"removed_download_source": "Download-Quelle entfernt",
"added_download_source": "Download-Quelle hinzugefügt",
"download_sources_synced": "Alle Download-Quellen sind synchronisiert",
"insert_valid_json_url": "Füge eine gültige JSON URL ein",
"found_download_option_zero": "Keine Download-Option gefunden",
"found_download_option_one": "{{countFormatted}} Download-Option gefunden",
"found_download_option_other": "{{countFormatted}} Download-Optionen gefunden",
"import": "Importieren"
},
"notifications": {
"download_complete": "Download abgeschlossen",
"game_ready_to_install": "{{title}} ist bereit zur Installation",
"repack_list_updated": "Repack-Liste aktualisiert",
"repack_count_one": "{{count}} Repack hinzugefügt",
"repack_count_other": "{{count}} Repacks hinzugefügt",
"new_update_available": "Version {{version}} verfügbar",
"restart_to_install_update": "Um das Update zu installieren, starte Hydra neu"
},
"system_tray": {
"open": "Hydra öffnen",
"quit": "Schließen"
},
"game_card": {
"no_downloads": "Keine Downloads verfügbar"
},
"binary_not_found_modal": {
"title": "Programme nicht installiert",
"description": "Ausführbare Dateien für Wine oder Lutris wurden auf deinem System nicht gefunden",
"instructions": "Überprüfe die korrekte Installation dieser für deine Linux-Distro, damit das Spiel normal laufen kann"
},
"modal": {
"close": "Knopf schließen"
},
"forms": {
"toggle_password_visibility": "Sichtbarkeit des Passworts umschalten"
},
"user_profile": {
"amount_hours": "{{amount}} Stunden",
"amount_minutes": "{{amount}} Minuten",
"last_time_played": "Zuletzt gespielt {{period}}",
"activity": "Letzte Aktivität",
"library": "Bibliothek",
"total_play_time": "Gesamtspielzeit: {{amount}}",
"no_recent_activity_title": "Hmmm… hier ist nichts",
"no_recent_activity_description": "Du hast in letzter Zeit keine Spiele gespielt. Es wird Zeit das zu ändern!",
"display_name": "Anzeigename",
"saving": "Speichert",
"save": "Speichern",
"edit_profile": "Profil Bearbeiten",
"saved_successfully": "Erfolgreich gespeichert",
"try_again": "Bitte versuche es erneut",
"sign_out_modal_title": "Bist du dir sicher?",
"cancel": "Abbrechen",
"successfully_signed_out": "Erfolgreich abgemeldet",
"sign_out": "Abmelden",
"playing_for": "Spielt {{amount}} lang",
"sign_out_modal_text": "Deine Bibliothek ist mit deinem aktuellen Konto verknüpft. Wenn du dich abmeldest, wird deine Bibliothek nicht mehr sichtbar sein und jeglicher Fortschritt wird nicht gespeichert. Abmelden fortführen?",
"add_friends": "Freunde hinzufügen",
"add": "Hinzufügen",
"friend_code": "Freundescode",
"see_profile": "Profil anzeigen",
"sending": "Sendet",
"friend_request_sent": "Freundschaftsanfrage versendet",
"friends": "Freunde",
"friends_list": "Freundesliste",
"user_not_found": "Nutzer nicht gefunden",
"block_user": "Nutzer blockieren",
"add_friend": "Freund hinzufügen",
"request_sent": "Anfrage versendet",
"request_received": "Anfrage erhalten",
"accept_request": "Anfrage annehmen",
"ignore_request": "Anfrage ignorieren",
"cancel_request": "Anfrage zurückziehen",
"undo_friendship": "Freundschaft kündigen",
"request_accepted": "Anfrage akzeptiert",
"user_blocked_successfully": "Nutzer erfolgreich blockiert",
"user_block_modal_text": "{{displayName}} wird dadurch blockiert",
"blocked_users": "Blockierte Nutzer",
"unblock": "Freigeben",
"no_friends_added": "Du hast noch keine Freunde hinzugefügt",
"pending": "Ausstehend",
"no_pending_invites": "Du hast keine ausstehenden Einladungen",
"no_blocked_users": "Du hast keine blockierten Nutzer",
"friend_code_copied": "Freundescode kopiert",
"undo_friendship_modal_text": "Freundschaft mit {{displayName}} wird dadurch gekündigt"
}
}

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "English",
"app": { "app": {
"successfully_signed_in": "Successfully signed in" "successfully_signed_in": "Successfully signed in"
}, },
@@ -7,10 +6,7 @@
"featured": "Featured", "featured": "Featured",
"trending": "Trending", "trending": "Trending",
"surprise_me": "Surprise me", "surprise_me": "Surprise me",
"no_results": "No results found", "no_results": "No results found"
"start_typing": "Starting typing to search...",
"hot": "🔥 Hot now",
"weekly": "📅 Top games of the week"
}, },
"sidebar": { "sidebar": {
"catalogue": "Catalogue", "catalogue": "Catalogue",
@@ -24,8 +20,7 @@
"home": "Home", "home": "Home",
"queued": "{{title}} (Queued)", "queued": "{{title}} (Queued)",
"game_has_no_executable": "Game has no executable selected", "game_has_no_executable": "Game has no executable selected",
"sign_in": "Sign in", "sign_in": "Sign in"
"friends": "Friends"
}, },
"header": { "header": {
"search": "Search games", "search": "Search games",
@@ -41,8 +36,7 @@
"no_downloads_in_progress": "No downloads in progress", "no_downloads_in_progress": "No downloads in progress",
"downloading_metadata": "Downloading {{title}} metadata…", "downloading_metadata": "Downloading {{title}} metadata…",
"downloading": "Downloading {{title}}… ({{percentage}} complete) - Conclusion {{eta}} - {{speed}}", "downloading": "Downloading {{title}}… ({{percentage}} complete) - Conclusion {{eta}} - {{speed}}",
"calculating_eta": "Downloading {{title}}… ({{percentage}} complete) - Calculating remaining time…", "calculating_eta": "Downloading {{title}}… ({{percentage}} complete) - Calculating remaining time…"
"checking_files": "Checking {{title}} files… ({{percentage}} complete)"
}, },
"catalogue": { "catalogue": {
"next_page": "Next page", "next_page": "Next page",
@@ -118,19 +112,7 @@
"download_paused": "Download paused", "download_paused": "Download paused",
"last_downloaded_option": "Last downloaded option", "last_downloaded_option": "Last downloaded option",
"create_shortcut_success": "Shortcut created successfully", "create_shortcut_success": "Shortcut created successfully",
"create_shortcut_error": "Error creating shortcut", "create_shortcut_error": "Error creating shortcut"
"nsfw_content_title": "This game contains innapropriate content",
"nsfw_content_description": "{{title}} contains content that may not be suitable for all ages. Are you sure you want to continue?",
"allow_nsfw_content": "Continue",
"refuse_nsfw_content": "Go back",
"stats": "Stats",
"download_count": "Downloads",
"player_count": "Active players",
"download_error": "This download option is not available",
"download": "Download",
"executable_path_in_use": "Executable already in use by \"{{game}}\"",
"warning": "Warning:",
"hydra_needs_to_remain_open": "for this download, Hydra needs to remain open util its conclusion. In case Hydra closes before the conclusion, you will lose your progress."
}, },
"activation": { "activation": {
"title": "Activate Hydra", "title": "Activate Hydra",
@@ -162,8 +144,7 @@
"downloads_completed": "Completed", "downloads_completed": "Completed",
"queued": "Queued", "queued": "Queued",
"no_downloads_title": "Such empty", "no_downloads_title": "Such empty",
"no_downloads_description": "You haven't downloaded anything with Hydra yet, but it's never too late to start.", "no_downloads_description": "You haven't downloaded anything with Hydra yet, but it's never too late to start."
"checking_files": "Checking files…"
}, },
"settings": { "settings": {
"downloads_path": "Downloads path", "downloads_path": "Downloads path",
@@ -191,9 +172,12 @@
"validate_download_source": "Validate", "validate_download_source": "Validate",
"remove_download_source": "Remove", "remove_download_source": "Remove",
"add_download_source": "Add source", "add_download_source": "Add source",
"download_count_zero": "No download options", "download_count_zero": "No downloads in list",
"download_count_one": "{{countFormatted}} download option", "download_count_one": "{{countFormatted}} download in list",
"download_count_other": "{{countFormatted}} download options", "download_count_other": "{{countFormatted}} downloads in list",
"download_options_zero": "No download available",
"download_options_one": "{{countFormatted}} download available",
"download_options_other": "{{countFormatted}} downloads available",
"download_source_url": "Download source URL", "download_source_url": "Download source URL",
"add_download_source_description": "Insert the URL containing the .json file", "add_download_source_description": "Insert the URL containing the .json file",
"download_source_up_to_date": "Up-to-date", "download_source_up_to_date": "Up-to-date",
@@ -206,27 +190,14 @@
"found_download_option_zero": "No download option found", "found_download_option_zero": "No download option found",
"found_download_option_one": "Found {{countFormatted}} download option", "found_download_option_one": "Found {{countFormatted}} download option",
"found_download_option_other": "Found {{countFormatted}} download options", "found_download_option_other": "Found {{countFormatted}} download options",
"import": "Import", "import": "Import"
"public": "Public",
"private": "Private",
"friends_only": "Friends only",
"privacy": "Privacy",
"profile_visibility": "Profile visibility",
"profile_visibility_description": "Choose who can see your profile and library",
"required_field": "This field is required",
"source_already_exists": "This source has been already added",
"must_be_valid_url": "The source must be a valid URL",
"blocked_users": "Blocked users",
"user_unblocked": "User has been unblocked"
}, },
"notifications": { "notifications": {
"download_complete": "Download complete", "download_complete": "Download complete",
"game_ready_to_install": "{{title}} is ready to install", "game_ready_to_install": "{{title}} is ready to install",
"repack_list_updated": "Repack list updated", "repack_list_updated": "Repack list updated",
"repack_count_one": "{{count}} repack added", "repack_count_one": "{{count}} repack added",
"repack_count_other": "{{count}} repacks added", "repack_count_other": "{{count}} repacks added"
"new_update_available": "Version {{version}} available",
"restart_to_install_update": "Restart Hydra to install the update"
}, },
"system_tray": { "system_tray": {
"open": "Open Hydra", "open": "Open Hydra",
@@ -266,51 +237,6 @@
"successfully_signed_out": "Successfully signed out", "successfully_signed_out": "Successfully signed out",
"sign_out": "Sign out", "sign_out": "Sign out",
"playing_for": "Playing for {{amount}}", "playing_for": "Playing for {{amount}}",
"sign_out_modal_text": "Your library is linked with your current account. When signing out, your library will not be visible anymore, and any progress will not be saved. Continue with sign out?", "sign_out_modal_text": "Your library is linked with your current account. When signing out, your library will not be visible anymore, and any progress will not be saved. Continue with sign out?"
"add_friends": "Add Friends",
"add": "Add",
"friend_code": "Friend code",
"see_profile": "See profile",
"sending": "Sending",
"friend_request_sent": "Friend request sent",
"friends": "Friends",
"friends_list": "Friends list",
"user_not_found": "User not found",
"block_user": "Block user",
"add_friend": "Add friend",
"request_sent": "Request sent",
"request_received": "Request received",
"accept_request": "Accept request",
"ignore_request": "Ignore request",
"cancel_request": "Cancel request",
"undo_friendship": "Undo friendship",
"request_accepted": "Request accepted",
"user_blocked_successfully": "User blocked successfully",
"user_block_modal_text": "This will block {{displayName}}",
"blocked_users": "Blocked users",
"unblock": "Unblock",
"no_friends_added": "You still don't have added friends",
"pending": "Pending",
"no_pending_invites": "You have no pending invites",
"no_blocked_users": "You have no blocked users",
"friend_code_copied": "Friend code copied",
"undo_friendship_modal_text": "This will undo your friendship with {{displayName}}",
"privacy_hint": "To adjust who can see this, go to the <0>Settings</0>",
"locked_profile": "This profile is private",
"image_process_failure": "Failure while processing the image",
"required_field": "This field is required",
"displayname_min_length": "Display name must be at least 3 characters long",
"displayname_max_length": "Display name must be at most 50 characters long",
"report_profile": "Report this profile",
"report_reason": "Why are you reporting this profile?",
"report_description": "Additional information",
"report_description_placeholder": "Additional information",
"report": "Report",
"report_reason_hate": "Hate speech",
"report_reason_sexual_content": "Sexual content",
"report_reason_violence": "Violence",
"report_reason_spam": "Spam",
"report_reason_other": "Other",
"profile_reported": "Profile reported"
} }
} }

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "Español",
"app": { "app": {
"successfully_signed_in": "Sesión iniciada correctamente" "successfully_signed_in": "Sesión iniciada correctamente"
}, },
@@ -7,10 +6,7 @@
"featured": "Destacado", "featured": "Destacado",
"trending": "Tendencias", "trending": "Tendencias",
"surprise_me": "¡Sorpréndeme!", "surprise_me": "¡Sorpréndeme!",
"no_results": "No se encontraron resultados", "no_results": "No se encontraron resultados"
"hot": "🔥 Caliente ahora",
"weekly": "📅 Los mejores juegos de la semana",
"start_typing": "Empieza a escribir para buscar..."
}, },
"sidebar": { "sidebar": {
"catalogue": "Catálogo", "catalogue": "Catálogo",
@@ -24,8 +20,7 @@
"home": "Inicio", "home": "Inicio",
"queued": "{{title}} (En Cola)", "queued": "{{title}} (En Cola)",
"game_has_no_executable": "El juego no tiene un ejecutable", "game_has_no_executable": "El juego no tiene un ejecutable",
"sign_in": "Iniciar sesión", "sign_in": "Iniciar sesión"
"friends": "Amigos"
}, },
"header": { "header": {
"search": "Buscar juegos", "search": "Buscar juegos",
@@ -41,8 +36,7 @@
"no_downloads_in_progress": "Sin descargas en progreso", "no_downloads_in_progress": "Sin descargas en progreso",
"downloading_metadata": "Descargando metadatos de {{title}}…", "downloading_metadata": "Descargando metadatos de {{title}}…",
"downloading": "Descargando {{title}}… ({{percentage}} completado) - Finalizando {{eta}} - {{speed}}", "downloading": "Descargando {{title}}… ({{percentage}} completado) - Finalizando {{eta}} - {{speed}}",
"calculating_eta": "Descargando {{title}}… ({{percentage}} completado) - Calculando tiempo restante…", "calculating_eta": "Descargando {{title}}… ({{percentage}} completado) - Calculando tiempo restante…"
"checking_files": "Verificando archivos de {{title}}… ({{percentage}} completado)"
}, },
"catalogue": { "catalogue": {
"next_page": "Siguiente página", "next_page": "Siguiente página",
@@ -53,7 +47,7 @@
"download_options_zero": "No hay opciones de descargas disponibles", "download_options_zero": "No hay opciones de descargas disponibles",
"download_options_one": "{{count}} opción de descarga", "download_options_one": "{{count}} opción de descarga",
"download_options_other": "{{count}} opciones de descargas", "download_options_other": "{{count}} opciones de descargas",
"updated_at": "Actualizado el: {{updated_at}}", "updated_at": "Actualizado el {{updated_at}}",
"install": "Instalar", "install": "Instalar",
"resume": "Continuar", "resume": "Continuar",
"pause": "Pausa", "pause": "Pausa",
@@ -79,7 +73,7 @@
"remove_from_library": "Eliminar de la biblioteca", "remove_from_library": "Eliminar de la biblioteca",
"no_downloads": "No hay descargas disponibles", "no_downloads": "No hay descargas disponibles",
"play_time": "Jugado por {{amount}}", "play_time": "Jugado por {{amount}}",
"last_time_played": "Jugado por última vez: {{period}}", "last_time_played": "Jugado por última vez {{period}}",
"not_played_yet": "Aún no has jugado a {{title}}", "not_played_yet": "Aún no has jugado a {{title}}",
"next_suggestion": "Siguiente sugerencia", "next_suggestion": "Siguiente sugerencia",
"play": "Jugar", "play": "Jugar",
@@ -98,7 +92,7 @@
"screenshot": "Captura {{number}}", "screenshot": "Captura {{number}}",
"open_screenshot": "Abrir captura {{number}}", "open_screenshot": "Abrir captura {{number}}",
"download_settings": "Ajustes de descarga", "download_settings": "Ajustes de descarga",
"downloader": "Método de descarga", "downloader": "Descargador",
"select_executable": "Seleccionar", "select_executable": "Seleccionar",
"no_executable_selected": "No se seleccionó un ejecutable", "no_executable_selected": "No se seleccionó un ejecutable",
"open_folder": "Abrir carpeta", "open_folder": "Abrir carpeta",
@@ -112,23 +106,13 @@
"executable_section_description": "Ruta del archivo que se ejecutará cuando se presione \"Jugar\"", "executable_section_description": "Ruta del archivo que se ejecutará cuando se presione \"Jugar\"",
"downloads_secion_title": "Descargas", "downloads_secion_title": "Descargas",
"downloads_section_description": "Buscar actualizaciones u otras versiones de este juego", "downloads_section_description": "Buscar actualizaciones u otras versiones de este juego",
"danger_zone_section_title": "Opciones Avanzadas", "danger_zone_section_title": "Zona de Peligro",
"danger_zone_section_description": "Eliminar este juego de tu librería o los archivos descargados por Hydra (Esto solo eliminará los archivos de instalación y no el juego instalado)", "danger_zone_section_description": "Eliminar este juego de tu librería o los archivos descargados por Hydra",
"download_in_progress": "Descarga en progreso", "download_in_progress": "Descarga en progreso",
"download_paused": "Descarga pausada", "download_paused": "Descarga pausada",
"last_downloaded_option": "Última opción descargada", "last_downloaded_option": "Última opción descargada",
"create_shortcut_success": "Atajo creado con éxito", "create_shortcut_success": "Atajo creado con éxito",
"create_shortcut_error": "Error al crear un atajo", "create_shortcut_error": "Error al crear un atajo"
"allow_nsfw_content": "Continuar",
"download": "Descargar",
"download_count": "Descargas",
"download_error": "Esta opción de descarga no está disponible.",
"executable_path_in_use": "Ejecutable ya en uso por \"{{game}}\"",
"nsfw_content_description": "{{title}} incluye contenido que puede no ser adecuado para todas las edades. \n¿Estás seguro de que quieres continuar?",
"nsfw_content_title": "Este juego contiene contenido inapropiado.",
"player_count": "Jugadores activos",
"refuse_nsfw_content": "Volver",
"stats": "Estadísticas"
}, },
"activation": { "activation": {
"title": "Activar Hydra", "title": "Activar Hydra",
@@ -153,15 +137,14 @@
"deleting": "Eliminando instalador…", "deleting": "Eliminando instalador…",
"delete": "Eliminar instalador", "delete": "Eliminar instalador",
"delete_modal_title": "¿Estás seguro?", "delete_modal_title": "¿Estás seguro?",
"delete_modal_description": "Esto eliminará todos los archivos de la instalación del repack del juego de tu computadora. (Si ya instalaste el juego, puedes eliminar esto, no afectará al juego)", "delete_modal_description": "Esto eliminará todos los archivos de instalación de tu computadora.",
"install": "Instalar", "install": "Instalar",
"download_in_progress": "En progreso", "download_in_progress": "En progreso",
"queued_downloads": "Descargas en cola", "queued_downloads": "Descargas en cola",
"downloads_completed": "Completado", "downloads_completed": "Completado",
"queued": "En cola", "queued": "En cola",
"no_downloads_title": "Esto está tan... vacío", "no_downloads_title": "Esto está tan... vacío",
"no_downloads_description": "No has descargado nada con Hydra... aún, ¡pero nunca es tarde para comenzar!.", "no_downloads_description": "No has descargado nada con Hydra... aún, ¡pero nunca es tarde para comenzar!."
"checking_files": "Verificando archivos…"
}, },
"settings": { "settings": {
"downloads_path": "Ruta de descarga", "downloads_path": "Ruta de descarga",
@@ -178,7 +161,7 @@
"language": "Idioma", "language": "Idioma",
"real_debrid_api_token": "Token API", "real_debrid_api_token": "Token API",
"enable_real_debrid": "Activar Real-Debrid", "enable_real_debrid": "Activar Real-Debrid",
"real_debrid_description": "Real-Debrid es una forma de descargar sin restricciones archivos instantáneamente con la máxima velocidad de tu internet.", "real_debrid_description": "Real-Debrid es un descargador sin restricciones que te permite descargar archivos instantáneamente con la máxima velocidad de tu internet.",
"real_debrid_invalid_token": "Token de API inválido", "real_debrid_invalid_token": "Token de API inválido",
"real_debrid_api_token_hint": "Puedes obtener tu clave de API <0>aquí</0>", "real_debrid_api_token_hint": "Puedes obtener tu clave de API <0>aquí</0>",
"real_debrid_free_account_error": "La cuenta \"{{username}}\" es una cuenta gratuita. Por favor, suscríbete a Real-Debrid", "real_debrid_free_account_error": "La cuenta \"{{username}}\" es una cuenta gratuita. Por favor, suscríbete a Real-Debrid",
@@ -192,6 +175,9 @@
"download_count_zero": "No hay descargas en la lista", "download_count_zero": "No hay descargas en la lista",
"download_count_one": "{{countFormatted}} descarga en la lista", "download_count_one": "{{countFormatted}} descarga en la lista",
"download_count_other": "{{countFormatted}} descargas en la lista", "download_count_other": "{{countFormatted}} descargas en la lista",
"download_options_zero": "No hay descargas disponibles",
"download_options_one": "{{countFormatted}} descarga disponible",
"download_options_other": "{{countFormatted}} descargas disponibles",
"download_source_url": "Descargar URL de origen", "download_source_url": "Descargar URL de origen",
"add_download_source_description": "Introduce la URL con el archivo .json", "add_download_source_description": "Introduce la URL con el archivo .json",
"download_source_up_to_date": "Al día", "download_source_up_to_date": "Al día",
@@ -204,30 +190,14 @@
"found_download_option_zero": "No se encontró una opción de descarga", "found_download_option_zero": "No se encontró una opción de descarga",
"found_download_option_one": "Se encontró {{countFormatted}} opción de descarga", "found_download_option_one": "Se encontró {{countFormatted}} opción de descarga",
"found_download_option_other": "Se encontraron {{countFormatted}} opciones de descarga", "found_download_option_other": "Se encontraron {{countFormatted}} opciones de descarga",
"import": "Importar", "import": "Importar"
"blocked_users": "Usuarios bloqueados",
"download_options_one": "",
"download_options_other": "",
"download_options_zero": "",
"friends_only": "solo amigos",
"must_be_valid_url": "La fuente debe ser una URL válida.",
"privacy": "Privacidad",
"private": "Privado",
"profile_visibility": "Visibilidad del perfil",
"profile_visibility_description": "Elige quién puede ver tu perfil y biblioteca",
"public": "Público",
"required_field": "Este campo es obligatorio",
"source_already_exists": "Esta fuente ya ha sido agregada.",
"user_unblocked": "El usuario ha sido desbloqueado"
}, },
"notifications": { "notifications": {
"download_complete": "Descarga completada", "download_complete": "Descarga completada",
"game_ready_to_install": "{{title}} está listo para instalarse", "game_ready_to_install": "{{title}} está listo para instalarse",
"repack_list_updated": "Lista de repacks actualizadas", "repack_list_updated": "Lista de repacks actualizadas",
"repack_count_one": "{{count}} repack ha sido añadido", "repack_count_one": "{{count}} repack ha sido añadido",
"repack_count_other": "{{count}} repacks añadidos", "repack_count_other": "{{count}} repacks añadidos"
"new_update_available": "Version {{version}} disponible",
"restart_to_install_update": "Reinicia Hydra para instalar la actualización"
}, },
"system_tray": { "system_tray": {
"open": "Abrir Hydra", "open": "Abrir Hydra",
@@ -250,13 +220,13 @@
"user_profile": { "user_profile": {
"amount_hours": "{{amount}} horas", "amount_hours": "{{amount}} horas",
"amount_minutes": "{{amount}} minutos", "amount_minutes": "{{amount}} minutos",
"last_time_played": "Última vez jugado: {{period}}", "last_time_played": "Última vez jugado {{period}}",
"activity": "Actividad reciente", "activity": "Actividad reciente",
"library": "Biblioteca", "library": "Biblioteca",
"total_play_time": "Total de tiempo jugado: {{amount}}", "total_play_time": "Total de tiempo jugado: {{amount}}",
"no_recent_activity_title": "Que raro, no hay nada por acá...", "no_recent_activity_title": "Que raro, no hay nada por acá, ¿que tal si jugamos algo para empezar?",
"no_recent_activity_description": "No has jugado ningún juego recientemente, ¡vamos a cambiar eso ahora!", "no_recent_activity_description": "No has jugado ningún juego recientemente, ¡vamos a cambiar eso ahora!",
"display_name": "Nombre en pantalla", "display_name": "Nombre a mostrar",
"saving": "Guardando", "saving": "Guardando",
"save": "Guardar", "save": "Guardar",
"edit_profile": "Editar perfil", "edit_profile": "Editar perfil",
@@ -267,52 +237,6 @@
"successfully_signed_out": "Sesión cerrada exitosamente", "successfully_signed_out": "Sesión cerrada exitosamente",
"sign_out": "Cerrar sesión", "sign_out": "Cerrar sesión",
"playing_for": "Jugando por {{amount}}", "playing_for": "Jugando por {{amount}}",
"sign_out_modal_text": "Tu biblioteca se ha vinculado con tu cuenta. Cuando cierres sesión, tú biblioteca ya no será visible y cualquier progreso no se guardará. ¿Continuar con el cierre de sesión?", "sign_out_modal_text": "Tu biblioteca se ha vinculado con tu cuenta. Cuando cierres sesión, tú biblioteca ya no será visible y cualquier progreso no se guardará. ¿Continuar con el cierre de sesión?"
"add_friends": "Añadir amigos",
"add": "Añadir",
"friend_code": "Código de amigo",
"see_profile": "Ver perfil",
"sending": "Enviando",
"friend_request_sent": "Solicitud de amistad enviada",
"friends": "Amigos",
"friends_list": "Lista de amigos",
"user_not_found": "Usuario no encontrado",
"block_user": "Bloquear usuario",
"add_friend": "Añadir amigo",
"request_sent": "Solicitud enviada",
"request_received": "Solicitud recibida",
"accept_request": "Aceptar solicitud",
"ignore_request": "Ignorar solicitud",
"cancel_request": "Cancelar solicitud",
"undo_friendship": "Eliminar amistad",
"request_accepted": "Solicitud aceptada",
"user_blocked_successfully": "Usuario bloqueado exitosamente",
"user_block_modal_text": "Esto va a bloquear a {{displayName}}",
"blocked_users": "Usuarios bloqueados",
"unblock": "Desbloquear",
"no_friends_added": "Todavía no tienes amigos añadidos",
"pending": "Pendiente",
"no_pending_invites": "No tienes invitaciones pendientes",
"no_blocked_users": "No has bloqueado a ningún usuario",
"friend_code_copied": "Código de amigo copiado",
"undo_friendship_modal_text": "Esto deshará tu amistad con {{displayName}}",
"displayname_max_length": "El nombre para mostrar debe tener como máximo 50 caracteres",
"displayname_min_length": "El nombre para mostrar debe tener al menos 3 caracteres",
"locked_profile": "Este perfil es privado.",
"privacy_hint": "Para ajustar quién puede ver esto, ve a <0>Configuración</0>.",
"profile_locked": "",
"profile_reported": "Perfil reportado",
"report": "Informe",
"report_description": "Información adicional",
"report_description_placeholder": "Información adicional",
"report_profile": "Reportar este perfil",
"report_reason": "¿Por qué estás denunciando este perfil?",
"report_reason_hate": "Discurso de odio",
"report_reason_other": "Otro",
"report_reason_sexual_content": "Contenido sexual",
"report_reason_spam": "Correo basura",
"report_reason_violence": "Violencia",
"required_field": "Este campo es obligatorio",
"image_process_failure": "Error al procesar la imagen"
} }
} }

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "فارسی",
"home": { "home": {
"featured": "پیشنهادی", "featured": "پیشنهادی",
"trending": "پرطرفدار", "trending": "پرطرفدار",

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "Français",
"home": { "home": {
"featured": "En vedette", "featured": "En vedette",
"trending": "Tendance", "trending": "Tendance",

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "Magyar",
"home": { "home": {
"featured": "Featured", "featured": "Featured",
"trending": "Népszerű", "trending": "Népszerű",

View File

@@ -1,256 +1,134 @@
{ {
"language_name": "Bahasa Indonesia",
"app": {
"successfully_signed_in": "Berhasil masuk"
},
"home": { "home": {
"featured": "Unggulan", "featured": "Unggulan",
"trending": "Sedang Tren", "trending": "Trending",
"surprise_me": "Kejutkan saya", "surprise_me": "Kejutkan Saya",
"no_results": "Tidak ada hasil ditemukan" "no_results": "Tidak ada hasil"
}, },
"sidebar": { "sidebar": {
"catalogue": "Katalog", "catalogue": "Katalog",
"downloads": "Unduhan", "downloads": "Unduhan",
"settings": "Pengaturan", "settings": "Pengaturan",
"my_library": "Perpustakaan saya", "my_library": "Koleksi saya",
"downloading_metadata": "{{title}} (Mengunduh metadata…)", "downloading_metadata": "{{title}} (Mengunduh metadata…)",
"paused": "{{title}} (Dijeda)", "paused": "{{title}} (Terhenti)",
"downloading": "{{title}} ({{percentage}} - Mengunduh…)", "downloading": "{{title}} ({{percentage}} - Mengunduh…)",
"filter": "Filter perpustakaan", "filter": "Filter koleksi",
"home": "Beranda", "home": "Beranda"
"queued": "{{title}} (Antrian)",
"game_has_no_executable": "Game tidak punya file eksekusi yang dipilih",
"sign_in": "Masuk"
}, },
"header": { "header": {
"search": "Cari game", "search": "Pencarian",
"home": "Beranda", "home": "Beranda",
"catalogue": "Katalog", "catalogue": "Katalog",
"downloads": "Unduhan", "downloads": "Unduhan",
"search_results": "Hasil pencarian", "search_results": "Hasil pencarian",
"settings": "Pengaturan", "settings": "Pengaturan"
"version_available_install": "Versi {{version}} tersedia. Klik di sini untuk restart dan instal.",
"version_available_download": "Versi {{version}} tersedia. Klik di sini untuk unduh."
}, },
"bottom_panel": { "bottom_panel": {
"no_downloads_in_progress": "Tidak ada unduhan yang sedang berjalan", "no_downloads_in_progress": "Tidak ada unduhan berjalan",
"downloading_metadata": "Mengunduh metadata {{title}}", "downloading_metadata": "Mengunduh metadata {{title}}...",
"downloading": "Mengunduh {{title}}… ({{percentage}} selesai) - Estimasi selesai {{eta}} - {{speed}}", "downloading": "Mengunduh {{title}}… ({{percentage}} selesai) - Perkiraan {{eta}} - {{speed}}"
"calculating_eta": "Mengunduh {{title}}… ({{percentage}} selesai) - Menghitung waktu yang tersisa…",
"checking_files": "Memeriksa file {{title}}… ({{percentage}} selesai)"
}, },
"catalogue": { "catalogue": {
"next_page": "Halaman Berikutnya", "next_page": "Halaman berikutnya",
"previous_page": "Halaman Sebelumnya" "previous_page": "Halaman sebelumnya"
}, },
"game_details": { "game_details": {
"open_download_options": "Buka opsi unduhan", "open_download_options": "Buka opsi unduhan",
"download_options_zero": "Tidak ada opsi unduhan", "download_options_zero": "Tidak ada opsi unduhan",
"download_options_one": "{{count}} opsi unduhan", "download_options_one": "{{count}} opsi unduhan",
"download_options_other": "{{count}} opsi unduhan", "download_options_other": "{{count}} opsi unduhan",
"updated_at": "Diperbarui pada {{updated_at}}", "updated_at": "Diperbarui {{updated_at}}",
"install": "Instal", "install": "Install",
"resume": "Lanjutkan", "resume": "Lanjutkan",
"pause": "Jeda", "pause": "Hentikan sementara",
"cancel": "Batal", "cancel": "Batalkan",
"remove": "Hapus", "remove": "Hapus",
"space_left_on_disk": "{{space}} tersisa di disk", "space_left_on_disk": "{{space}} tersisa pada disk",
"eta": "Estimasi {{eta}}", "eta": "Perkiraan {{eta}}",
"calculating_eta": "Menghitung waktu yang tersisa…",
"downloading_metadata": "Mengunduh metadata…", "downloading_metadata": "Mengunduh metadata…",
"filter": "Filter repack", "filter": "Saring repacks",
"requirements": "Persyaratan sistem", "requirements": "Keperluan sistem",
"minimum": "Minimum", "minimum": "Minimum",
"recommended": "Dianjurkan", "recommended": "Rekomendasi",
"paused": "Dijeda",
"release_date": "Dirilis pada {{date}}", "release_date": "Dirilis pada {{date}}",
"publisher": "Diterbitkan oleh {{publisher}}", "publisher": "Dipublikasikan oleh {{publisher}}",
"hours": "jam", "hours": "jam",
"minutes": "menit", "minutes": "menit",
"amount_hours": "{{amount}} jam", "amount_hours": "{{amount}} jam",
"amount_minutes": "{{amount}} menit", "amount_minutes": "{{amount}} menit",
"accuracy": "{{accuracy}}% akurasi", "accuracy": "{{accuracy}}% akurasi",
"add_to_library": "Tambah ke perpustakaan", "add_to_library": "Tambahkan ke koleksi",
"remove_from_library": "Hapus dari perpustakaan", "remove_from_library": "Hapus dari koleksi",
"no_downloads": "Tidak ada yang bisa diunduh", "no_downloads": "Tidak ada unduhan tersedia",
"play_time": "Dimainkan selama {{amount}}", "play_time": "Dimainkan selama {{amount}}",
"last_time_played": "Terakhir dimainkan {{period}}", "last_time_played": "Terakhir dimainkan {{period}}",
"not_played_yet": "Kamu belum memainkan {{title}}", "not_played_yet": "Kamu belum memainkan {{title}}",
"next_suggestion": "Saran berikutnya", "next_suggestion": "Rekomendasi berikutnya",
"play": "Main", "play": "Mainkan",
"deleting": "Menghapus installer…", "deleting": "Menghapus installer…",
"close": "Tutup", "close": "Tutup",
"playing_now": "Sedang dimainkan", "playing_now": "Memainkan sekarang",
"change": "Ubah", "change": "Ubah",
"repacks_modal_description": "Pilih repack yang ingin kamu unduh", "repacks_modal_description": "Pilih repack yang kamu ingin unduh",
"select_folder_hint": "Untuk ganti folder default, buka <0>Pengaturan</0>", "select_folder_hint": "Untuk merubah folder bawaan, akses melalui",
"download_now": "Unduh sekarang", "download_now": "Unduh sekarang"
"no_shop_details": "Gagal mendapatkan detail toko.",
"download_options": "Opsi unduhan",
"download_path": "Path unduhan",
"previous_screenshot": "Screenshot sebelumnya",
"next_screenshot": "Screenshot berikutnya",
"screenshot": "Screenshot {{number}}",
"open_screenshot": "Buka screenshot {{number}}",
"download_settings": "Pengaturan unduhan",
"downloader": "Pengunduh",
"select_executable": "Pilih",
"no_executable_selected": "Tidak ada file eksekusi yang dipilih",
"open_folder": "Buka folder",
"open_download_location": "Lihat file yang diunduh",
"create_shortcut": "Buat pintasan desktop",
"remove_files": "Hapus file",
"remove_from_library_title": "Apa kamu yakin?",
"remove_from_library_description": "Ini akan menghapus {{game}} dari perpustakaan kamu",
"options": "Opsi",
"executable_section_title": "Eksekusi",
"executable_section_description": "Path file eksekusi saat \"Main\" diklik",
"downloads_secion_title": "Unduhan",
"downloads_section_description": "Cek update atau versi lain dari game ini",
"danger_zone_section_title": "Zona Berbahaya",
"danger_zone_section_description": "Hapus game ini dari perpustakaan kamu atau file yang diunduh oleh Hydra",
"download_in_progress": "Sedang mengunduh",
"download_paused": "Unduhan dijeda",
"last_downloaded_option": "Opsi terakhir diunduh",
"create_shortcut_success": "Pintasan berhasil dibuat",
"create_shortcut_error": "Gagal membuat pintasan"
}, },
"activation": { "activation": {
"title": "Aktifkan Hydra", "title": "Aktivasi Hydra",
"installation_id": "ID Instalasi:", "installation_id": "ID instalasi:",
"enter_activation_code": "Masukkan kode aktivasi kamu", "enter_activation_code": "Masukkan kode aktivasi",
"message": "Kalau tidak tahu harus tanya ke siapa, berarti kamu tidak perlu ini.", "message": "Jika kamu tidak tau dimana bertanya untuk ini, maka kamu tidak seharusnya memiliki ini.",
"activate": "Aktifkan", "activate": "Aktifkan",
"loading": "Memuat…" "loading": "Memuat…"
}, },
"downloads": { "downloads": {
"resume": "Lanjutkan", "resume": "Lanjutkan",
"pause": "Jeda", "pause": "Hentikan sementara",
"eta": "Estimasi {{eta}}", "eta": "Perkiraan {{eta}}",
"paused": "Dijeda", "paused": "Terhenti sementara",
"verifying": "Verifikasi…", "verifying": "Memeriksa…",
"completed": "Selesai", "completed": "Selesai",
"removed": "Tidak diunduh", "cancel": "Batalkan",
"cancel": "Batal", "filter": "Saring game yang diunduh",
"filter": "Filter game yang diunduh",
"remove": "Hapus", "remove": "Hapus",
"downloading_metadata": "Mengunduh metadata…", "downloading_metadata": "Mengunduh metadata…",
"deleting": "Menghapus installer…", "deleting": "Menghapus file instalasi…",
"delete": "Hapus installer", "delete": "Hapus file instalasi",
"delete_modal_title": "Apa kamu yakin?", "delete_modal_title": "Kamu yakin?",
"delete_modal_description": "Ini akan menghapus semua file instalasi dari komputer kamu", "delete_modal_description": "Proses ini akan menghapus semua file instalasi dari komputer kamu",
"install": "Instal", "install": "Install"
"download_in_progress": "Sedang berlangsung",
"queued_downloads": "Unduhan dalam antrian",
"downloads_completed": "Selesai",
"queued": "Dalam antrian",
"no_downloads_title": "Kosong",
"no_downloads_description": "Kamu belum mengunduh apa pun dengan Hydra, tapi belum terlambat untuk mulai.",
"checking_files": "Memeriksa file…"
}, },
"settings": { "settings": {
"downloads_path": "Path unduhan", "downloads_path": "Lokasi unduhan",
"change": "Ganti", "change": "Perbarui",
"notifications": "Notifikasi", "notifications": "Pengingat",
"enable_download_notifications": "Saat unduhan selesai", "enable_download_notifications": "Saat unduhan selesai",
"enable_repack_list_notifications": "Saat ada repack baru", "enable_repack_list_notifications": "Saat repack terbaru ditambahkan",
"real_debrid_api_token_label": "Token API Real-Debrid",
"quit_app_instead_hiding": "Jangan sembunyikan Hydra saat ditutup",
"launch_with_system": "Jalankan Hydra saat sistem dinyalakan",
"general": "Umum",
"behavior": "Perilaku", "behavior": "Perilaku",
"download_sources": "Sumber unduhan", "quit_app_instead_hiding": "Tutup aplikasi alih-alih menyembunyikan aplikasi",
"language": "Bahasa", "launch_with_system": "Jalankan saat memulai sistem"
"real_debrid_api_token": "Token API",
"enable_real_debrid": "Aktifkan Real-Debrid",
"real_debrid_description": "Real-Debrid adalah downloader tanpa batas yang memungkinkan kamu untuk mengunduh file dengan cepat dan pada kecepatan terbaik dari Internet kamu.",
"real_debrid_invalid_token": "Token API tidak valid",
"real_debrid_api_token_hint": "Kamu bisa dapatkan token API di <0>sini</0>",
"real_debrid_free_account_error": "Akun \"{{username}}\" adalah akun gratis. Silakan berlangganan Real-Debrid",
"real_debrid_linked_message": "Akun \"{{username}}\" terhubung",
"save_changes": "Simpan perubahan",
"changes_saved": "Perubahan disimpan berhasil",
"download_sources_description": "Hydra akan mencari link unduhan dari sini. URL harus menuju file .json dengan link unduhan.",
"validate_download_source": "Validasi",
"remove_download_source": "Hapus",
"add_download_source": "Tambahkan sumber",
"download_count_zero": "Tidak ada unduhan dalam daftar",
"download_count_one": "{{countFormatted}} unduhan dalam daftar",
"download_count_other": "{{countFormatted}} unduhan dalam daftar",
"download_options_zero": "Tidak ada unduhan tersedia",
"download_options_one": "{{countFormatted}} unduhan tersedia",
"download_options_other": "{{countFormatted}} unduhan tersedia",
"download_source_url": "URL sumber unduhan",
"add_download_source_description": "Masukkan URL yang berisi file .json",
"download_source_up_to_date": "Terkini",
"download_source_errored": "Terjadi kesalahan",
"sync_download_sources": "Sinkronkan sumber",
"removed_download_source": "Sumber unduhan dihapus",
"added_download_source": "Sumber unduhan ditambahkan",
"download_sources_synced": "Semua sumber unduhan disinkronkan",
"insert_valid_json_url": "Masukkan URL JSON yang valid",
"found_download_option_zero": "Tidak ada opsi unduhan ditemukan",
"found_download_option_one": "Ditemukan {{countFormatted}} opsi unduhan",
"found_download_option_other": "Ditemukan {{countFormatted}} opsi unduhan",
"import": "Impor"
}, },
"notifications": { "notifications": {
"download_complete": "Unduhan selesai", "download_complete": "Unduhan selesai",
"game_ready_to_install": "{{title}} siap untuk diinstal", "game_ready_to_install": "{{title}} sudah siap untuk instalasi",
"repack_list_updated": "Daftar repack diperbarui", "repack_list_updated": "Daftar repack diperbarui",
"repack_count_one": "{{count}} repack ditambahkan", "repack_count_one": "{{count}} repack ditambahkan",
"repack_count_other": "{{count}} repack ditambahkan", "repack_count_other": "{{count}} repack ditambahkan"
"new_update_available": "Versi {{version}} tersedia",
"restart_to_install_update": "Restart Hydra untuk instal pembaruan"
}, },
"system_tray": { "system_tray": {
"open": "Buka Hydra", "open": "Buka Hydra",
"quit": "Keluar" "quit": "Tutup"
}, },
"game_card": { "game_card": {
"no_downloads": "Tidak ada unduhan yang tersedia" "no_downloads": "Tidak ada unduhan tersedia"
}, },
"binary_not_found_modal": { "binary_not_found_modal": {
"title": "Program tidak terpasang", "title": "Program tidak terinstal",
"description": "Executable Wine atau Lutris tidak ditemukan di sistem kamu", "description": "Wine atau Lutris exe tidak ditemukan pada sistem kamu",
"instructions": "Cek cara instalasi yang benar di distro Linux kamu agar game bisa jalan normal" "instructions": "Periksa cara instalasi yang benar pada Linux distro-mu agar game dapat dimainkan dengan benar"
}, },
"modal": { "modal": {
"close": "Tutup" "close": "Tombol tutup"
},
"forms": {
"toggle_password_visibility": "Tampilkan/Sembunyikan kata sandi"
},
"user_profile": {
"amount_hours": "{{amount}} jam",
"amount_minutes": "{{amount}} menit",
"last_time_played": "Terakhir dimainkan {{period}}",
"activity": "Aktivitas terbaru",
"library": "Perpustakaan",
"total_play_time": "Total waktu bermain: {{amount}}",
"no_recent_activity_title": "Hmm… kosong di sini",
"no_recent_activity_description": "Kamu belum main game baru-baru ini. Yuk, mulai main!",
"display_name": "Nama tampilan",
"saving": "Menyimpan",
"save": "Simpan",
"edit_profile": "Edit Profil",
"saved_successfully": "Berhasil disimpan",
"try_again": "Coba lagi yuk",
"sign_out_modal_title": "Apa kamu yakin?",
"cancel": "Batal",
"successfully_signed_out": "Berhasil keluar",
"sign_out": "Keluar",
"playing_for": "Bermain selama {{amount}}",
"sign_out_modal_text": "Perpustakaan kamu terhubung dengan akun saat ini. Saat keluar, perpustakaan kamu tidak akan terlihat lagi, dan progres tidak akan disimpan. Lanjutkan keluar?",
"add_friends": "Tambah Teman",
"add": "Tambah",
"friend_code": "Kode teman",
"see_profile": "Lihat profil",
"sending": "Mengirim",
"friend_request_sent": "Permintaan teman terkirim",
"friends": "Teman",
"friends_list": "Daftar teman",
"user_not_found": "Pengguna tidak ditemukan"
} }
} }

View File

@@ -1,51 +1,18 @@
import en from "./en/translation.json"; export { default as en } from "./en/translation.json";
import ptPT from "./pt-PT/translation.json"; export { default as pt } from "./pt/translation.json";
import ptBR from "./pt-BR/translation.json"; export { default as es } from "./es/translation.json";
import es from "./es/translation.json"; export { default as nl } from "./nl/translation.json";
import nl from "./nl/translation.json"; export { default as fr } from "./fr/translation.json";
import fr from "./fr/translation.json"; export { default as hu } from "./hu/translation.json";
import hu from "./hu/translation.json"; export { default as it } from "./it/translation.json";
import it from "./it/translation.json"; export { default as pl } from "./pl/translation.json";
import de from "./de/translation.json"; export { default as ru } from "./ru/translation.json";
import pl from "./pl/translation.json"; export { default as tr } from "./tr/translation.json";
import ru from "./ru/translation.json"; export { default as be } from "./be/translation.json";
import tr from "./tr/translation.json"; export { default as uk } from "./uk/translation.json";
import be from "./be/translation.json"; export { default as zh } from "./zh/translation.json";
import uk from "./uk/translation.json"; export { default as id } from "./id/translation.json";
import zh from "./zh/translation.json"; export { default as ko } from "./ko/translation.json";
import id from "./id/translation.json"; export { default as da } from "./da/translation.json";
import ko from "./ko/translation.json"; export { default as ar } from "./ar/translation.json";
import da from "./da/translation.json"; export { default as fa } from "./fa/translation.json";
import ar from "./ar/translation.json";
import fa from "./fa/translation.json";
import ro from "./ro/translation.json";
import ca from "./ca/translation.json";
import kk from "./kk/translation.json";
import cs from "./cs/translation.json";
export default {
"pt-BR": ptBR,
"pt-PT": ptPT,
en,
de,
es,
nl,
fr,
hu,
it,
pl,
ru,
tr,
be,
uk,
zh,
id,
ko,
da,
ar,
fa,
ro,
ca,
kk,
cs,
};

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "Italiano",
"home": { "home": {
"featured": "In primo piano", "featured": "In primo piano",
"trending": "Di tendenza", "trending": "Di tendenza",

View File

@@ -1,243 +0,0 @@
{
"language_name": "қазақ тілі",
"app": {
"successfully_signed_in": "Сәтті кіру"
},
"home": {
"featured": "Ұсынылған",
"trending": "Трендте",
"surprise_me": "Таңқалдыр",
"no_results": "Ештеңе табылмады"
},
"sidebar": {
"catalogue": "Каталог",
"downloads": "Жүктеулер",
"settings": "Параметрлер",
"my_library": "Кітапхана",
"downloading_metadata": "{{title}} (Метадеректерді жүктеу…)",
"paused": "{{title}} (Тоқтатылды)",
"downloading": "{{title}} ({{percentage}} - Жүктеу…)",
"filter": "Кітапхана фильтрі",
"home": "Басты бет",
"queued": "{{title}} (Кезекте)",
"game_has_no_executable": "Ойынды іске қосу файлы таңдалмаған",
"sign_in": "Кіру"
},
"header": {
"search": "Іздеу",
"home": "Басты бет",
"catalogue": "Каталог",
"downloads": "Жүктеулер",
"search_results": "Іздеу нәтижелері",
"settings": "Параметрлер",
"version_available_install": "Қол жетімді нұсқа {{version}}. Қайта іске қосу және орнату үшін мұнда басыңыз.",
"version_available_download": "Қол жетімді нұсқа {{version}}. Жүктеу үшін мұнда басыңыз."
},
"bottom_panel": {
"no_downloads_in_progress": "Белсенді жүктеулер жоқ",
"downloading_metadata": "Метадеректерді жүктеу {{title}}…",
"downloading": "Жүктеу {{title}}… ({{percentage}} аяқталды) - Аяқтау {{eta}} - {{speed}}",
"calculating_eta": "Жүктеу {{title}}… ({{percentage}} аяқталды) - Қалған уақытты есептеу…"
},
"catalogue": {
"next_page": "Келесі бет",
"previous_page": "Алдыңғы бет"
},
"game_details": {
"open_download_options": "Жүктеу нұсқаларын ашу",
"download_options_zero": "Жүктеу нұсқалары жоқ",
"download_options_one": "{{count}} жүктеу нұсқасы",
"download_options_other": "{{count}} жүктеу нұсқалары",
"updated_at": "Жаңартылды {{updated_at}}",
"install": "Орнату",
"resume": "Жандандыру",
"pause": "Тоқтату",
"cancel": "Болдырмау",
"remove": "Жою",
"space_left_on_disk": "{{space}} бос орын",
"eta": "Аяқтау {{eta}}",
"calculating_eta": "Қалған уақытты есептеу…",
"downloading_metadata": "Метадеректерді жүктеу…",
"filter": "Репактар фильтрі",
"requirements": "Жүйелік талаптар",
"minimum": "Минималды",
"recommended": "Ұсынылған",
"paused": "Тоқтатылды",
"release_date": "Шыққан күні {{date}}",
"publisher": "Баспагер {{publisher}}",
"hours": "сағат",
"minutes": "минут",
"amount_hours": "{{amount}} сағат",
"amount_minutes": "{{amount}} минут",
"accuracy": "дәлдік {{accuracy}}%",
"add_to_library": "Кітапханаға қосу",
"remove_from_library": "Кітапханадан жою",
"no_downloads": "Жүктеулер жоқ",
"play_time": "Ойнау уақыты {{amount}}",
"last_time_played": "Соңғы ойнаған уақыт {{period}}",
"not_played_yet": "Сіз {{title}} ойнамағансыз",
"next_suggestion": "Келесі ұсыныс",
"play": "Ойнау",
"deleting": "Орнатушыны жою…",
"close": "Жабу",
"playing_now": "Қазір ойнап жатыр",
"change": "Өзгерту",
"repacks_modal_description": "Жүктеу үшін репакты таңдаңыз",
"select_folder_hint": "Әдепкі жүктеу қалтасын өзгерту үшін <0>Параметрлер</0> ашыңыз",
"download_now": "Қазір жүктеу",
"no_shop_details": "Сипаттаманы алу мүмкін болмады",
"download_options": "Жүктеу нұсқалары",
"download_path": "Жүктеу жолы",
"previous_screenshot": "Алдыңғы скриншот",
"next_screenshot": "Келесі скриншот",
"screenshot": "Скриншот {{number}}",
"open_screenshot": "Скриншотты ашу {{number}}",
"download_settings": "Жүктеу параметрлері",
"downloader": "Жүктегіш",
"select_executable": "Таңдау",
"no_executable_selected": "Файл таңдалмаған",
"open_folder": "Қалтаны ашу",
"open_download_location": "Жүктеу қалтасын қарау",
"create_shortcut": "Жұмыс үстелінде жарлық жасау",
"remove_files": "Файлдарды жою",
"remove_from_library_title": "Сіз сенімдісіз бе?",
"remove_from_library_description": "{{game}} сіздің кітапханаңыздан жойылады.",
"options": "Параметрлер",
"executable_section_title": "Файл",
"executable_section_description": "\"Ойнау\" батырмасын басқанда іске қосылатын файл жолы",
"downloads_secion_title": "Жүктеулер",
"downloads_section_description": "Ойынның жаңартулары немесе басқа нұсқалары бар-жоғын тексеру",
"danger_zone_section_title": "Қауіпті аймақ",
"danger_zone_section_description": "Осы ойынды кітапханаңыздан жою немесе Hydra жүктеген файлдарды жою",
"download_in_progress": "Жүктеу жүріп жатыр",
"download_paused": "Жүктеу тоқтатылды",
"last_downloaded_option": "Соңғы жүктеу нұсқасы",
"create_shortcut_success": "Жарлық жасалды",
"create_shortcut_error": "Жарлық жасау мүмкін болмады"
},
"activation": {
"title": "Hydra-ны белсендіру",
"installation_id": "Орнату ID:",
"enter_activation_code": "Активтендіру кодын енгізіңіз",
"message": "Егер оның қайдан алуға болатынын білмесеңіз, сізде оның болмауы керек.",
"activate": "Белсендіру",
"loading": "Жүктеу…"
},
"downloads": {
"resume": "Жандандыру",
"pause": "Тоқтату",
"eta": "Аяқтау {{eta}}",
"paused": "Тоқтатылды",
"verifying": "Тексеру…",
"completed": "Аяқталды",
"removed": "Жүктелмеген",
"cancel": "Болдырмау",
"filter": "Жүктелген ойындар фильтрі",
"remove": "Жою",
"downloading_metadata": "Метадеректерді жүктеу…",
"deleting": "Орнатушыны жою…",
"delete": "Орнатушыны жою",
"delete_modal_title": "Сіз сенімдісіз бе?",
"delete_modal_description": "Бұл барлық орнатушыларды компьютеріңізден жояды",
"install": "Орнату",
"download_in_progress": "Жүктеу жүріп жатыр",
"queued_downloads": "Кезектегі жүктеулер",
"downloads_completed": "Аяқталды",
"queued": "Кезекте",
"no_downloads_title": "Мұнда бос...",
"no_downloads_description": "Сіз Hydra арқылы әлі ештеңе жүктемегенсіз, бірақ бастау ешқашан кеш емес."
},
"settings": {
"downloads_path": "Жүктеу жолы",
"change": "Өзгерту",
"notifications": "Хабарламалар",
"enable_download_notifications": "Жүктеу аяқталғанда",
"enable_repack_list_notifications": "Жаңа репак қосылғанда",
"real_debrid_api_token_label": "Real-Debrid API-токен",
"quit_app_instead_hiding": "Hydra-ны трейге жасырудың орнына жабу",
"launch_with_system": "Жүйемен бірге Hydra-ны іске қосу",
"general": "Жалпы",
"behavior": "Мінез-құлық",
"download_sources": "Жүктеу көздері",
"language": "Тіл",
"real_debrid_api_token": "API Кілті",
"enable_real_debrid": "Real-Debrid-ті қосу",
"real_debrid_description": "Real-Debrid - бұл шектеусіз жүктеуші, ол интернетте орналастырылған файлдарды тез жүктеуге немесе жеке желі арқылы кез келген блоктарды айналып өтіп, оларды бірден плеерге беруге мүмкіндік береді.",
"real_debrid_invalid_token": "Қате API кілті",
"real_debrid_api_token_hint": "API кілтін <0>осы жерден</0> алуға болады",
"real_debrid_free_account_error": "\"{{username}}\" аккаунты жазылымға ие емес. Real-Debrid жазылымын алыңыз",
"real_debrid_linked_message": "\"{{username}}\" аккаунты байланған",
"save_changes": "Өзгерістерді сақтау",
"changes_saved": "Өзгерістер сәтті сақталды",
"download_sources_description": "Hydra осы көздерден жүктеу сілтемелерін алады. URL-да жүктеу сілтемелері бар .json файлына тікелей сілтеме болуы керек.",
"validate_download_source": "Тексеру",
"remove_download_source": "Жою",
"add_download_source": "Жүктеу көзін қосу",
"download_count_zero": "Жүктеулер тізімінде жоқ",
"download_count_one": "{{countFormatted}} жүктеу тізімде",
"download_count_other": "{{countFormatted}} жүктеу тізімде",
"download_options_zero": "Қолжетімді жүктеулер жоқ",
"download_options_one": "{{countFormatted}} жүктеу нұсқасы қол жетімді",
"download_options_other": "{{countFormatted}} жүктеу нұсқалары қол жетімді",
"download_source_url": "Көздің сілтемесі",
"add_download_source_description": ".json файлға сілтемені қойыңыз",
"download_source_up_to_date": "Жаңартылған",
"download_source_errored": "Қате",
"sync_download_sources": "Көздерді синхрондау",
"removed_download_source": "Жүктеу көзі жойылды",
"added_download_source": "Жүктеу көзі қосылды",
"download_sources_synced": "Барлық жүктеу көздері синхрондалды",
"insert_valid_json_url": "Жарамды JSON URL енгізіңіз",
"found_download_option_zero": "Жүктеу нұсқалары табылмады",
"found_download_option_one": "{{countFormatted}} жүктеу нұсқасы табылды",
"found_download_option_other": "{{countFormatted}} жүктеу нұсқалары табылды",
"import": "Импорттау"
},
"notifications": {
"download_complete": "Жүктеу аяқталды",
"game_ready_to_install": "{{title}} орнатуға дайын",
"repack_list_updated": "Репактар тізімі жаңартылды",
"repack_count_one": "{{count}} репак қосылды",
"repack_count_other": "{{count}} репактар қосылды"
},
"system_tray": {
"open": "Hydra-ны ашу",
"quit": "Шығу"
},
"game_card": {
"no_downloads": "Жүктеулер жоқ"
},
"binary_not_found_modal": {
"title": "Бағдарламалар орнатылмаған",
"description": "Wine немесе Lutris табылмады",
"instructions": "Linux дистрибутивіңізге олардың кез келгенін дұрыс орнатудың жолын біліңіз осылайша ойын дұрыс жұмыс істей алады"
},
"modal": {
"close": "Жабу"
},
"forms": {
"toggle_password_visibility": "Құпиясөзді көрсету"
},
"user_profile": {
"amount_hours": "{{amount}} сағат",
"amount_minutes": "{{amount}} минут",
"last_time_played": "Соңғы ойын {{period}}",
"activity": "Соңғы әрекет",
"library": "Кітапхана",
"total_play_time": "Барлығы ойнаған: {{amount}}",
"no_recent_activity_title": "Хммм... Мұнда ештеңе жоқ",
"no_recent_activity_description": "Сіз ұзақ уақыт бойы ештеңе ойнаған жоқсыз. Мұны өзгерту керек!",
"display_name": "Көрсету аты",
"saving": "Сақтау",
"save": "Сақталды",
"edit_profile": "Профильді өзгерту",
"saved_successfully": "Сәтті сақталды",
"try_again": "Қайта көріңіз",
"sign_out_modal_title": "Сіз сенімдісіз бе?",
"cancel": "Болдырмау",
"successfully_signed_out": "Аккаунттан сәтті шығу",
"sign_out": "Шығу",
"playing_for": "Ойнаған {{amount}}",
"sign_out_modal_text": "Сіздің кітапханаңыз ағымдағы аккаунтпен байланысты. Жүйеден шыққанда сіздің кітапханаңыз қол жетімсіз болады және прогресс сақталмайды. Шығу?"
}
}

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "한국어",
"home": { "home": {
"featured": "추천", "featured": "추천",
"trending": "인기", "trending": "인기",

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "Nederlands",
"home": { "home": {
"featured": "Uitgelicht", "featured": "Uitgelicht",
"trending": "Trending", "trending": "Trending",

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "Polski",
"home": { "home": {
"featured": "Wyróżnione", "featured": "Wyróżnione",
"trending": "Trendujące", "trending": "Trendujące",

View File

@@ -1,280 +0,0 @@
{
"language_name": "Português (Portugal)",
"app": {
"successfully_signed_in": "Sessão iniciada com sucesso"
},
"home": {
"featured": "Destaques",
"trending": "Populares",
"surprise_me": "Surpreende-me",
"no_results": "Nenhum resultado encontrado",
"start_typing": "Comece a digitar para pesquisar…"
},
"sidebar": {
"catalogue": "Catálogo",
"downloads": "Transferências",
"settings": "Definições",
"my_library": "Biblioteca",
"downloading_metadata": "{{title}} (A transferir metadados…)",
"paused": "{{title}} (Pausado)",
"downloading": "{{title}} ({{percentage}} - A transferir…)",
"filter": "Procurar",
"home": "Início",
"queued": "{{title}} (Na fila)",
"game_has_no_executable": "Jogo não tem executável selecionado",
"sign_in": "Iniciar sessão"
},
"header": {
"search": "Procurar jogos",
"catalogue": "Catálogo",
"downloads": "Transferências",
"search_results": "Resultados da pesquisa",
"settings": "Definições",
"home": "Início",
"version_available_install": "Versão {{version}} disponível. Clique aqui para reiniciar e instalar.",
"version_available_download": "Versão {{version}} disponível. Clique aqui para fazer o download."
},
"bottom_panel": {
"no_downloads_in_progress": "Sem transferências em andamento",
"downloading_metadata": "A transferir metadados de {{title}}…",
"downloading": "A transferir {{title}}… ({{percentage}} concluído) - Conclusão {{eta}} - {{speed}}",
"calculating_eta": "A transferir {{title}}… ({{percentage}} concluído) - A calcular tempo restante…",
"checking_files": "A verificar ficheiros de {{title}}…"
},
"game_details": {
"open_download_options": "Ver opções de transferência",
"download_options_zero": "Sem opções de transferência",
"download_options_one": "{{count}} opção de transferência",
"download_options_other": "{{count}} opções de transferência",
"updated_at": "Atualizado a {{updated_at}}",
"resume": "Retomar",
"pause": "Pausar",
"cancel": "Cancelar",
"remove": "Remover",
"space_left_on_disk": "{{space}} livres no disco",
"eta": "Conclusão {{eta}}",
"calculating_eta": "A calcular tempo restante…",
"downloading_metadata": "A transferir metadados…",
"filter": "Filtrar repacks",
"requirements": "Requisitos do sistema",
"minimum": "Mínimos",
"recommended": "Recomendados",
"paused": "Pausado",
"release_date": "Lançado em {{date}}",
"publisher": "Publicado por {{publisher}}",
"hours": "horas",
"minutes": "minutos",
"amount_hours": "{{amount}} horas",
"amount_minutes": "{{amount}} minutos",
"accuracy": "{{accuracy}}% de precisão",
"add_to_library": "Adicionar à biblioteca",
"remove_from_library": "Remover da biblioteca",
"no_downloads": "Nenhuma transferência disponível",
"play_time": "Jogou por {{amount}}",
"next_suggestion": "Próxima sugestão",
"install": "Instalar",
"last_time_played": "Última sessão {{period}}",
"play": "Jogar",
"not_played_yet": "Ainda não jogou {{title}}",
"close": "Fechar",
"deleting": "A eliminar instalador…",
"playing_now": "A jogar agora",
"change": "Explorar",
"repacks_modal_description": "Escolha o repack do jogo que deseja transferir",
"select_folder_hint": "Para trocar o diretório padrão, aceda à <0>Tela de Definições</0>",
"download_now": "Iniciar transferência",
"no_shop_details": "Não foi possível obter os detalhes da loja.",
"download_options": "Opções de transferência",
"download_path": "Diretório de transferência",
"previous_screenshot": "Captura de ecrã anterior",
"next_screenshot": "Próxima captura de ecrã",
"screenshot": "Captura de ecrã {{number}}",
"open_screenshot": "Ver captura de ecrã {{number}}",
"download_settings": "Definições de transferência",
"downloader": "Downloader",
"select_executable": "Explorar",
"no_executable_selected": "Nenhum executável selecionado",
"open_folder": "Abrir pasta",
"open_download_location": "Ver ficheiros transferidos",
"create_shortcut": "Criar atalho no ambiente de trabalho",
"remove_files": "Remover ficheiros",
"options": "Gerir",
"remove_from_library_description": "Isto irá remover {{game}} da sua biblioteca",
"remove_from_library_title": "Tem a certeza?",
"executable_section_title": "Executável",
"executable_section_description": "O caminho do ficheiro que será executado ao clicar em \"Jogar\"",
"downloads_secion_title": "Transferências",
"downloads_section_description": "Confira atualizações ou versões diferentes para este mesmo título",
"danger_zone_section_title": "Zona de perigo",
"danger_zone_section_description": "Remova o jogo da sua biblioteca ou os ficheiros que foram transferidos pelo Hydra",
"download_in_progress": "Transferência em andamento",
"download_paused": "Transferência pausada",
"last_downloaded_option": "Última opção transferida",
"create_shortcut_success": "Atalho criado com sucesso",
"create_shortcut_error": "Erro ao criar atalho",
"download": "Transferir",
"executable_path_in_use": "Executável em uso por \"{{game}}\"",
"warning": "Aviso:",
"hydra_needs_to_remain_open": "para este download, o Hydra precisa ficar aberto até a conclusão. Caso o Hydra encerre antes da conclusão, perderá seu progresso."
},
"activation": {
"title": "Ativação",
"installation_id": "ID da instalação:",
"enter_activation_code": "Insira o seu código de ativação",
"message": "Se não sabe onde conseguir o código, talvez não devesse estar aqui.",
"activate": "Ativar",
"loading": "A carregar…"
},
"downloads": {
"resume": "Retomar",
"pause": "Pausar",
"eta": "Conclusão {{eta}}",
"paused": "Pausado",
"verifying": "A verificar…",
"completed": "Concluído",
"removed": "Cancelado",
"cancel": "Cancelar",
"filter": "Filtrar jogos transferidos",
"remove": "Remover",
"downloading_metadata": "A transferir metadados…",
"delete": "Remover instalador",
"delete_modal_description": "Isto removerá todos os ficheiros de instalação do seu computador",
"delete_modal_title": "Tem a certeza?",
"deleting": "A eliminar instalador…",
"install": "Instalar",
"download_in_progress": "A transferir agora",
"queued_downloads": "Na fila",
"downloads_completed": "Concluído",
"queued": "Na fila",
"no_downloads_title": "Nada por aqui…",
"no_downloads_description": "Ainda não transferiu nada pelo Hydra, mas nunca é tarde para começar.",
"checking_files": "A verificar ficheiros…"
},
"settings": {
"downloads_path": "Diretório das transferências",
"change": "Explorar...",
"notifications": "Notificações",
"enable_download_notifications": "Quando uma transferência for concluída",
"enable_repack_list_notifications": "Quando a lista de repacks for atualizada",
"real_debrid_api_token_label": "Token de API do Real-Debrid",
"quit_app_instead_hiding": "Encerrar o Hydra em vez de apenas minimizá-lo ao fechar.",
"launch_with_system": "Iniciar o Hydra com o sistema",
"general": "Geral",
"behavior": "Comportamento",
"download_sources": "Fontes de transferência",
"language": "Idioma",
"real_debrid_api_token": "Token de API",
"enable_real_debrid": "Ativar Real-Debrid",
"real_debrid_api_token_hint": "Pode obter o seu token de API <0>aqui</0>",
"real_debrid_description": "O Real-Debrid é um downloader sem restrições que permite transferir ficheiros instantaneamente e com a melhor velocidade da sua Internet.",
"real_debrid_invalid_token": "Token de API inválido",
"real_debrid_free_account_error": "A conta \"{{username}}\" é uma conta gratuita. Por favor, subscreva o Real-Debrid",
"real_debrid_linked_message": "Conta \"{{username}}\" vinculada",
"save_changes": "Guardar alterações",
"changes_saved": "Definições guardadas com sucesso",
"download_sources_description": "O Hydra vai procurar links de transferência em todas as fontes ativadas. A URL da página de detalhes da loja não é guardada no seu dispositivo. Utilizamos um sistema de metadados criado pela comunidade para fornecer suporte a mais fontes de transferência de jogos.",
"validate_download_source": "Validar",
"remove_download_source": "Remover",
"add_download_source": "Adicionar fonte",
"download_count_zero": "Sem transferências na lista",
"download_count_one": "{{countFormatted}} transferência na lista",
"download_count_other": "{{countFormatted}} transferências na lista",
"download_options_zero": "Sem transferências disponíveis",
"download_options_one": "{{countFormatted}} transferência disponível",
"download_options_other": "{{countFormatted}} transferências disponíveis",
"download_source_url": "URL da fonte",
"add_download_source_description": "Insira o URL contendo o arquivo .json",
"download_source_up_to_date": "Sincronizada",
"download_source_errored": "Falhou",
"sync_download_sources": "Sincronizar",
"removed_download_source": "Fonte removida",
"added_download_source": "Fonte adicionada",
"download_sources_synced": "As fontes foram sincronizadas",
"insert_valid_json_url": "Insira o URL de um JSON válido",
"found_download_option_zero": "Nenhuma opção de transferência encontrada",
"found_download_option_one": "{{countFormatted}} opção de transferência encontrada",
"found_download_option_other": "{{countFormatted}} opções de transferências encontradas",
"import": "Importar"
},
"notifications": {
"download_complete": "Transferência concluída",
"game_ready_to_install": "{{title}} está pronto para ser descarregado",
"repack_list_updated": "Lista de repacks atualizada",
"repack_count_one": "{{count}} novo repack",
"repack_count_other": "{{count}} novos repacks",
"new_update_available": "Versão {{version}} disponível",
"restart_to_install_update": "Reinicie o Hydra para instalar a nova versão"
},
"system_tray": {
"open": "Abrir Hydra",
"quit": "Fechar"
},
"game_card": {
"no_downloads": "Sem transferências disponíveis"
},
"binary_not_found_modal": {
"title": "Programas não instalados",
"description": "Os executáveis do Wine ou Lutris não foram encontrados em seu sistema.",
"instructions": "Verifique a forma correta de instalar algum deles na sua distro Linux, garantindo assim a execução normal do jogo."
},
"catalogue": {
"next_page": "Próxima página",
"previous_page": "Página anterior"
},
"modal": {
"close": "Botão de fechar"
},
"forms": {
"toggle_password_visibility": "Alternar visibilidade da palavra-passe"
},
"user_profile": {
"amount_hours": "{{amount}} horas",
"amount_minutes": "{{amount}} minutos",
"last_time_played": "Última sessão {{period}}",
"activity": "Atividades recentes",
"library": "Biblioteca",
"total_play_time": "Tempo total de jogo: {{amount}}",
"no_recent_activity_title": "Hmmm… nada por aqui",
"no_recent_activity_description": "Parece que não jogaste nada recentemente. Que tal começar agora?",
"display_name": "Nome de exibição",
"saving": "a guardar…",
"save": "Guardar",
"edit_profile": "Editar perfil",
"saved_successfully": "Guardado com sucesso",
"try_again": "Por favor, tenta novamente",
"cancel": "Cancelar",
"successfully_signed_out": "Terminado com sucesso",
"sign_out": "Terminar sessão",
"sign_out_modal_title": "Tens a certeza?",
"playing_for": "A jogar há {{amount}}",
"sign_out_modal_text": "A tua biblioteca de jogos está associada com a tua conta atual. Ao sair, a tua biblioteca não aparecerá mais no Hydra e qualquer progresso não será guardado. Desejas continuar?",
"add_friends": "Adicionar Amigos",
"friend_code": "Código de amigo",
"see_profile": "Ver perfil",
"friend_request_sent": "Pedido de amizade enviado",
"friends": "Amigos",
"add": "Adicionar",
"sending": "A enviar",
"friends_list": "Lista de amigos",
"user_not_found": "Utilizador não encontrado",
"block_user": "Bloquear",
"add_friend": "Adicionar amigo",
"request_sent": "Pedido enviado",
"request_received": "Pedido recebido",
"accept_request": "Aceitar pedido",
"ignore_request": "Ignorar pedido",
"cancel_request": "Cancelar pedido",
"undo_friendship": "Desfazer amizade",
"request_accepted": "Pedido de amizade aceito",
"user_blocked_successfully": "Utilizador bloqueado com sucesso",
"user_block_modal_text": "Bloquear {{displayName}}",
"blocked_users": "Utilizadores bloqueados",
"unblock": "Desbloquear",
"no_friends_added": "Ainda não adicionaste amigos",
"pending": "Pendentes",
"no_pending_invites": "Não tens convites de amizade pendentes",
"no_blocked_users": "Não tens nenhum utilizador bloqueado",
"friend_code_copied": "Código de amigo copiado",
"image_process_failure": "Falha ao processar a imagem"
}
}

View File

@@ -1,31 +1,26 @@
{ {
"language_name": "Português (Brasil)",
"app": { "app": {
"successfully_signed_in": "Autenticado com sucesso" "successfully_signed_in": "Logado com sucesso"
}, },
"home": { "home": {
"featured": "Destaques", "featured": "Destaque",
"trending": "Populares", "trending": "Populares",
"hot": "🔥 Populares agora",
"weekly": "📅 Mais baixados da semana",
"surprise_me": "Surpreenda-me", "surprise_me": "Surpreenda-me",
"no_results": "Nenhum resultado encontrado", "no_results": "Nenhum resultado encontrado"
"start_typing": "Comece a digitar para pesquisar…"
}, },
"sidebar": { "sidebar": {
"catalogue": "Catálogo", "catalogue": "Catálogo",
"downloads": "Downloads", "downloads": "Downloads",
"settings": "Ajustes", "settings": "Ajustes",
"my_library": "Biblioteca", "my_library": "Minha biblioteca",
"downloading_metadata": "{{title}} (Baixando metadados…)", "downloading_metadata": "{{title}} (Baixando metadados…)",
"paused": "{{title}} (Pausado)", "paused": "{{title}} (Pausado)",
"downloading": "{{title}} ({{percentage}} - Baixando…)", "downloading": "{{title}} ({{percentage}} - Baixando…)",
"filter": "Buscar", "filter": "Filtrar biblioteca",
"home": "Início", "home": "Início",
"queued": "{{title}} (Na fila)", "queued": "{{title}} (Na fila)",
"game_has_no_executable": "Jogo não possui executável selecionado", "game_has_no_executable": "Jogo não possui executável selecionado",
"sign_in": "Login", "sign_in": "Login"
"friends": "Amigos"
}, },
"header": { "header": {
"search": "Buscar jogos", "search": "Buscar jogos",
@@ -41,8 +36,7 @@
"no_downloads_in_progress": "Sem downloads em andamento", "no_downloads_in_progress": "Sem downloads em andamento",
"downloading_metadata": "Baixando metadados de {{title}}…", "downloading_metadata": "Baixando metadados de {{title}}…",
"downloading": "Baixando {{title}}… ({{percentage}} concluído) - Conclusão {{eta}} - {{speed}}", "downloading": "Baixando {{title}}… ({{percentage}} concluído) - Conclusão {{eta}} - {{speed}}",
"calculating_eta": "Baixando {{title}}… ({{percentage}} concluído) - Calculando tempo restante…", "calculating_eta": "Baixando {{title}}… ({{percentage}} concluído) - Calculando tempo restante…"
"checking_files": "Verificando arquivos de {{title}}…"
}, },
"game_details": { "game_details": {
"open_download_options": "Ver opções de download", "open_download_options": "Ver opções de download",
@@ -50,7 +44,7 @@
"download_options_one": "{{count}} opção de download", "download_options_one": "{{count}} opção de download",
"download_options_other": "{{count}} opções de download", "download_options_other": "{{count}} opções de download",
"updated_at": "Atualizado {{updated_at}}", "updated_at": "Atualizado {{updated_at}}",
"resume": "Retomar", "resume": "Resumir",
"pause": "Pausar", "pause": "Pausar",
"cancel": "Cancelar", "cancel": "Cancelar",
"remove": "Remover", "remove": "Remover",
@@ -59,7 +53,7 @@
"calculating_eta": "Calculando tempo restante…", "calculating_eta": "Calculando tempo restante…",
"downloading_metadata": "Baixando metadados…", "downloading_metadata": "Baixando metadados…",
"filter": "Filtrar repacks", "filter": "Filtrar repacks",
"requirements": "Requisitos de sistema", "requirements": "Requisitos do sistema",
"minimum": "Mínimos", "minimum": "Mínimos",
"recommended": "Recomendados", "recommended": "Recomendados",
"paused": "Pausado", "paused": "Pausado",
@@ -73,16 +67,16 @@
"add_to_library": "Adicionar à biblioteca", "add_to_library": "Adicionar à biblioteca",
"remove_from_library": "Remover da biblioteca", "remove_from_library": "Remover da biblioteca",
"no_downloads": "Nenhum download disponível", "no_downloads": "Nenhum download disponível",
"play_time": "Jogou por {{amount}}", "play_time": "Jogado por {{amount}}",
"next_suggestion": "Próxima sugestão", "next_suggestion": "Próxima sugestão",
"install": "Instalar", "install": "Instalar",
"last_time_played": "Última sessão {{period}}", "last_time_played": "Jogou por último {{period}}",
"play": "Jogar", "play": "Jogar",
"not_played_yet": "Você ainda não jogou {{title}}", "not_played_yet": "Você ainda não jogou {{title}}",
"close": "Fechar", "close": "Fechar",
"deleting": "Excluindo instalador…", "deleting": "Excluindo instalador…",
"playing_now": "Jogando agora", "playing_now": "Jogando agora",
"change": "Explorar", "change": "Mudar",
"repacks_modal_description": "Escolha o repack do jogo que deseja baixar", "repacks_modal_description": "Escolha o repack do jogo que deseja baixar",
"select_folder_hint": "Para trocar o diretório padrão, acesse a <0>Tela de Ajustes</0>", "select_folder_hint": "Para trocar o diretório padrão, acesse a <0>Tela de Ajustes</0>",
"download_now": "Iniciar download", "download_now": "Iniciar download",
@@ -95,13 +89,13 @@
"open_screenshot": "Ver captura de tela {{number}}", "open_screenshot": "Ver captura de tela {{number}}",
"download_settings": "Ajustes do download", "download_settings": "Ajustes do download",
"downloader": "Downloader", "downloader": "Downloader",
"select_executable": "Explorar", "select_executable": "Selecionar",
"no_executable_selected": "Nenhum executável selecionado", "no_executable_selected": "Nenhum executável selecionado",
"open_folder": "Abrir pasta", "open_folder": "Abrir pasta",
"open_download_location": "Ver arquivos baixados", "open_download_location": "Ver arquivos baixados",
"create_shortcut": "Criar atalho na área de trabalho", "create_shortcut": "Criar atalho na área de trabalho",
"remove_files": "Remover arquivos", "remove_files": "Remover arquivos",
"options": "Gerenciar", "options": "Opções",
"remove_from_library_description": "Isso irá remover {{game}} da sua biblioteca", "remove_from_library_description": "Isso irá remover {{game}} da sua biblioteca",
"remove_from_library_title": "Tem certeza?", "remove_from_library_title": "Tem certeza?",
"executable_section_title": "Executável", "executable_section_title": "Executável",
@@ -114,19 +108,7 @@
"download_paused": "Download pausado", "download_paused": "Download pausado",
"last_downloaded_option": "Última opção baixada", "last_downloaded_option": "Última opção baixada",
"create_shortcut_success": "Atalho criado com sucesso", "create_shortcut_success": "Atalho criado com sucesso",
"create_shortcut_error": "Erro ao criar atalho", "create_shortcut_error": "Erro ao criar atalho"
"nsfw_content_title": "Este jogo contém conteúdo inapropriado",
"nsfw_content_description": "{{title}} contém conteúdo que pode não ser apropriado para todas as idades. Você deseja continuar?",
"allow_nsfw_content": "Continuar",
"refuse_nsfw_content": "Voltar",
"stats": "Estatísticas",
"download_count": "Downloads",
"player_count": "Jogadores ativos",
"download_error": "Essa opção de download falhou",
"download": "Baixar",
"executable_path_in_use": "Executável em uso por \"{{game}}\"",
"warning": "Aviso:",
"hydra_needs_to_remain_open": "para este download, o Hydra precisa ficar aberto até a conclusão. Caso o Hydra encerre antes da conclusão, perderá seu progresso."
}, },
"activation": { "activation": {
"title": "Ativação", "title": "Ativação",
@@ -137,7 +119,7 @@
"loading": "Carregando…" "loading": "Carregando…"
}, },
"downloads": { "downloads": {
"resume": "Retomar", "resume": "Resumir",
"pause": "Pausar", "pause": "Pausar",
"eta": "Conclusão {{eta}}", "eta": "Conclusão {{eta}}",
"paused": "Pausado", "paused": "Pausado",
@@ -158,17 +140,16 @@
"downloads_completed": "Completo", "downloads_completed": "Completo",
"queued": "Na fila", "queued": "Na fila",
"no_downloads_title": "Nada por aqui…", "no_downloads_title": "Nada por aqui…",
"no_downloads_description": "Você ainda não baixou nada pelo Hydra, mas nunca é tarde para começar.", "no_downloads_description": "Você ainda não baixou nada pelo Hydra, mas nunca é tarde para começar."
"checking_files": "Verificando arquivos…"
}, },
"settings": { "settings": {
"downloads_path": "Diretório dos downloads", "downloads_path": "Diretório dos downloads",
"change": "Explorar...", "change": "Mudar",
"notifications": "Notificações", "notifications": "Notificações",
"enable_download_notifications": "Quando um download for concluído", "enable_download_notifications": "Quando um download for concluído",
"enable_repack_list_notifications": "Quando a lista de repacks for atualizada", "enable_repack_list_notifications": "Quando a lista de repacks for atualizada",
"real_debrid_api_token_label": "Token de API do Real-Debrid", "real_debrid_api_token_label": "Token de API do Real-Debrid",
"quit_app_instead_hiding": "Encerrar o Hydra em vez de apenas minimizá-lo ao fechar.", "quit_app_instead_hiding": "Encerrar o Hydra ao invés de minimizá-lo ao fechar",
"launch_with_system": "Iniciar o Hydra junto com o sistema", "launch_with_system": "Iniciar o Hydra junto com o sistema",
"general": "Geral", "general": "Geral",
"behavior": "Comportamento", "behavior": "Comportamento",
@@ -183,7 +164,7 @@
"real_debrid_linked_message": "Conta \"{{username}}\" vinculada", "real_debrid_linked_message": "Conta \"{{username}}\" vinculada",
"save_changes": "Salvar mudanças", "save_changes": "Salvar mudanças",
"changes_saved": "Ajustes salvos com sucesso", "changes_saved": "Ajustes salvos com sucesso",
"download_sources_description": "Hydra vai buscar links de download em todas as fontes habilitadas. A URL da fonte deve ser um link direto para um arquivo .json contendo uma lista de links.", "download_sources_description": "Hydra vai buscar links de download em todas as fonte habilitadas. A URL da fonte deve ser um link direto para um arquivo .json contendo uma lista de links.",
"validate_download_source": "Validar", "validate_download_source": "Validar",
"remove_download_source": "Remover", "remove_download_source": "Remover",
"add_download_source": "Adicionar fonte", "add_download_source": "Adicionar fonte",
@@ -205,27 +186,14 @@
"found_download_option_zero": "Nenhuma opção de download encontrada", "found_download_option_zero": "Nenhuma opção de download encontrada",
"found_download_option_one": "{{countFormatted}} opção de download encontrada", "found_download_option_one": "{{countFormatted}} opção de download encontrada",
"found_download_option_other": "{{countFormatted}} opções de download encontradas", "found_download_option_other": "{{countFormatted}} opções de download encontradas",
"import": "Importar", "import": "Importar"
"privacy": "Privacidade",
"private": "Privado",
"friends_only": "Apenas amigos",
"public": "Público",
"profile_visibility": "Visibilidade do perfil",
"profile_visibility_description": "Escolha quem pode ver seu perfil e biblioteca",
"required_field": "Este campo é obrigatório",
"source_already_exists": "Essa fonte já foi adicionada",
"must_be_valid_url": "A fonte deve ser uma URL válida",
"blocked_users": "Usuários bloqueados",
"user_unblocked": "Usuário desbloqueado"
}, },
"notifications": { "notifications": {
"download_complete": "Download concluído", "download_complete": "Download concluído",
"game_ready_to_install": "{{title}} está pronto para ser instalado", "game_ready_to_install": "{{title}} está pronto para ser instalado",
"repack_list_updated": "Lista de repacks atualizada", "repack_list_updated": "Lista de repacks atualizada",
"repack_count_one": "{{count}} novo repack", "repack_count_one": "{{count}} novo repack",
"repack_count_other": "{{count}} novos repacks", "repack_count_other": "{{count}} novos repacks"
"new_update_available": "Versão {{version}} disponível",
"restart_to_install_update": "Reinicie o Hydra para instalar a nova versão"
}, },
"system_tray": { "system_tray": {
"open": "Abrir Hydra", "open": "Abrir Hydra",
@@ -236,7 +204,7 @@
}, },
"binary_not_found_modal": { "binary_not_found_modal": {
"title": "Programas não instalados", "title": "Programas não instalados",
"description": "Os executáveis do Wine ou Lutris não foram encontrados em seu sistema.", "description": "Não foram encontrados no seu sistema os executáveis do Wine ou Lutris",
"instructions": "Verifique a forma correta de instalar algum deles no seu distro Linux, garantindo assim a execução normal do jogo" "instructions": "Verifique a forma correta de instalar algum deles no seu distro Linux, garantindo assim a execução normal do jogo"
}, },
"catalogue": { "catalogue": {
@@ -252,8 +220,8 @@
"user_profile": { "user_profile": {
"amount_hours": "{{amount}} horas", "amount_hours": "{{amount}} horas",
"amount_minutes": "{{amount}} minutos", "amount_minutes": "{{amount}} minutos",
"last_time_played": "Última sessão {{period}}", "last_time_played": "Jogou {{period}}",
"activity": "Atividades recentes", "activity": "Atividade recente",
"library": "Biblioteca", "library": "Biblioteca",
"total_play_time": "Tempo total de jogo: {{amount}}", "total_play_time": "Tempo total de jogo: {{amount}}",
"no_recent_activity_title": "Hmmm… nada por aqui", "no_recent_activity_title": "Hmmm… nada por aqui",
@@ -261,60 +229,14 @@
"display_name": "Nome de exibição", "display_name": "Nome de exibição",
"saving": "Salvando…", "saving": "Salvando…",
"save": "Salvar", "save": "Salvar",
"edit_profile": "Editar perfil", "edit_profile": "Editar Perfil",
"saved_successfully": "Salvo com sucesso", "saved_successfully": "Salvo com sucesso",
"try_again": "Por favor, tente novamente", "try_again": "Por favor, tente novamente",
"cancel": "Cancelar", "cancel": "Cancelar",
"successfully_signed_out": "Deslogado com sucesso", "successfully_signed_out": "Deslogado com sucesso",
"sign_out": "Sair da conta", "sign_out": "Sair da conta",
"sign_out_modal_title": "Deseja mesmo sair?", "sign_out_modal_title": "Tem certeza?",
"playing_for": "Jogando por {{amount}}", "playing_for": "Jogando por {{amount}}",
"sign_out_modal_text": "Sua biblioteca de jogos está associada com a sua conta atual. Ao sair, sua biblioteca não aparecerá mais no Hydra e qualquer progresso não será salvo. Deseja continuar?", "sign_out_modal_text": "Sua biblioteca de jogos está associada com a sua conta atual. Ao sair, sua biblioteca não aparecerá mais no Hydra e qualquer progresso não será salvo. Deseja continuar?"
"add_friends": "Adicionar Amigos",
"friend_code": "Código de amigo",
"see_profile": "Ver perfil",
"friend_request_sent": "Pedido de amizade enviado",
"friends": "Amigos",
"add": "Adicionar",
"sending": "Enviando",
"friends_list": "Lista de amigos",
"user_not_found": "Usuário não encontrado",
"block_user": "Bloquear",
"add_friend": "Adicionar amigo",
"request_sent": "Pedido enviado",
"request_received": "Pedido recebido",
"accept_request": "Aceitar pedido",
"ignore_request": "Ignorar pedido",
"cancel_request": "Cancelar pedido",
"undo_friendship": "Desfazer amizade",
"request_accepted": "Pedido de amizade aceito",
"user_blocked_successfully": "Usuário bloqueado com sucesso",
"user_block_modal_text": "Bloquear {{displayName}}",
"blocked_users": "Usuários bloqueados",
"unblock": "Desbloquear",
"no_friends_added": "Você ainda não possui amigos adicionados",
"pending": "Pendentes",
"no_pending_invites": "Você não possui convites de amizade pendentes",
"no_blocked_users": "Você não tem nenhum usuário bloqueado",
"friend_code_copied": "Código de amigo copiado",
"undo_friendship_modal_text": "Isso irá remover sua amizade com {{displayName}}",
"privacy_hint": "Pra controlar quem pode ver seu perfil, acesse a <0>Tela de Configurações</0>",
"profile_locked": "Este perfil é privado",
"image_process_failure": "Falha ao processar a imagem",
"required_field": "Este campo é obrigatório",
"displayname_min_length": "Nome de exibição deve ter pelo menos 3 caracteres",
"displayname_max_length": "Nome de exibição deve ter no máximo 50 caracteres",
"locked_profile": "Este perfil é privado",
"report_profile": "Reportar este perfil",
"report_reason": "Por que você deseja reportar este perfil?",
"report_description": "Informações adicionais",
"report_description_placeholder": "Insira aqui",
"report": "Reportar",
"report_reason_hate": "Discurso de ódio",
"report_reason_sexual_content": "Conteúdo sexual",
"report_reason_violence": "Violência",
"report_reason_spam": "Spam",
"report_reason_other": "Outro",
"profile_reported": "Perfil reportado"
} }
} }

View File

@@ -1,160 +0,0 @@
{
"language_name": "Română",
"home": {
"featured": "Recomandate",
"trending": "Populare",
"surprise_me": "Surprinde-mă",
"no_results": "Niciun rezultat găsit"
},
"sidebar": {
"catalogue": "Catalog",
"downloads": "Descărcări",
"settings": "Setări",
"my_library": "Biblioteca mea",
"downloading_metadata": "{{title}} (Se descarcă metadata...)",
"paused": "{{title}} (Pauzat)",
"downloading": "{{title}} ({{percentage}} - Se descarcă...)",
"filter": "Filtrează biblioteca",
"home": "Acasă"
},
"header": {
"search": "Caută jocuri",
"home": "Acasă",
"catalogue": "Catalog",
"downloads": "Descărcări",
"search_results": "Rezultatele căutării",
"settings": "Setări"
},
"bottom_panel": {
"no_downloads_in_progress": "Nicio descărcare în curs",
"downloading_metadata": "Se descarcă metadata pentru {{title}}...",
"downloading": "Se descarcă {{title}}... ({{percentage}} complet) - Concluzie {{eta}} - {{speed}}",
"calculating_eta": "Se descarcă {{title}}... ({{percentage}} complet) - Calculare timp rămas..."
},
"catalogue": {
"next_page": "Pagina următoare",
"previous_page": "Pagina anterioară"
},
"game_details": {
"open_download_options": "Deschide opțiunile de descărcare",
"download_options_zero": "Nicio opțiune de descărcare",
"download_options_one": "{{count}} opțiune de descărcare",
"download_options_other": "{{count}} opțiuni de descărcare",
"updated_at": "Actualizat la {{updated_at}}",
"install": "Instalează",
"resume": "Reia",
"pause": "Pauză",
"cancel": "Anulează",
"remove": "Elimină",
"space_left_on_disk": "{{space}} liber pe disc",
"eta": "Concluzie {{eta}}",
"calculating_eta": "Calculare timp rămas...",
"downloading_metadata": "Se descarcă metadata...",
"filter": "Filtrează repack-urile",
"requirements": "Cerințe de sistem",
"minimum": "Minim",
"recommended": "Recomandat",
"paused": "Pauzat",
"release_date": "Lansat pe {{date}}",
"publisher": "Publicat de {{publisher}}",
"hours": "ore",
"minutes": "minute",
"amount_hours": "{{amount}} ore",
"amount_minutes": "{{amount}} minute",
"accuracy": "{{accuracy}}% acuratețe",
"add_to_library": "Adaugă în bibliotecă",
"remove_from_library": "Elimină din bibliotecă",
"no_downloads": "Nicio descărcare disponibilă",
"play_time": "Jucat timp de {{amount}}",
"last_time_played": "Ultima dată jucat {{period}}",
"not_played_yet": "Nu ai jucat încă {{title}}",
"next_suggestion": "Sugestia următoare",
"play": "Joacă",
"deleting": "Se șterge programul de instalare...",
"close": "Închide",
"playing_now": "Se joacă acum",
"change": "Schimbă",
"repacks_modal_description": "Alege repack-ul pe care vrei să-l descarci",
"select_folder_hint": "Pentru a schimba folderul predefinit, mergi la <0>Setări</0>",
"download_now": "Descarcă acum",
"no_shop_details": "Nu s-au putut obține detalii din magazin.",
"download_options": "Opțiuni de descărcare",
"download_path": "Locația de descărcare",
"previous_screenshot": "Captura de ecran anterioară",
"next_screenshot": "Captura de ecran următoare",
"screenshot": "Captură de ecran {{number}}",
"open_screenshot": "Deschide captura de ecran {{number}}",
"download_settings": "Setări de descărcare",
"downloader": "Program de descărcare"
},
"activation": {
"title": "Activează Hydra",
"installation_id": "ID-ul de instalare:",
"enter_activation_code": "Introdu codul de activare",
"message": "Dacă nu știi de unde să ceri acest lucru, atunci nu ar trebui să-l ai.",
"activate": "Activează",
"loading": "Se încarcă..."
},
"downloads": {
"resume": "Reia",
"pause": "Pauză",
"eta": "Concluzie {{eta}}",
"paused": "Pauzat",
"verifying": "Se verifică...",
"completed": "Completat",
"removed": "Nu este descărcat",
"cancel": "Anulează",
"filter": "Filtrează jocurile descărcate",
"remove": "Elimină",
"downloading_metadata": "Se descarcă metadata...",
"deleting": "Se șterge programul de instalare...",
"delete": "Elimină programul de instalare",
"delete_modal_title": "Ești sigur?",
"delete_modal_description": "Aceasta va elimina toate fișierele de instalare de pe computer",
"install": "Instalează"
},
"settings": {
"downloads_path": "Locația de descărcare",
"change": "Actualizează",
"notifications": "Notificări",
"enable_download_notifications": "Când o descărcare este completă",
"enable_repack_list_notifications": "Când un nou repack este adăugat",
"real_debrid_api_token_label": "Token API Real-Debrid",
"quit_app_instead_hiding": "Nu ascunde Hydra la închidere",
"launch_with_system": "Lansează Hydra la pornirea sistemului",
"general": "General",
"behavior": "Comportament",
"language": "Limbă",
"real_debrid_api_token": "Token API",
"enable_real_debrid": "Activează Real-Debrid",
"real_debrid_description": "Real-Debrid este un descărcător fără restricții care îți permite să descarci fișiere instantaneu și la cea mai bună viteză a internetului tău.",
"real_debrid_invalid_token": "Token API invalid",
"real_debrid_api_token_hint": "Poți obține token-ul tău API <0>aici</0>",
"real_debrid_free_account_error": "Contul \"{{username}}\" este un cont gratuit. Te rugăm să te abonezi la Real-Debrid",
"real_debrid_linked_message": "Contul \"{{username}}\" a fost legat",
"save_changes": "Salvează modificările",
"changes_saved": "Modificările au fost salvate cu succes"
},
"notifications": {
"download_complete": "Descărcare completă",
"game_ready_to_install": "{{title}} este gata de instalare",
"repack_list_updated": "Lista de repack-uri a fost actualizată",
"repack_count_one": "{{count}} repack adăugat",
"repack_count_other": "{{count}} repack-uri adăugate"
},
"system_tray": {
"open": "Deschide Hydra",
"quit": "Ieși"
},
"game_card": {
"no_downloads": "Nicio descărcare disponibilă"
},
"binary_not_found_modal": {
"title": "Programele nu sunt instalate",
"description": "Fișierele executabile Wine sau Lutris nu au fost găsite pe sistemul tău",
"instructions": "Verifică modul corect de instalare a oricăruia dintre acestea pe distribuția ta Linux pentru ca jocul să ruleze normal"
},
"modal": {
"close": "Buton de închidere"
}
}

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "Русский",
"app": { "app": {
"successfully_signed_in": "Успешный вход" "successfully_signed_in": "Успешный вход"
}, },
@@ -7,10 +6,7 @@
"featured": "Рекомендованное", "featured": "Рекомендованное",
"trending": "В тренде", "trending": "В тренде",
"surprise_me": "Удиви меня", "surprise_me": "Удиви меня",
"no_results": "Ничего не найдено", "no_results": "Ничего не найдено"
"hot": "🔥 Сейчас жарко",
"start_typing": "Начинаю вводить текст для поиска...",
"weekly": "📅 Лучшие игры недели"
}, },
"sidebar": { "sidebar": {
"catalogue": "Каталог", "catalogue": "Каталог",
@@ -24,8 +20,7 @@
"home": "Главная", "home": "Главная",
"queued": "{{title}} (В очереди)", "queued": "{{title}} (В очереди)",
"game_has_no_executable": "Файл запуска игры не выбран", "game_has_no_executable": "Файл запуска игры не выбран",
"sign_in": "Войти", "sign_in": "Войти"
"friends": "Друзья"
}, },
"header": { "header": {
"search": "Поиск", "search": "Поиск",
@@ -41,8 +36,7 @@
"no_downloads_in_progress": "Нет активных загрузок", "no_downloads_in_progress": "Нет активных загрузок",
"downloading_metadata": "Загрузка метаданных {{title}}…", "downloading_metadata": "Загрузка метаданных {{title}}…",
"downloading": "Загрузка {{title}}… ({{percentage}} завершено) - Окончание {{eta}} - {{speed}}", "downloading": "Загрузка {{title}}… ({{percentage}} завершено) - Окончание {{eta}} - {{speed}}",
"calculating_eta": "Загрузка {{title}}… ({{percentage}} завершено) - Подсчёт оставшегося времени…", "calculating_eta": "Загрузка {{title}}… ({{percentage}} завершено) - Подсчёт оставшегося времени…"
"checking_files": "Проверка файлов {{title}}… ({{percentage}} завершено)"
}, },
"catalogue": { "catalogue": {
"next_page": "Следующая страница", "next_page": "Следующая страница",
@@ -118,17 +112,7 @@
"download_paused": "Загрузка приостановлена", "download_paused": "Загрузка приостановлена",
"last_downloaded_option": "Последний вариант загрузки", "last_downloaded_option": "Последний вариант загрузки",
"create_shortcut_success": "Ярлык создан", "create_shortcut_success": "Ярлык создан",
"create_shortcut_error": "Не удалось создать ярлык", "create_shortcut_error": "Не удалось создать ярлык"
"allow_nsfw_content": "Продолжать",
"download": "Скачать",
"download_count": "Загрузки",
"download_error": "Этот вариант загрузки недоступен",
"executable_path_in_use": "Исполняемый файл уже используется \"{{game}}\"",
"nsfw_content_description": "{{title}} содержит контент, который может не подходить для всех возрастов. \nВы уверены, что хотите продолжить?",
"nsfw_content_title": "Эта игра содержит неприемлемый контент",
"player_count": "Активные игроки",
"refuse_nsfw_content": "Возвращаться",
"stats": "Статистика"
}, },
"activation": { "activation": {
"title": "Активировать Hydra", "title": "Активировать Hydra",
@@ -160,8 +144,7 @@
"downloads_completed": "Завершено", "downloads_completed": "Завершено",
"queued": "В очереди", "queued": "В очереди",
"no_downloads_title": "Здесь так пусто...", "no_downloads_title": "Здесь так пусто...",
"no_downloads_description": "Вы ещё ничего не скачали через Hydra, но никогда не поздно начать.", "no_downloads_description": "Вы ещё ничего не скачали через Hydra, но никогда не поздно начать."
"checking_files": "Проверка файлов…"
}, },
"settings": { "settings": {
"downloads_path": "Путь загрузок", "downloads_path": "Путь загрузок",
@@ -170,11 +153,11 @@
"enable_download_notifications": "По завершении загрузки", "enable_download_notifications": "По завершении загрузки",
"enable_repack_list_notifications": "При добавлении нового репака", "enable_repack_list_notifications": "При добавлении нового репака",
"real_debrid_api_token_label": "Real-Debrid API-токен", "real_debrid_api_token_label": "Real-Debrid API-токен",
"quit_app_instead_hiding": "Закрывать приложение вместо сворачивания в трей", "quit_app_instead_hiding": "Закрывать Hydra вместо того, чтобы сворачивать его в трей",
"launch_with_system": "Запускать Hydra вместе с системой", "launch_with_system": "Запуск Hydra вместе с системой",
"general": "Основные", "general": "Основные",
"behavior": "Поведение", "behavior": "Поведение",
"download_sources": "Источники загрузки", "download_sources": "Скачать исходный код",
"language": "Язык", "language": "Язык",
"real_debrid_api_token": "API Ключ", "real_debrid_api_token": "API Ключ",
"enable_real_debrid": "Включить Real-Debrid", "enable_real_debrid": "Включить Real-Debrid",
@@ -192,6 +175,9 @@
"download_count_zero": "В списке нет загрузок", "download_count_zero": "В списке нет загрузок",
"download_count_one": "{{countFormatted}} загрузка в списке", "download_count_one": "{{countFormatted}} загрузка в списке",
"download_count_other": "{{countFormatted}} загрузок в списке", "download_count_other": "{{countFormatted}} загрузок в списке",
"download_options_zero": "Нет доступных загрузок",
"download_options_one": "{{countFormatted}} вариант загрузки доступен",
"download_options_other": "{{countFormatted}} вариантов загрузки доступно",
"download_source_url": "Ссылка на источник", "download_source_url": "Ссылка на источник",
"add_download_source_description": "Вставьте ссылку на .json-файл", "add_download_source_description": "Вставьте ссылку на .json-файл",
"download_source_up_to_date": "Обновлён", "download_source_up_to_date": "Обновлён",
@@ -204,30 +190,14 @@
"found_download_option_zero": "Не найдено вариантов загрузки", "found_download_option_zero": "Не найдено вариантов загрузки",
"found_download_option_one": "Найден {{countFormatted}} вариант загрузки", "found_download_option_one": "Найден {{countFormatted}} вариант загрузки",
"found_download_option_other": "Найдено {{countFormatted}} вариантов загрузки", "found_download_option_other": "Найдено {{countFormatted}} вариантов загрузки",
"import": "Импортировать", "import": "Импортировать"
"blocked_users": "Заблокированные пользователи",
"download_options_one": "",
"download_options_other": "",
"download_options_zero": "",
"friends_only": "Только друзья",
"must_be_valid_url": "Источник должен быть действительным URL-адресом.",
"privacy": "Конфиденциальность",
"private": "Частный",
"profile_visibility": "Видимость профиля",
"profile_visibility_description": "Выберите, кто может видеть ваш профиль и библиотеку",
"public": "Общественный",
"required_field": "Это поле обязательно к заполнению",
"source_already_exists": "Этот источник уже добавлен",
"user_unblocked": "Пользователь разблокирован"
}, },
"notifications": { "notifications": {
"download_complete": "Загрузка завершена", "download_complete": "Загрузка завершена",
"game_ready_to_install": "{{title}} готова к установке", "game_ready_to_install": "{{title}} готова к установке",
"repack_list_updated": "Список репаков обновлен", "repack_list_updated": "Список репаков обновлен",
"repack_count_one": "{{count}} репак добавлен", "repack_count_one": "{{count}} репак добавлен",
"repack_count_other": "{{count}} репаков добавлено", "repack_count_other": "{{count}} репаков добавлено"
"new_update_available": "Доступна версия {{version}}",
"restart_to_install_update": "Перезапустите Hydra для установки обновления"
}, },
"system_tray": { "system_tray": {
"open": "Открыть Hydra", "open": "Открыть Hydra",
@@ -258,7 +228,7 @@
"no_recent_activity_description": "Вы давно ни во что не играли. Пора это изменить!", "no_recent_activity_description": "Вы давно ни во что не играли. Пора это изменить!",
"display_name": "Отображаемое имя", "display_name": "Отображаемое имя",
"saving": "Сохранение", "saving": "Сохранение",
"save": "Сохранить", "save": "Сохранено",
"edit_profile": "Редактировать Профиль", "edit_profile": "Редактировать Профиль",
"saved_successfully": "Успешно сохранено", "saved_successfully": "Успешно сохранено",
"try_again": "Пожалуйста, попробуйте ещё раз", "try_again": "Пожалуйста, попробуйте ещё раз",
@@ -267,52 +237,6 @@
"successfully_signed_out": "Успешный выход из аккаунта", "successfully_signed_out": "Успешный выход из аккаунта",
"sign_out": "Выйти", "sign_out": "Выйти",
"playing_for": "Сыграно {{amount}}", "playing_for": "Сыграно {{amount}}",
"sign_out_modal_text": "Ваша библиотека связана с текущей учетной записью. При выходе из системы ваша библиотека станет недоступна, и прогресс не будет сохранен. Выйти?", "sign_out_modal_text": "Ваша библиотека связана с текущей учетной записью. При выходе из системы ваша библиотека станет недоступна, и прогресс не будет сохранен. Выйти?"
"add_friends": "Добавить друзей",
"add": "Добавить",
"friend_code": "Код друга",
"see_profile": "Просмотреть профиль",
"sending": "Отправка",
"friend_request_sent": "Запрос в друзья отправлен",
"friends": "Друзья",
"friends_list": "Список друзей",
"user_not_found": "Пользователь не найден",
"block_user": "Заблокировать пользователя",
"add_friend": "Добавить друга",
"request_sent": "Запрос отправлен",
"request_received": "Запрос получен",
"accept_request": "Принять запрос",
"ignore_request": "Игнорировать запрос",
"cancel_request": "Отменить запрос",
"undo_friendship": "Удалить друга",
"request_accepted": "Запрос принят",
"user_blocked_successfully": "Пользователь успешно заблокирован",
"user_block_modal_text": "{{displayName}} будет заблокирован",
"blocked_users": "Заблокированные пользователи",
"unblock": "Разблокировать",
"no_friends_added": "Вы ещё не добавили ни одного друга",
"pending": "Ожидание",
"no_pending_invites": "У вас нет запросов ожидающих ответа",
"no_blocked_users": "Вы не заблокировали ни одного пользователя",
"friend_code_copied": "Код друга скопирован",
"displayname_max_length": "Отображаемое имя должно содержать не более 50 символов.",
"displayname_min_length": "Отображаемое имя должно содержать не менее 3 символов.",
"image_process_failure": "Сбой при обработке изображения",
"locked_profile": "Этот профиль является частным",
"privacy_hint": "Чтобы указать, кто может это видеть, перейдите в <0>Настройки</0>.",
"profile_locked": "",
"profile_reported": "Профиль сообщил",
"report": "Отчет",
"report_description": "Дополнительная информация",
"report_description_placeholder": "Дополнительная информация",
"report_profile": "Пожаловаться на этот профиль",
"report_reason": "Почему вы жалуетесь на этот профиль?",
"report_reason_hate": "Разжигание ненависти",
"report_reason_other": "Другой",
"report_reason_sexual_content": "Сексуальный контент",
"report_reason_spam": "Спам",
"report_reason_violence": "Насилие",
"required_field": "Это поле обязательно к заполнению",
"undo_friendship_modal_text": "Это отменит вашу дружбу с {{displayName}}."
} }
} }

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "Türkçe",
"home": { "home": {
"featured": "Öne çıkan", "featured": "Öne çıkan",
"trending": "Popüler", "trending": "Popüler",

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "Українська",
"app": { "app": {
"successfully_signed_in": "Успішний вхід в систему" "successfully_signed_in": "Успішний вхід в систему"
}, },

View File

@@ -1,5 +1,4 @@
{ {
"language_name": "中文",
"app": { "app": {
"successfully_signed_in": "已成功登录" "successfully_signed_in": "已成功登录"
}, },

View File

@@ -3,8 +3,11 @@ import path from "node:path";
export const defaultDownloadsPath = app.getPath("downloads"); export const defaultDownloadsPath = app.getPath("downloads");
export const databaseDirectory = path.join(app.getPath("appData"), "hydra"); export const databasePath = path.join(
export const databasePath = path.join(databaseDirectory, "hydra.db"); app.getPath("appData"),
"hydra",
"hydra.db"
);
export const logsPath = path.join(app.getPath("appData"), "hydra", "logs"); export const logsPath = path.join(app.getPath("appData"), "hydra", "logs");

View File

@@ -6,22 +6,32 @@ import {
GameShopCache, GameShopCache,
Repack, Repack,
UserPreferences, UserPreferences,
UserAuth,
} from "@main/entity"; } from "@main/entity";
import type { BetterSqlite3ConnectionOptions } from "typeorm/driver/better-sqlite3/BetterSqlite3ConnectionOptions";
import { databasePath } from "./constants"; import { databasePath } from "./constants";
import migrations from "./migrations";
import { UserAuth } from "./entity/user-auth";
export const dataSource = new DataSource({ export const createDataSource = (
type: "better-sqlite3", options: Partial<BetterSqlite3ConnectionOptions>
entities: [ ) =>
Game, new DataSource({
Repack, type: "better-sqlite3",
UserPreferences, entities: [
GameShopCache, Game,
DownloadSource, Repack,
DownloadQueue, UserPreferences,
UserAuth, GameShopCache,
], DownloadSource,
synchronize: false, DownloadQueue,
database: databasePath, UserAuth,
],
synchronize: true,
database: databasePath,
...options,
});
export const dataSource = createDataSource({
migrations,
}); });

80
src/main/declaration.d.ts vendored Normal file
View File

@@ -0,0 +1,80 @@
declare module "aria2" {
export type Aria2Status =
| "active"
| "waiting"
| "paused"
| "error"
| "complete"
| "removed";
export interface StatusResponse {
gid: string;
status: Aria2Status;
totalLength: string;
completedLength: string;
uploadLength: string;
bitfield: string;
downloadSpeed: string;
uploadSpeed: string;
infoHash?: string;
numSeeders?: string;
seeder?: boolean;
pieceLength: string;
numPieces: string;
connections: string;
errorCode?: string;
errorMessage?: string;
followedBy?: string[];
following: string;
belongsTo: string;
dir: string;
files: {
path: string;
length: string;
completedLength: string;
selected: string;
}[];
bittorrent?: {
announceList: string[][];
comment: string;
creationDate: string;
mode: "single" | "multi";
info: {
name: string;
verifiedLength: string;
verifyIntegrityPending: string;
};
};
}
export default class Aria2 {
constructor(options: any);
open: () => Promise<void>;
call(
method: "addUri",
uris: string[],
options: { dir: string }
): Promise<string>;
call(
method: "tellStatus",
gid: string,
keys?: string[]
): Promise<StatusResponse>;
call(method: "pause", gid: string): Promise<string>;
call(method: "forcePause", gid: string): Promise<string>;
call(method: "unpause", gid: string): Promise<string>;
call(method: "remove", gid: string): Promise<string>;
call(method: "forceRemove", gid: string): Promise<string>;
call(method: "pauseAll"): Promise<string>;
call(method: "forcePauseAll"): Promise<string>;
listNotifications: () => [
"onDownloadStart",
"onDownloadPause",
"onDownloadStop",
"onDownloadComplete",
"onDownloadError",
"onBtDownloadComplete",
];
on: (event: string, callback: (params: any) => void) => void;
}
}

View File

@@ -9,8 +9,9 @@ import {
} from "typeorm"; } from "typeorm";
import { Repack } from "./repack.entity"; import { Repack } from "./repack.entity";
import type { GameShop, GameStatus } from "@types"; import type { GameShop } from "@types";
import { Downloader } from "@shared"; import { Downloader } from "@shared";
import type { Aria2Status } from "aria2";
import type { DownloadQueue } from "./download-queue.entity"; import type { DownloadQueue } from "./download-queue.entity";
@Entity("game") @Entity("game")
@@ -46,7 +47,7 @@ export class Game {
shop: GameShop; shop: GameShop;
@Column("text", { nullable: true }) @Column("text", { nullable: true })
status: GameStatus | null; status: Aria2Status | null;
@Column("int", { default: Downloader.Torrent }) @Column("int", { default: Downloader.Torrent })
downloader: Downloader; downloader: Downloader;

View File

@@ -16,12 +16,15 @@ export class Repack {
@Column("text", { unique: true }) @Column("text", { unique: true })
title: string; title: string;
/**
* @deprecated Use uris instead
*/
@Column("text", { unique: true }) @Column("text", { unique: true })
magnet: string; magnet: string;
/**
* @deprecated
*/
@Column("int", { nullable: true })
page: number;
@Column("text") @Column("text")
repacker: string; repacker: string;
@@ -34,9 +37,6 @@ export class Repack {
@ManyToOne(() => DownloadSource, { nullable: true, onDelete: "CASCADE" }) @ManyToOne(() => DownloadSource, { nullable: true, onDelete: "CASCADE" })
downloadSource: DownloadSource; downloadSource: DownloadSource;
@Column("text", { default: "[]" })
uris: string;
@CreateDateColumn() @CreateDateColumn()
createdAt: Date; createdAt: Date;

View File

@@ -1,5 +1,4 @@
import jwt from "jsonwebtoken"; import jwt from "jsonwebtoken";
import * as Sentry from "@sentry/electron/main";
import { userAuthRepository } from "@main/repository"; import { userAuthRepository } from "@main/repository";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
@@ -9,9 +8,6 @@ const getSessionHash = async (_event: Electron.IpcMainInvokeEvent) => {
if (!auth) return null; if (!auth) return null;
const payload = jwt.decode(auth.accessToken) as jwt.JwtPayload; const payload = jwt.decode(auth.accessToken) as jwt.JwtPayload;
Sentry.setContext("sessionId", payload.sessionId);
return payload.sessionId; return payload.sessionId;
}; };

View File

@@ -1,11 +1,5 @@
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import * as Sentry from "@sentry/electron/main"; import { DownloadManager, HydraApi, gamesPlaytime } from "@main/services";
import {
DownloadManager,
HydraApi,
PythonInstance,
gamesPlaytime,
} from "@main/services";
import { dataSource } from "@main/data-source"; import { dataSource } from "@main/data-source";
import { DownloadQueue, Game, UserAuth } from "@main/entity"; import { DownloadQueue, Game, UserAuth } from "@main/entity";
@@ -25,20 +19,12 @@ const signOut = async (_event: Electron.IpcMainInvokeEvent) => {
gamesPlaytime.clear(); gamesPlaytime.clear();
}); });
/* Removes user from Sentry */ /* Disconnects aria2 */
Sentry.setUser(null); DownloadManager.disconnect();
/* Cancels any ongoing downloads */
DownloadManager.cancelDownload();
/* Disconnects libtorrent */
PythonInstance.killTorrent();
HydraApi.handleSignOut();
await Promise.all([ await Promise.all([
databaseOperations, databaseOperations,
HydraApi.post("/auth/logout").catch(() => {}), HydraApi.post("/auth/logout").catch(),
]); ]);
}; };

View File

@@ -3,7 +3,6 @@ import { registerEvent } from "../register-event";
import updater, { UpdateInfo } from "electron-updater"; import updater, { UpdateInfo } from "electron-updater";
import { WindowManager } from "@main/services"; import { WindowManager } from "@main/services";
import { app } from "electron"; import { app } from "electron";
import { publishNotificationUpdateReadyToInstall } from "@main/services/notifications";
const { autoUpdater } = updater; const { autoUpdater } = updater;
@@ -21,17 +20,13 @@ const mockValuesForDebug = () => {
sendEvent({ type: "update-downloaded" }); sendEvent({ type: "update-downloaded" });
}; };
const newVersionInfo = { version: "" };
const checkForUpdates = async (_event: Electron.IpcMainInvokeEvent) => { const checkForUpdates = async (_event: Electron.IpcMainInvokeEvent) => {
autoUpdater autoUpdater
.once("update-available", (info: UpdateInfo) => { .once("update-available", (info: UpdateInfo) => {
sendEvent({ type: "update-available", info }); sendEvent({ type: "update-available", info });
newVersionInfo.version = info.version;
}) })
.once("update-downloaded", () => { .once("update-downloaded", () => {
sendEvent({ type: "update-downloaded" }); sendEvent({ type: "update-downloaded" });
publishNotificationUpdateReadyToInstall(newVersionInfo.version);
}); });
if (app.isPackaged) { if (app.isPackaged) {

View File

@@ -1,44 +1,36 @@
import type { GameShop } from "@types"; import { getSteamAppAsset } from "@main/helpers";
import type { CatalogueEntry, GameShop } from "@types";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import { HydraApi, RepacksManager } from "@main/services"; import { RepacksManager, requestSteam250 } from "@main/services";
import { CatalogueCategory, formatName, steamUrlBuilder } from "@shared"; import { formatName } from "@shared";
import { steamGamesWorker } from "@main/workers";
const getCatalogue = async ( const resultSize = 12;
_event: Electron.IpcMainInvokeEvent,
category: CatalogueCategory
) => {
const params = new URLSearchParams({
take: "12",
skip: "0",
});
const response = await HydraApi.get<{ objectId: string; shop: GameShop }[]>( const getCatalogue = async (_event: Electron.IpcMainInvokeEvent) => {
`/games/${category}?${params.toString()}`, const trendingGames = await requestSteam250("/90day");
{}, const results: CatalogueEntry[] = [];
{ needsAuth: false }
);
return Promise.all( for (let i = 0; i < resultSize; i++) {
response.map(async (game) => { if (!trendingGames[i]) {
const steamGame = await steamGamesWorker.run(Number(game.objectId), { i++;
name: "getById", continue;
}); }
const repacks = RepacksManager.search({ const { title, objectID } = trendingGames[i]!;
query: formatName(steamGame.name), const repacks = RepacksManager.search({ query: formatName(title) });
});
return { const catalogueEntry = {
title: steamGame.name, objectID,
shop: game.shop, title,
repacks, shop: "steam" as GameShop,
cover: steamUrlBuilder.library(game.objectId), cover: getSteamAppAsset("library", objectID),
objectID: game.objectId, };
};
}) results.push({ ...catalogueEntry, repacks });
); }
return results;
}; };
registerEvent("getCatalogue", getCatalogue); registerEvent("getCatalogue", getCatalogue);

View File

@@ -1,23 +0,0 @@
import type { GameShop } from "@types";
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
import type { GameStats } from "@types";
const getGameStats = async (
_event: Electron.IpcMainInvokeEvent,
objectId: string,
shop: GameShop
) => {
const params = new URLSearchParams({
objectId,
shop,
});
const response = await HydraApi.get<GameStats>(
`/games/stats?${params.toString()}`
);
return response;
};
registerEvent("getGameStats", getGameStats);

View File

@@ -3,7 +3,7 @@ import { shuffle } from "lodash-es";
import { getSteam250List } from "@main/services"; import { getSteam250List } from "@main/services";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import { getSteamGameById } from "../helpers/search-games"; import { searchSteamGames } from "../helpers/search-games";
import type { Steam250Game } from "@types"; import type { Steam250Game } from "@types";
const state = { games: Array<Steam250Game>(), index: 0 }; const state = { games: Array<Steam250Game>(), index: 0 };
@@ -12,10 +12,14 @@ const filterGames = async (games: Steam250Game[]) => {
const results: Steam250Game[] = []; const results: Steam250Game[] = [];
for (const game of games) { for (const game of games) {
const steamGame = await getSteamGameById(game.objectID); const catalogue = await searchSteamGames({ query: game.title });
if (steamGame?.repacks.length) { if (catalogue.length) {
results.push(game); const [steamGame] = catalogue;
if (steamGame.repacks.length) {
results.push(game);
}
} }
} }

View File

@@ -1,22 +0,0 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
import { userPreferencesRepository } from "@main/repository";
import { TrendingGame } from "@types";
const getTrendingGames = async (_event: Electron.IpcMainInvokeEvent) => {
const userPreferences = await userPreferencesRepository.findOne({
where: { id: 1 },
});
const language = userPreferences?.language || "en";
const trendingGames = await HydraApi.get<TrendingGame[]>(
"/games/trending",
{ language },
{ needsAuth: false }
).catch(() => []);
return trendingGames;
};
registerEvent("getTrendingGames", getTrendingGames);

View File

@@ -1,25 +1,10 @@
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import { convertSteamGameToCatalogueEntry } from "../helpers/search-games"; import { searchSteamGames } from "../helpers/search-games";
import { CatalogueEntry } from "@types"; import { CatalogueEntry } from "@types";
import { HydraApi, RepacksManager } from "@main/services";
const searchGamesEvent = async ( const searchGamesEvent = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
query: string query: string
): Promise<CatalogueEntry[]> => { ): Promise<CatalogueEntry[]> => searchSteamGames({ query, limit: 12 });
const games = await HydraApi.get<
{ objectId: string; title: string; shop: string }[]
>("/games/search", { title: query, take: 12, skip: 0 }, { needsAuth: false });
const steamGames = games.map((game) => {
return convertSteamGameToCatalogueEntry({
id: Number(game.objectId),
name: game.title,
clientIcon: null,
});
});
return RepacksManager.findRepacksForCatalogueEntries(steamGames);
};
registerEvent("searchGames", searchGamesEvent); registerEvent("searchGames", searchGamesEvent);

View File

@@ -1,11 +1,16 @@
import { downloadSourceRepository } from "@main/repository"; import { downloadSourceRepository } from "@main/repository";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
const getDownloadSources = async (_event: Electron.IpcMainInvokeEvent) => const getDownloadSources = async (_event: Electron.IpcMainInvokeEvent) => {
downloadSourceRepository.find({ return downloadSourceRepository
order: { .createQueryBuilder("downloadSource")
createdAt: "DESC", .leftJoin("downloadSource.repacks", "repacks")
}, .orderBy("downloadSource.createdAt", "DESC")
}); .loadRelationCountAndMap(
"downloadSource.repackCount",
"downloadSource.repacks"
)
.getMany();
};
registerEvent("getDownloadSources", getDownloadSources); registerEvent("getDownloadSources", getDownloadSources);

View File

@@ -1,12 +1,17 @@
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import axios from "axios";
import { downloadSourceRepository } from "@main/repository"; import { downloadSourceRepository } from "@main/repository";
import { downloadSourceSchema } from "../helpers/validators";
import { RepacksManager } from "@main/services"; import { RepacksManager } from "@main/services";
import { downloadSourceWorker } from "@main/workers";
const validateDownloadSource = async ( const validateDownloadSource = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
url: string url: string
) => { ) => {
const response = await axios.get(url);
const source = downloadSourceSchema.parse(response.data);
const existingSource = await downloadSourceRepository.findOne({ const existingSource = await downloadSourceRepository.findOne({
where: { url }, where: { url },
}); });
@@ -16,12 +21,14 @@ const validateDownloadSource = async (
const repacks = RepacksManager.repacks; const repacks = RepacksManager.repacks;
return downloadSourceWorker.run( const existingUris = source.downloads
{ url, repacks }, .flatMap((download) => download.uris)
{ .filter((uri) => repacks.some((repack) => repack.magnet === uri));
name: "validateDownloadSource",
} return {
); name: source.name,
downloadCount: source.downloads.length - existingUris.length,
};
}; };
registerEvent("validateDownloadSource", validateDownloadSource); registerEvent("validateDownloadSource", validateDownloadSource);

View File

@@ -1,10 +0,0 @@
import { shell } from "electron";
export const parseExecutablePath = (path: string) => {
if (process.platform === "win32" && path.endsWith(".lnk")) {
const { target } = shell.readShortcutLink(path);
return target;
}
return path;
};

View File

@@ -1,8 +1,11 @@
import { orderBy } from "lodash-es";
import flexSearch from "flexsearch";
import type { GameShop, CatalogueEntry, SteamGame } from "@types"; import type { GameShop, CatalogueEntry, SteamGame } from "@types";
import { getSteamAppAsset } from "@main/helpers";
import { steamGamesWorker } from "@main/workers"; import { steamGamesWorker } from "@main/workers";
import { RepacksManager } from "@main/services"; import { RepacksManager } from "@main/services";
import { steamUrlBuilder } from "@shared";
export interface SearchGamesArgs { export interface SearchGamesArgs {
query?: string; query?: string;
@@ -16,22 +19,24 @@ export const convertSteamGameToCatalogueEntry = (
objectID: String(game.id), objectID: String(game.id),
title: game.name, title: game.name,
shop: "steam" as GameShop, shop: "steam" as GameShop,
cover: steamUrlBuilder.library(String(game.id)), cover: getSteamAppAsset("library", String(game.id)),
repacks: [], repacks: [],
}); });
export const getSteamGameById = async ( export const searchSteamGames = async (
objectId: string options: flexSearch.SearchOptions
): Promise<CatalogueEntry | null> => { ): Promise<CatalogueEntry[]> => {
const steamGame = await steamGamesWorker.run(Number(objectId), { const steamGames = (await steamGamesWorker.run(options, {
name: "getById", name: "search",
}); })) as SteamGame[];
if (!steamGame) return null; const result = RepacksManager.findRepacksForCatalogueEntries(
steamGames.map((game) => convertSteamGameToCatalogueEntry(game))
);
const catalogueEntry = convertSteamGameToCatalogueEntry(steamGame); return orderBy(
result,
const result = RepacksManager.findRepacksForCatalogueEntry(catalogueEntry); [({ repacks }) => repacks.length, "repacks"],
["desc"]
return result; );
}; };

View File

@@ -8,8 +8,6 @@ import "./catalogue/get-how-long-to-beat";
import "./catalogue/get-random-game"; import "./catalogue/get-random-game";
import "./catalogue/search-games"; import "./catalogue/search-games";
import "./catalogue/search-game-repacks"; import "./catalogue/search-game-repacks";
import "./catalogue/get-game-stats";
import "./catalogue/get-trending-games";
import "./hardware/get-disk-free-space"; import "./hardware/get-disk-free-space";
import "./library/add-game-to-library"; import "./library/add-game-to-library";
import "./library/create-game-shortcut"; import "./library/create-game-shortcut";
@@ -22,9 +20,9 @@ import "./library/open-game-executable-path";
import "./library/open-game-installer"; import "./library/open-game-installer";
import "./library/open-game-installer-path"; import "./library/open-game-installer-path";
import "./library/update-executable-path"; import "./library/update-executable-path";
import "./library/verify-executable-path";
import "./library/remove-game"; import "./library/remove-game";
import "./library/remove-game-from-library"; import "./library/remove-game-from-library";
import "./misc/is-user-logged-in";
import "./misc/open-external"; import "./misc/open-external";
import "./misc/show-open-dialog"; import "./misc/show-open-dialog";
import "./torrenting/cancel-game-download"; import "./torrenting/cancel-game-download";
@@ -46,22 +44,9 @@ import "./auth/sign-out";
import "./auth/open-auth-window"; import "./auth/open-auth-window";
import "./auth/get-session-hash"; import "./auth/get-session-hash";
import "./user/get-user"; import "./user/get-user";
import "./user/get-blocked-users";
import "./user/block-user";
import "./user/unblock-user";
import "./user/get-user-friends";
import "./user/get-user-stats";
import "./user/report-user";
import "./profile/get-friend-requests";
import "./profile/get-me"; import "./profile/get-me";
import "./profile/undo-friendship";
import "./profile/update-friend-request";
import "./profile/update-profile"; import "./profile/update-profile";
import "./profile/process-profile-image";
import "./profile/send-friend-request";
import { isPortableVersion } from "@main/helpers";
ipcMain.handle("ping", () => "pong"); ipcMain.handle("ping", () => "pong");
ipcMain.handle("getVersion", () => app.getVersion()); ipcMain.handle("getVersion", () => app.getVersion());
ipcMain.handle("isPortableVersion", () => isPortableVersion());
ipcMain.handle("getDefaultDownloadsPath", () => defaultDownloadsPath); ipcMain.handle("getDefaultDownloadsPath", () => defaultDownloadsPath);

View File

@@ -3,11 +3,10 @@ import { gameRepository } from "@main/repository";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import type { GameShop } from "@types"; import type { GameShop } from "@types";
import { getFileBase64 } from "@main/helpers"; import { getFileBase64, getSteamAppAsset } from "@main/helpers";
import { steamGamesWorker } from "@main/workers"; import { steamGamesWorker } from "@main/workers";
import { createGame } from "@main/services/library-sync"; import { createGame } from "@main/services/library-sync";
import { steamUrlBuilder } from "@shared";
const addGameToLibrary = async ( const addGameToLibrary = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
@@ -33,7 +32,7 @@ const addGameToLibrary = async (
}); });
const iconUrl = steamGame?.clientIcon const iconUrl = steamGame?.clientIcon
? steamUrlBuilder.icon(objectID, steamGame.clientIcon) ? getSteamAppAsset("icon", objectID, steamGame.clientIcon)
: null; : null;
await gameRepository await gameRepository
@@ -54,7 +53,18 @@ const addGameToLibrary = async (
const game = await gameRepository.findOne({ where: { objectID } }); const game = await gameRepository.findOne({ where: { objectID } });
createGame(game!).catch(() => {}); createGame(game!).then((response) => {
const {
id: remoteId,
playTimeInMilliseconds,
lastTimePlayed,
} = response.data;
gameRepository.update(
{ objectID },
{ remoteId, playTimeInMilliseconds, lastTimePlayed }
);
});
}); });
}; };

View File

@@ -1,45 +1,39 @@
import path from "node:path";
import { gameRepository } from "@main/repository"; import { gameRepository } from "@main/repository";
import { getProcesses } from "@main/helpers";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import { PythonInstance, logger } from "@main/services";
import sudo from "sudo-prompt";
import { app } from "electron";
const getKillCommand = (pid: number) => {
if (process.platform == "win32") {
return `taskkill /PID ${pid}`;
}
return `kill -9 ${pid}`;
};
const closeGame = async ( const closeGame = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
gameId: number gameId: number
) => { ) => {
const processes = await PythonInstance.getProcessList(); const processes = await getProcesses();
const game = await gameRepository.findOne({ const game = await gameRepository.findOne({
where: { id: gameId, isDeleted: false }, where: { id: gameId, isDeleted: false },
}); });
if (!game) return; if (!game) return false;
const executablePath = game.executablePath!;
const basename = path.win32.basename(executablePath);
const basenameWithoutExtension = path.win32.basename(
executablePath,
path.extname(executablePath)
);
const gameProcess = processes.find((runningProcess) => { const gameProcess = processes.find((runningProcess) => {
return runningProcess.exe === game.executablePath; if (process.platform === "win32") {
return runningProcess.name === basename;
}
return [basename, basenameWithoutExtension].includes(runningProcess.name);
}); });
if (gameProcess) { if (gameProcess) return process.kill(gameProcess.pid);
try { return false;
process.kill(gameProcess.pid);
} catch (err) {
sudo.exec(
getKillCommand(gameProcess.pid),
{ name: app.getName() },
(error, _stdout, _stderr) => {
logger.error(error);
}
);
}
}
}; };
registerEvent("closeGame", closeGame); registerEvent("closeGame", closeGame);

View File

@@ -4,7 +4,6 @@ import { IsNull, Not } from "typeorm";
import createDesktopShortcut from "create-desktop-shortcuts"; import createDesktopShortcut from "create-desktop-shortcuts";
import path from "node:path"; import path from "node:path";
import { app } from "electron"; import { app } from "electron";
import { removeSymbolsFromName } from "@shared";
const createGameShortcut = async ( const createGameShortcut = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
@@ -23,7 +22,7 @@ const createGameShortcut = async (
const options = { const options = {
filePath, filePath,
name: removeSymbolsFromName(game.title), name: game.title,
}; };
return createDesktopShortcut({ return createDesktopShortcut({

View File

@@ -45,6 +45,10 @@ const deleteGameFolder = async (
reject(); reject();
} }
const aria2ControlFilePath = `${folderPath}.aria2`;
if (fs.existsSync(aria2ControlFilePath))
fs.rmSync(aria2ControlFilePath);
resolve(); resolve();
} }
); );

View File

@@ -2,18 +2,15 @@ import { gameRepository } from "@main/repository";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import { shell } from "electron"; import { shell } from "electron";
import { parseExecutablePath } from "../helpers/parse-executable-path";
const openGame = async ( const openGame = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
gameId: number, gameId: number,
executablePath: string executablePath: string
) => { ) => {
const parsedPath = parseExecutablePath(executablePath); await gameRepository.update({ id: gameId }, { executablePath });
await gameRepository.update({ id: gameId }, { executablePath: parsedPath }); shell.openPath(executablePath);
shell.openPath(parsedPath);
}; };
registerEvent("openGame", openGame); registerEvent("openGame", openGame);

View File

@@ -20,7 +20,7 @@ const removeRemoveGameFromLibrary = async (gameId: number) => {
const game = await gameRepository.findOne({ where: { id: gameId } }); const game = await gameRepository.findOne({ where: { id: gameId } });
if (game?.remoteId) { if (game?.remoteId) {
HydraApi.delete(`/profile/games/${game.remoteId}`).catch(() => {}); HydraApi.delete(`/games/${game.remoteId}`);
} }
}; };

View File

@@ -1,7 +1,6 @@
import { gameRepository } from "@main/repository"; import { gameRepository } from "@main/repository";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import { parseExecutablePath } from "../helpers/parse-executable-path";
const updateExecutablePath = async ( const updateExecutablePath = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
@@ -13,7 +12,7 @@ const updateExecutablePath = async (
id, id,
}, },
{ {
executablePath: parseExecutablePath(executablePath), executablePath,
} }
); );
}; };

View File

@@ -1,13 +0,0 @@
import { gameRepository } from "@main/repository";
import { registerEvent } from "../register-event";
const verifyExecutablePathInUse = async (
_event: Electron.IpcMainInvokeEvent,
executablePath: string
) => {
return gameRepository.findOne({
where: { executablePath },
});
};
registerEvent("verifyExecutablePathInUse", verifyExecutablePathInUse);

View File

@@ -0,0 +1,8 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
const isUserLoggedIn = async (_event: Electron.IpcMainInvokeEvent) => {
return HydraApi.isLoggedIn();
};
registerEvent("isUserLoggedIn", isUserLoggedIn);

View File

@@ -1,11 +0,0 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
import { FriendRequest } from "@types";
const getFriendRequests = async (
_event: Electron.IpcMainInvokeEvent
): Promise<FriendRequest[]> => {
return HydraApi.get(`/profile/friend-requests`).catch(() => []);
};
registerEvent("getFriendRequests", getFriendRequests);

View File

@@ -1,33 +1,16 @@
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import * as Sentry from "@sentry/electron/main"; import { HydraApi } from "@main/services";
import { HydraApi, logger } from "@main/services";
import { UserProfile } from "@types"; import { UserProfile } from "@types";
import { userAuthRepository } from "@main/repository"; import { userAuthRepository } from "@main/repository";
import { steamUrlBuilder, UserNotLoggedInError } from "@shared"; import { logger } from "@main/services";
import { steamGamesWorker } from "@main/workers";
const getSteamGame = async (objectId: string) => {
try {
const steamGame = await steamGamesWorker.run(Number(objectId), {
name: "getById",
});
return {
title: steamGame.name,
iconUrl: steamUrlBuilder.icon(objectId, steamGame.clientIcon),
};
} catch (err) {
logger.error("Failed to get Steam game", err);
return null;
}
};
const getMe = async ( const getMe = async (
_event: Electron.IpcMainInvokeEvent _event: Electron.IpcMainInvokeEvent
): Promise<UserProfile | null> => { ): Promise<UserProfile | null> => {
return HydraApi.get(`/profile/me`) return HydraApi.get(`/profile/me`)
.then(async (me) => { .then((response) => {
const me = response.data;
userAuthRepository.upsert( userAuthRepository.upsert(
{ {
id: 1, id: 1,
@@ -38,33 +21,11 @@ const getMe = async (
["id"] ["id"]
); );
if (me.currentGame) {
const steamGame = await getSteamGame(me.currentGame.objectId);
if (steamGame) {
me.currentGame = {
...me.currentGame,
...steamGame,
};
}
}
Sentry.setUser({ id: me.id, username: me.username });
return me; return me;
}) })
.catch(async (err) => { .catch((err) => {
if (err instanceof UserNotLoggedInError) { logger.error("getMe", err);
return null; return userAuthRepository.findOne({ where: { id: 1 } });
}
const loggedUser = await userAuthRepository.findOne({ where: { id: 1 } });
if (loggedUser) {
return { ...loggedUser, id: loggedUser.userId };
}
return null;
}); });
}; };

View File

@@ -1,11 +0,0 @@
import { registerEvent } from "../register-event";
import { PythonInstance } from "@main/services";
const processProfileImage = async (
_event: Electron.IpcMainInvokeEvent,
path: string
) => {
return PythonInstance.processProfileImage(path);
};
registerEvent("processProfileImage", processProfileImage);

View File

@@ -1,11 +0,0 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
const sendFriendRequest = async (
_event: Electron.IpcMainInvokeEvent,
userId: string
) => {
return HydraApi.post("/profile/friend-requests", { friendCode: userId });
};
registerEvent("sendFriendRequest", sendFriendRequest);

View File

@@ -1,11 +0,0 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
const undoFriendship = async (
_event: Electron.IpcMainInvokeEvent,
userId: string
) => {
await HydraApi.delete(`/profile/friends/${userId}`);
};
registerEvent("undoFriendship", undoFriendship);

View File

@@ -1,19 +0,0 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
import { FriendRequestAction } from "@types";
const updateFriendRequest = async (
_event: Electron.IpcMainInvokeEvent,
userId: string,
action: FriendRequestAction
) => {
if (action == "CANCEL") {
return HydraApi.delete(`/profile/friend-requests/${userId}`);
}
return HydraApi.patch(`/profile/friend-requests/${userId}`, {
requestState: action,
});
};
registerEvent("updateFriendRequest", updateFriendRequest);

View File

@@ -1,56 +1,61 @@
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import { HydraApi, PythonInstance } from "@main/services"; import { HydraApi } from "@main/services";
import axios from "axios";
import fs from "node:fs"; import fs from "node:fs";
import path from "node:path"; import path from "node:path";
import type { UpdateProfileRequest, UserProfile } from "@types"; import { fileTypeFromFile } from "file-type";
import { omit } from "lodash-es"; import { UserProfile } from "@types";
import axios from "axios";
interface PresignedResponse { const patchUserProfile = async (
presignedUrl: string; displayName: string,
profileImageUrl: string; profileImageUrl?: string
} ) => {
if (profileImageUrl) {
const patchUserProfile = async (updateProfile: UpdateProfileRequest) => { return HydraApi.patch("/profile", {
return HydraApi.patch<UserProfile>("/profile", updateProfile); displayName,
}; profileImageUrl,
const getNewProfileImageUrl = async (localImageUrl: string) => {
const { imagePath, mimeType } =
await PythonInstance.processProfileImage(localImageUrl);
const stats = fs.statSync(imagePath);
const fileBuffer = fs.readFileSync(imagePath);
const fileSizeInBytes = stats.size;
const { presignedUrl, profileImageUrl } =
await HydraApi.post<PresignedResponse>(`/presigned-urls/profile-image`, {
imageExt: path.extname(imagePath).slice(1),
imageLength: fileSizeInBytes,
}); });
} else {
await axios.put(presignedUrl, fileBuffer, { return HydraApi.patch("/profile", {
headers: { displayName,
"Content-Type": mimeType, });
}, }
});
return profileImageUrl;
}; };
const updateProfile = async ( const updateProfile = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
updateProfile: UpdateProfileRequest displayName: string,
) => { newProfileImagePath: string | null
if (!updateProfile.profileImageUrl) { ): Promise<UserProfile> => {
return patchUserProfile(omit(updateProfile, "profileImageUrl")); if (!newProfileImagePath) {
return (await patchUserProfile(displayName)).data;
} }
const profileImageUrl = await getNewProfileImageUrl( const stats = fs.statSync(newProfileImagePath);
updateProfile.profileImageUrl const fileBuffer = fs.readFileSync(newProfileImagePath);
).catch(() => undefined); const fileSizeInBytes = stats.size;
return patchUserProfile({ ...updateProfile, profileImageUrl }); const profileImageUrl = await HydraApi.post(`/presigned-urls/profile-image`, {
imageExt: path.extname(newProfileImagePath).slice(1),
imageLength: fileSizeInBytes,
})
.then(async (preSignedResponse) => {
const { presignedUrl, profileImageUrl } = preSignedResponse.data;
const mimeType = await fileTypeFromFile(newProfileImagePath);
await axios.put(presignedUrl, fileBuffer, {
headers: {
"Content-Type": mimeType?.mime,
},
});
return profileImageUrl;
})
.catch(() => {
return undefined;
});
return (await patchUserProfile(displayName, profileImageUrl)).data;
}; };
registerEvent("updateProfile", updateProfile); registerEvent("updateProfile", updateProfile);

View File

@@ -1,112 +1,117 @@
import {
downloadQueueRepository,
gameRepository,
repackRepository,
} from "@main/repository";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import type { StartGameDownloadPayload } from "@types"; import type { StartGameDownloadPayload } from "@types";
import { getFileBase64 } from "@main/helpers"; import { getFileBase64, getSteamAppAsset } from "@main/helpers";
import { DownloadManager } from "@main/services"; import { DownloadManager } from "@main/services";
import { Not } from "typeorm"; import { Not } from "typeorm";
import { steamGamesWorker } from "@main/workers"; import { steamGamesWorker } from "@main/workers";
import { createGame } from "@main/services/library-sync"; import { createGame } from "@main/services/library-sync";
import { steamUrlBuilder } from "@shared";
import { dataSource } from "@main/data-source";
import { DownloadQueue, Game, Repack } from "@main/entity";
const startGameDownload = async ( const startGameDownload = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
payload: StartGameDownloadPayload payload: StartGameDownloadPayload
) => { ) => {
const { repackId, objectID, title, shop, downloadPath, downloader, uri } = const { repackId, objectID, title, shop, downloadPath, downloader } = payload;
payload;
return dataSource.transaction(async (transactionalEntityManager) => { const [game, repack] = await Promise.all([
const gameRepository = transactionalEntityManager.getRepository(Game); gameRepository.findOne({
const repackRepository = transactionalEntityManager.getRepository(Repack);
const downloadQueueRepository =
transactionalEntityManager.getRepository(DownloadQueue);
const [game, repack] = await Promise.all([
gameRepository.findOne({
where: {
objectID,
shop,
},
}),
repackRepository.findOne({
where: {
id: repackId,
},
}),
]);
if (!repack) return;
await DownloadManager.pauseDownload();
await gameRepository.update(
{ status: "active", progress: Not(1) },
{ status: "paused" }
);
if (game) {
await gameRepository.update(
{
id: game.id,
},
{
status: "active",
progress: 0,
bytesDownloaded: 0,
downloadPath,
downloader,
uri,
isDeleted: false,
}
);
} else {
const steamGame = await steamGamesWorker.run(Number(objectID), {
name: "getById",
});
const iconUrl = steamGame?.clientIcon
? steamUrlBuilder.icon(objectID, steamGame.clientIcon)
: null;
await gameRepository
.insert({
title,
iconUrl,
objectID,
downloader,
shop,
status: "active",
downloadPath,
uri,
})
.then((result) => {
if (iconUrl) {
getFileBase64(iconUrl).then((base64) =>
gameRepository.update({ objectID }, { iconUrl: base64 })
);
}
return result;
});
}
const updatedGame = await gameRepository.findOne({
where: { where: {
objectID, objectID,
shop,
}, },
}),
repackRepository.findOne({
where: {
id: repackId,
},
}),
]);
if (!repack) return;
await DownloadManager.pauseDownload();
await gameRepository.update(
{ status: "active", progress: Not(1) },
{ status: "paused" }
);
if (game) {
await gameRepository.update(
{
id: game.id,
},
{
status: "active",
progress: 0,
bytesDownloaded: 0,
downloadPath,
downloader,
uri: repack.magnet,
isDeleted: false,
}
);
} else {
const steamGame = await steamGamesWorker.run(Number(objectID), {
name: "getById",
}); });
createGame(updatedGame!).catch(() => {}); const iconUrl = steamGame?.clientIcon
? getSteamAppAsset("icon", objectID, steamGame.clientIcon)
: null;
await DownloadManager.cancelDownload(updatedGame!.id); await gameRepository
await DownloadManager.startDownload(updatedGame!); .insert({
title,
iconUrl,
objectID,
downloader,
shop,
status: "active",
downloadPath,
uri: repack.magnet,
})
.then((result) => {
if (iconUrl) {
getFileBase64(iconUrl).then((base64) =>
gameRepository.update({ objectID }, { iconUrl: base64 })
);
}
await downloadQueueRepository.delete({ game: { id: updatedGame!.id } }); return result;
await downloadQueueRepository.insert({ game: { id: updatedGame!.id } }); });
}
const updatedGame = await gameRepository.findOne({
where: {
objectID,
},
}); });
createGame(updatedGame!).then((response) => {
const {
id: remoteId,
playTimeInMilliseconds,
lastTimePlayed,
} = response.data;
gameRepository.update(
{ objectID },
{ remoteId, playTimeInMilliseconds, lastTimePlayed }
);
});
await downloadQueueRepository.delete({ game: { id: updatedGame!.id } });
await downloadQueueRepository.insert({ game: { id: updatedGame!.id } });
await DownloadManager.startDownload(updatedGame!);
}; };
registerEvent("startGameDownload", startGameDownload); registerEvent("startGameDownload", startGameDownload);

View File

@@ -1,41 +1,18 @@
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import AutoLaunch from "auto-launch"; import AutoLaunch from "auto-launch";
import { app } from "electron"; import { app } from "electron";
import path from "path";
import fs from "node:fs";
import { logger } from "@main/services";
const windowsStartupPath = path.join(
app.getPath("appData"),
"Microsoft",
"Windows",
"Start Menu",
"Programs",
"Startup"
);
const autoLaunch = async ( const autoLaunch = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
enabled: boolean enabled: boolean
) => { ) => {
if (!app.isPackaged) return;
const appLauncher = new AutoLaunch({ const appLauncher = new AutoLaunch({
name: app.getName(), name: app.getName(),
}); });
if (enabled) { if (enabled) {
appLauncher.enable().catch((err) => { appLauncher.enable().catch();
logger.error(err);
});
} else { } else {
if (process.platform == "win32") { appLauncher.disable().catch();
fs.rm(path.join(windowsStartupPath, "Hydra.vbs"), () => {});
}
appLauncher.disable().catch((err) => {
logger.error(err);
});
} }
}; };

View File

@@ -2,23 +2,17 @@ import { userPreferencesRepository } from "@main/repository";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import type { UserPreferences } from "@types"; import type { UserPreferences } from "@types";
import i18next from "i18next";
const updateUserPreferences = async ( const updateUserPreferences = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
preferences: Partial<UserPreferences> preferences: Partial<UserPreferences>
) => { ) =>
if (preferences.language) { userPreferencesRepository.upsert(
i18next.changeLanguage(preferences.language);
}
return userPreferencesRepository.upsert(
{ {
id: 1, id: 1,
...preferences, ...preferences,
}, },
["id"] ["id"]
); );
};
registerEvent("updateUserPreferences", updateUserPreferences); registerEvent("updateUserPreferences", updateUserPreferences);

View File

@@ -1,11 +0,0 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
const blockUser = async (
_event: Electron.IpcMainInvokeEvent,
userId: string
) => {
await HydraApi.post(`/users/${userId}/block`);
};
registerEvent("blockUser", blockUser);

View File

@@ -1,13 +0,0 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
import { UserBlocks } from "@types";
export const getBlockedUsers = async (
_event: Electron.IpcMainInvokeEvent,
take: number,
skip: number
): Promise<UserBlocks> => {
return HydraApi.get(`/profile/blocks`, { take, skip });
};
registerEvent("getBlockedUsers", getBlockedUsers);

View File

@@ -1,29 +0,0 @@
import { userAuthRepository } from "@main/repository";
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
import { UserFriends } from "@types";
export const getUserFriends = async (
userId: string,
take: number,
skip: number
): Promise<UserFriends> => {
const loggedUser = await userAuthRepository.findOne({ where: { id: 1 } });
if (loggedUser?.userId === userId) {
return HydraApi.get(`/profile/friends`, { take, skip });
}
return HydraApi.get(`/users/${userId}/friends`, { take, skip });
};
const getUserFriendsEvent = async (
_event: Electron.IpcMainInvokeEvent,
userId: string,
take: number,
skip: number
) => {
return getUserFriends(userId, take, skip);
};
registerEvent("getUserFriends", getUserFriendsEvent);

View File

@@ -1,12 +0,0 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
import type { UserStats } from "@types";
export const getUserStats = async (
_event: Electron.IpcMainInvokeEvent,
userId: string
): Promise<UserStats> => {
return HydraApi.get(`/users/${userId}/stats`);
};
registerEvent("getUserStats", getUserStats);

View File

@@ -1,79 +1,54 @@
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import { HydraApi, logger } from "@main/services"; import { HydraApi } from "@main/services";
import { steamGamesWorker } from "@main/workers"; import { steamGamesWorker } from "@main/workers";
import type { UserProfile } from "@types"; import { UserProfile } from "@types";
import { steamUrlBuilder } from "@shared"; import { convertSteamGameToCatalogueEntry } from "../helpers/search-games";
import { getSteamAppAsset } from "@main/helpers";
const getSteamGame = async (objectId: string) => {
try {
const steamGame = await steamGamesWorker.run(Number(objectId), {
name: "getById",
});
return {
title: steamGame.name,
iconUrl: steamUrlBuilder.icon(objectId, steamGame.clientIcon),
};
} catch (err) {
logger.error("Failed to get Steam game", err);
return null;
}
};
const getUser = async ( const getUser = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
userId: string userId: string
): Promise<UserProfile | null> => { ): Promise<UserProfile | null> => {
try { try {
const profile = await HydraApi.get<UserProfile | null>(`/users/${userId}`); const response = await HydraApi.get(`/user/${userId}`);
const profile = response.data;
if (!profile) return null;
const recentGames = await Promise.all( const recentGames = await Promise.all(
profile.recentGames profile.recentGames.map(async (game) => {
.map(async (game) => { const steamGame = await steamGamesWorker.run(Number(game.objectId), {
const steamGame = await getSteamGame(game.objectId); name: "getById",
});
const iconUrl = steamGame?.clientIcon
? getSteamAppAsset("icon", game.objectId, steamGame.clientIcon)
: null;
return { return {
...game, ...game,
...steamGame, ...convertSteamGameToCatalogueEntry(steamGame),
}; iconUrl,
}) };
.filter((game) => game) })
); );
const libraryGames = await Promise.all( const libraryGames = await Promise.all(
profile.libraryGames profile.libraryGames.map(async (game) => {
.map(async (game) => { const steamGame = await steamGamesWorker.run(Number(game.objectId), {
const steamGame = await getSteamGame(game.objectId); name: "getById",
});
const iconUrl = steamGame?.clientIcon
? getSteamAppAsset("icon", game.objectId, steamGame.clientIcon)
: null;
return { return {
...game, ...game,
...steamGame, ...convertSteamGameToCatalogueEntry(steamGame),
}; iconUrl,
}) };
.filter((game) => game) })
); );
if (profile.currentGame) { return { ...profile, libraryGames, recentGames };
const steamGame = await getSteamGame(profile.currentGame.objectId);
if (steamGame) {
profile.currentGame = {
...profile.currentGame,
...steamGame,
};
}
}
return {
...profile,
libraryGames,
recentGames,
};
} catch (err) { } catch (err) {
console.log(err);
return null; return null;
} }
}; };

View File

@@ -1,16 +0,0 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
export const reportUser = async (
_event: Electron.IpcMainInvokeEvent,
userId: string,
reason: string,
description: string
): Promise<void> => {
return HydraApi.post(`/users/${userId}/report`, {
reason,
description,
});
};
registerEvent("reportUser", reportUser);

View File

@@ -1,11 +0,0 @@
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
const unblockUser = async (
_event: Electron.IpcMainInvokeEvent,
userId: string
) => {
await HydraApi.post(`/users/${userId}/unblock`);
};
registerEvent("unblockUser", unblockUser);

View File

@@ -17,8 +17,7 @@ export const insertDownloadsFromSource = async (
const repacks: QueryDeepPartialEntity<Repack>[] = downloads.map( const repacks: QueryDeepPartialEntity<Repack>[] = downloads.map(
(download) => ({ (download) => ({
title: download.title, title: download.title,
uris: JSON.stringify(download.uris), magnet: download.uris[0],
magnet: download.uris[0]!,
fileSize: download.fileSize, fileSize: download.fileSize,
repacker: downloadSource.name, repacker: downloadSource.name,
uploadDate: download.uploadDate, uploadDate: download.uploadDate,

View File

@@ -1,7 +1,23 @@
import axios from "axios"; import axios from "axios";
import { JSDOM } from "jsdom";
import UserAgent from "user-agents"; import UserAgent from "user-agents";
export const getSteamAppAsset = (
category: "library" | "hero" | "logo" | "icon",
objectID: string,
clientIcon?: string
) => {
if (category === "library")
return `https://steamcdn-a.akamaihd.net/steam/apps/${objectID}/header.jpg`;
if (category === "hero")
return `https://steamcdn-a.akamaihd.net/steam/apps/${objectID}/library_hero.jpg`;
if (category === "logo")
return `https://cdn.cloudflare.steamstatic.com/steam/apps/${objectID}/logo.png`;
return `https://cdn.cloudflare.steamstatic.com/steamcommunity/public/images/apps/${objectID}/${clientIcon}.ico`;
};
export const getFileBuffer = async (url: string) => export const getFileBuffer = async (url: string) =>
fetch(url, { method: "GET" }).then((response) => fetch(url, { method: "GET" }).then((response) =>
response.arrayBuffer().then((buffer) => Buffer.from(buffer)) response.arrayBuffer().then((buffer) => Buffer.from(buffer))
@@ -17,25 +33,29 @@ export const getFileBase64 = async (url: string) =>
}) })
); );
export const steamUrlBuilder = {
library: (objectID: string) =>
`https://steamcdn-a.akamaihd.net/steam/apps/${objectID}/header.jpg`,
libraryHero: (objectID: string) =>
`https://steamcdn-a.akamaihd.net/steam/apps/${objectID}/library_hero.jpg`,
logo: (objectID: string) =>
`https://cdn.cloudflare.steamstatic.com/steam/apps/${objectID}/logo.png`,
};
export const sleep = (ms: number) => export const sleep = (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms)); new Promise((resolve) => setTimeout(resolve, ms));
export const requestWebPage = async (url: string) => { export const requestWebPage = async (url: string) => {
const userAgent = new UserAgent(); const userAgent = new UserAgent();
const data = await axios return axios
.get(url, { .get(url, {
headers: { headers: {
"User-Agent": userAgent.toString(), "User-Agent": userAgent.toString(),
}, },
}) })
.then((response) => response.data); .then((response) => response.data);
const { window } = new JSDOM(data);
return window.document;
}; };
export const isPortableVersion = () => export * from "./ps";
process.env.PORTABLE_EXECUTABLE_FILE != null;
export * from "./download-source"; export * from "./download-source";

33
src/main/helpers/ps.ts Normal file
View File

@@ -0,0 +1,33 @@
import psList from "ps-list";
import path from "node:path";
import childProcess from "node:child_process";
import { promisify } from "node:util";
import { app } from "electron";
const TEN_MEGABYTES = 1000 * 1000 * 10;
const execFile = promisify(childProcess.execFile);
export const getProcesses = async () => {
if (process.platform == "win32") {
const binaryPath = app.isPackaged
? path.join(process.resourcesPath, "fastlist.exe")
: path.join(__dirname, "..", "..", "fastlist.exe");
const { stdout } = await execFile(binaryPath, {
maxBuffer: TEN_MEGABYTES,
windowsHide: true,
});
return stdout
.trim()
.split("\r\n")
.map((line) => line.split("\t"))
.map(([pid, ppid, name]) => ({
pid: Number.parseInt(pid, 10),
ppid: Number.parseInt(ppid, 10),
name,
}));
} else {
return psList();
}
};

View File

@@ -1,17 +1,13 @@
import { app, BrowserWindow, net, protocol } from "electron"; import { app, BrowserWindow, net, protocol } from "electron";
import { init } from "@sentry/electron/main";
import updater from "electron-updater"; import updater from "electron-updater";
import i18n from "i18next"; import i18n from "i18next";
import path from "node:path"; import path from "node:path";
import url from "node:url"; import url from "node:url";
import fs from "node:fs";
import { electronApp, optimizer } from "@electron-toolkit/utils"; import { electronApp, optimizer } from "@electron-toolkit/utils";
import { logger, PythonInstance, WindowManager } from "@main/services"; import { DownloadManager, logger, WindowManager } from "@main/services";
import { dataSource } from "@main/data-source"; import { dataSource } from "@main/data-source";
import resources from "@locales"; import * as resources from "@locales";
import { userPreferencesRepository } from "@main/repository"; import { userPreferencesRepository } from "@main/repository";
import { knexClient, migrationConfig } from "./knex-client";
import { databaseDirectory } from "./constants";
const { autoUpdater } = updater; const { autoUpdater } = updater;
@@ -26,12 +22,6 @@ autoUpdater.logger = logger;
const gotTheLock = app.requestSingleInstanceLock(); const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) app.quit(); if (!gotTheLock) app.quit();
if (import.meta.env.MAIN_VITE_SENTRY_DSN) {
init({
dsn: import.meta.env.MAIN_VITE_SENTRY_DSN,
});
}
app.commandLine.appendSwitch("--no-sandbox"); app.commandLine.appendSwitch("--no-sandbox");
i18n.init({ i18n.init({
@@ -55,22 +45,6 @@ if (process.defaultApp) {
app.setAsDefaultProtocolClient(PROTOCOL); app.setAsDefaultProtocolClient(PROTOCOL);
} }
const runMigrations = async () => {
if (!fs.existsSync(databaseDirectory)) {
fs.mkdirSync(databaseDirectory, { recursive: true });
}
await knexClient.migrate.list(migrationConfig).then((result) => {
logger.log(
"Migrations to run:",
result[1].map((migration) => migration.name)
);
});
await knexClient.migrate.latest(migrationConfig);
await knexClient.destroy();
};
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
@@ -82,15 +56,8 @@ app.whenReady().then(async () => {
return net.fetch(url.pathToFileURL(decodeURI(filePath)).toString()); return net.fetch(url.pathToFileURL(decodeURI(filePath)).toString());
}); });
await runMigrations()
.then(() => {
logger.log("Migrations executed successfully");
})
.catch((err) => {
logger.log("Migrations failed to run:", err);
});
await dataSource.initialize(); await dataSource.initialize();
await dataSource.runMigrations();
await import("./main"); await import("./main");
@@ -98,10 +65,6 @@ app.whenReady().then(async () => {
where: { id: 1 }, where: { id: 1 },
}); });
if (userPreferences?.language) {
i18n.changeLanguage(userPreferences.language);
}
WindowManager.createMainWindow(); WindowManager.createMainWindow();
WindowManager.createSystemTray(userPreferences?.language || "en"); WindowManager.createSystemTray(userPreferences?.language || "en");
}); });
@@ -112,15 +75,10 @@ app.on("browser-window-created", (_, window) => {
const handleDeepLinkPath = (uri?: string) => { const handleDeepLinkPath = (uri?: string) => {
if (!uri) return; if (!uri) return;
const url = new URL(uri);
try { if (url.host === "install-source") {
const url = new URL(uri); WindowManager.redirect(`settings${url.search}`);
if (url.host === "install-source") {
WindowManager.redirect(`settings${url.search}`);
}
} catch (error) {
logger.error("Error handling deep link", uri, error);
} }
}; };
@@ -150,8 +108,7 @@ app.on("window-all-closed", () => {
}); });
app.on("before-quit", () => { app.on("before-quit", () => {
/* Disconnects libtorrent */ DownloadManager.disconnect();
PythonInstance.kill();
}); });
app.on("activate", () => { app.on("activate", () => {

View File

@@ -1,30 +0,0 @@
import knex, { Knex } from "knex";
import { databasePath } from "./constants";
import { Hydra2_0_3 } from "./migrations/20240830143811_Hydra_2_0_3";
import { RepackUris } from "./migrations/20240830143906_RepackUris";
import { UpdateUserLanguage } from "./migrations/20240913213944_update_user_language";
export type HydraMigration = Knex.Migration & { name: string };
class MigrationSource implements Knex.MigrationSource<HydraMigration> {
getMigrations(): Promise<HydraMigration[]> {
return Promise.resolve([Hydra2_0_3, RepackUris, UpdateUserLanguage]);
}
getMigrationName(migration: HydraMigration): string {
return migration.name;
}
getMigration(migration: HydraMigration): Promise<Knex.Migration> {
return Promise.resolve(migration);
}
}
export const knexClient = knex({
client: "better-sqlite3",
connection: {
filename: databasePath,
},
});
export const migrationConfig: Knex.MigratorConfig = {
migrationSource: new MigrationSource(),
};

View File

@@ -1,10 +0,0 @@
const config = {
development: {
migrations: {
extension: "ts",
stub: "migrations/migration.stub",
},
},
};
export default config;

View File

@@ -1,9 +1,4 @@
import { import { DownloadManager, RepacksManager, startMainLoop } from "./services";
DownloadManager,
RepacksManager,
PythonInstance,
startMainLoop,
} from "./services";
import { import {
downloadQueueRepository, downloadQueueRepository,
repackRepository, repackRepository,
@@ -17,17 +12,18 @@ import { MoreThan } from "typeorm";
import { HydraApi } from "./services/hydra-api"; import { HydraApi } from "./services/hydra-api";
import { uploadGamesBatch } from "./services/library-sync"; import { uploadGamesBatch } from "./services/library-sync";
startMainLoop();
const loadState = async (userPreferences: UserPreferences | null) => { const loadState = async (userPreferences: UserPreferences | null) => {
RepacksManager.updateRepacks(); await RepacksManager.updateRepacks();
import("./events"); import("./events");
if (userPreferences?.realDebridApiToken) { if (userPreferences?.realDebridApiToken)
RealDebridClient.authorize(userPreferences?.realDebridApiToken); RealDebridClient.authorize(userPreferences?.realDebridApiToken);
}
HydraApi.setupApi().then(() => { HydraApi.setupApi().then(async () => {
uploadGamesBatch(); if (HydraApi.isLoggedIn()) uploadGamesBatch();
}); });
const [nextQueueItem] = await downloadQueueRepository.find({ const [nextQueueItem] = await downloadQueueRepository.find({
@@ -39,13 +35,8 @@ const loadState = async (userPreferences: UserPreferences | null) => {
}, },
}); });
if (nextQueueItem?.game.status === "active") { if (nextQueueItem?.game.status === "active")
DownloadManager.startDownload(nextQueueItem.game); DownloadManager.startDownload(nextQueueItem.game);
} else {
PythonInstance.spawn();
}
startMainLoop();
const now = new Date(); const now = new Date();

Some files were not shown because too many files have changed in this diff Show More