Compare commits

..

9 Commits

Author SHA1 Message Date
Zamitto
f4193ac42c Update build.yml 2025-02-21 22:34:32 -03:00
Zamitto
2495aea137 feat: update macos icon 2025-02-21 22:10:18 -03:00
Chubby Granny Chaser
285eadd0f4 ci: adding macos build to the pipeline 2025-02-21 23:19:53 +00:00
Chubby Granny Chaser
01b8430c6b ci: adding macos build to the pipeline 2025-02-21 23:11:45 +00:00
Chubby Granny Chaser
6e5d20f10c ci: adding macos build to the pipeline 2025-02-21 23:02:09 +00:00
Chubby Granny Chaser
d9b536506b ci: adding macos build to the pipeline 2025-02-21 22:56:06 +00:00
Chubby Granny Chaser
7b4b1cb230 ci: adding macos build to the pipeline 2025-02-21 22:49:46 +00:00
Chubby Granny Chaser
8252c9ee22 ci: adding macos build to the pipeline 2025-02-21 22:44:14 +00:00
Chubby Granny Chaser
eb65873cb7 ci: adding macos build to the pipeline 2025-02-21 22:39:03 +00:00
165 changed files with 1304 additions and 3358 deletions

View File

@@ -1,4 +1,2 @@
MAIN_VITE_API_URL=API_URL MAIN_VITE_API_URL=API_URL
MAIN_VITE_AUTH_URL=AUTH_URL MAIN_VITE_AUTH_URL=AUTH_URL
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID=
RENDERER_VITE_TORBOX_REFERRAL_CODE=

View File

@@ -10,8 +10,7 @@ jobs:
build: build:
strategy: strategy:
matrix: matrix:
os: [windows-latest, ubuntu-latest] os: [windows-latest, ubuntu-latest, macos-latest]
fail-fast: false
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -24,14 +23,14 @@ jobs:
with: with:
node-version: 20.18.0 node-version: 20.18.0
- name: Install dependencies
run: yarn --frozen-lockfile
- name: Install Python - name: Install Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: 3.9 python-version: 3.9
- name: Install dependencies
run: yarn
- name: Install dependencies - name: Install dependencies
run: pip install -r requirements.txt run: pip install -r requirements.txt
@@ -53,8 +52,19 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }} RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }}
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID: ${{ vars.RENDERER_VITE_REAL_DEBRID_REFERRAL_ID }}
RENDERER_VITE_TORBOX_REFERRAL_CODE: ${{ vars.RENDERER_VITE_TORBOX_REFERRAL_CODE }} - name: Build macOS
if: matrix.os == 'macos-latest'
run: yarn build:mac
env:
MAIN_VITE_API_URL: ${{ vars.MAIN_VITE_STAGING_API_URL }}
MAIN_VITE_AUTH_URL: ${{ vars.MAIN_VITE_STAGING_AUTH_URL }}
MAIN_VITE_CHECKOUT_URL: ${{ vars.MAIN_VITE_STAGING_CHECKOUT_URL }}
RENDERER_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.EXTERNAL_RESOURCES_URL }}
MAIN_VITE_EXTERNAL_RESOURCES_URL: ${{ vars.EXTERNAL_RESOURCES_URL }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }}
- name: Build Windows - name: Build Windows
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
@@ -68,8 +78,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }} RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }}
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID: ${{ vars.RENDERER_VITE_REAL_DEBRID_REFERRAL_ID }}
RENDERER_VITE_TORBOX_REFERRAL_CODE: ${{ vars.RENDERER_VITE_TORBOX_REFERRAL_CODE }}
- name: Upload build - name: Upload build
env: env:
@@ -81,6 +89,7 @@ jobs:
BUILDS_URL: ${{ secrets.BUILDS_URL }} BUILDS_URL: ${{ secrets.BUILDS_URL }}
BUILD_WEBHOOK_URL: ${{ secrets.BUILD_WEBHOOK_URL }} BUILD_WEBHOOK_URL: ${{ secrets.BUILD_WEBHOOK_URL }}
GITHUB_ACTOR: ${{ github.actor }} GITHUB_ACTOR: ${{ github.actor }}
run: node scripts/upload-build.cjs run: node scripts/upload-build.cjs
- name: Create artifact - name: Create artifact

View File

@@ -20,7 +20,7 @@ jobs:
node-version: 20.18.0 node-version: 20.18.0
- name: Install dependencies - name: Install dependencies
run: yarn --frozen-lockfile run: yarn
- name: Validate current commit (last commit) with commitlint - name: Validate current commit (last commit) with commitlint
run: npx commitlint --last --verbose run: npx commitlint --last --verbose

View File

@@ -12,7 +12,7 @@ jobs:
build: build:
strategy: strategy:
matrix: matrix:
os: [windows-latest, ubuntu-latest] os: [windows-latest, ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -25,14 +25,14 @@ jobs:
with: with:
node-version: 20.18.0 node-version: 20.18.0
- name: Install dependencies
run: yarn --frozen-lockfile
- name: Install Python - name: Install Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: 3.9 python-version: 3.9
- name: Install dependencies
run: yarn
- name: Install dependencies - name: Install dependencies
run: pip install -r requirements.txt run: pip install -r requirements.txt
@@ -54,8 +54,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }} RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }}
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID: ${{ vars.RENDERER_VITE_REAL_DEBRID_REFERRAL_ID }}
RENDERER_VITE_TORBOX_REFERRAL_CODE: ${{ vars.RENDERER_VITE_TORBOX_REFERRAL_CODE }}
- name: Build Windows - name: Build Windows
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
@@ -69,8 +67,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }} RENDERER_VITE_SENTRY_DSN: ${{ vars.SENTRY_DSN }}
RENDERER_VITE_REAL_DEBRID_REFERRAL_ID: ${{ vars.RENDERER_VITE_REAL_DEBRID_REFERRAL_ID }}
RENDERER_VITE_TORBOX_REFERRAL_CODE: ${{ vars.RENDERER_VITE_TORBOX_REFERRAL_CODE }}
- name: Create artifact - name: Create artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4

View File

@@ -1,13 +0,0 @@
name: Trigger Landing Page Build
on:
release:
types: [published]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Trigger Landing Page build
run: curl --location --request POST '${{ secrets.LP_TRIGGER_DEPLOY_URL }}'

3
.gitignore vendored
View File

@@ -9,11 +9,10 @@ out
.vite .vite
ludusavi/ ludusavi/
hydra-python-rpc/ hydra-python-rpc/
aria2/
.python-version .python-version
# Sentry Config File # Sentry Config File
.env.sentry-build-plugin .env.sentry-build-plugin
*storybook.log *storybook.log
aria2/

View File

@@ -25,8 +25,7 @@
[![cs](https://img.shields.io/badge/lang-cs-purple)](./docs/README.cs.md) [![cs](https://img.shields.io/badge/lang-cs-purple)](./docs/README.cs.md)
[![da](https://img.shields.io/badge/lang-da-red)](./docs/README.da.md) [![da](https://img.shields.io/badge/lang-da-red)](./docs/README.da.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](./docs/README.nb.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](./docs/README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](./docs/README.et.md) [![ee](https://img.shields.io/badge/lang-et-blue.svg)](./docs/README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](./docs/README.tr.md)
![Hydra Catalogue](./docs/screenshot.png) ![Hydra Catalogue](./docs/screenshot.png)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -26,7 +26,6 @@
[![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) [![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Hydra Catalogue](screenshot.png) ![Hydra Catalogue](screenshot.png)

View File

@@ -26,7 +26,6 @@
[![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) [![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Hydra Katalog](screenshot.png) ![Hydra Katalog](screenshot.png)

View File

@@ -25,7 +25,6 @@
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
[![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) [![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Hydra Catalogue](screenshot.png) ![Hydra Catalogue](screenshot.png)

View File

@@ -26,7 +26,6 @@
[![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) [![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Hydra Katalog](screenshot.png) ![Hydra Katalog](screenshot.png)

View File

@@ -26,7 +26,6 @@
[![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) [![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Hydra Catalogue](screenshot.png) ![Hydra Catalogue](screenshot.png)

View File

@@ -23,8 +23,7 @@
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
[![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) [![ee](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Hydra Kataloog](screenshot.png) ![Hydra Kataloog](screenshot.png)

View File

@@ -26,7 +26,6 @@
[![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) [![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Catalogue Hydra](screenshot.png) ![Catalogue Hydra](screenshot.png)

View File

@@ -26,7 +26,6 @@
[![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) [![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Hydra Catalogue](./screenshot.png) ![Hydra Catalogue](./screenshot.png)

View File

@@ -25,7 +25,6 @@
[![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md) [![cs](https://img.shields.io/badge/lang-cs-purple)](README.cs.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) [![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Hydra Catalogue](screenshot.png) ![Hydra Catalogue](screenshot.png)

View File

@@ -26,7 +26,6 @@
[![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) [![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Hydra Catalogue](./screenshot.png) ![Hydra Catalogue](./screenshot.png)

View File

@@ -26,7 +26,6 @@
[![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) [![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Hydra Catalogue](./screenshot.png) ![Hydra Catalogue](./screenshot.png)

View File

@@ -26,7 +26,6 @@
[![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) [![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Hydra Catalogue](./screenshot.png) ![Hydra Catalogue](./screenshot.png)

View File

@@ -1,194 +0,0 @@
<br>
<div align="center">
[<img src="../resources/icon.png" width="144"/>](https://help.hydralauncher.gg)
<h1 align="center">Hydra Launcher</h1>
<p align="center">
<strong>Hydra, kendi gömülü BitTorrent istemcisine sahip bir oyun başlatıcısıdır.</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)
[![da](https://img.shields.io/badge/lang-da-red)](README.da.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Hydra Catalogue](screenshot.png)
</div>
## <a name="içindekiler"></a> İçindekiler
- [İçindekiler](#içindekiler)
- [Hakkında](#hakkında)
- [Özellikler](#özellikler)
- [Kurulum](#kurulum)
- [Katkıda bulunma](#katkıda-bulunma)
- [Telegram grubumuza katılın](#telegram-katıl)
- [Repoyu forklayın ve klonlayın](#repo-fork-klon)
- [Katkıda bulunabileceğin yollar](#katkı-yolları)
- [Proje yapısı](#proje-yapısı)
- [Kaynak kodundan derleme](#kaynak-kodundan-derleme)
- [Node.js'i yükleme](#nodejs-yükle)
- [Yarn'ı yükleme](#yarn-yükle)
- [Node bağımlılıklarını yükleme](#node-bağımlılık-yükle)
- [OpenSSL 1.1'i yükleme](#openssl-1-1-yükle)
- [Python 3.9'u yükleme](#python-3-9-yükle)
- [Python bağımlılıklarını yükleme](#python-bağımlılık-yükle)
- [Ortam değişkenleri](#ortam-değişkenleri)
- [Çalıştırma](#çalıştırma)
- [Derleme](#derleme)
- [BitTorrent istemcisini derleme](#bittorrent-istemci-derle)
- [Electron uygulamasını derleme](#electron-uygulama-derle)
- [Katkıda bulunanlar](#katkıda-bulunanlar)
- [Lisans](#lisans)
## <a name="hakkında"></a> Hakkında
**Hydra**, kendi gömülü **BitTorrent istemci**sine sahip bir **oyun başlatıcısı**dır.
<br>
Başlatıcı, torrent sistemini libtorrent kullanarak yöneten Python ve TypeScript (Electron) ile yazılmıştır.
## <a name="özellikler"></a> Özellikler
- Kendi gömülü BitTorrent istemcisi
- Oyun sayfasında How Long To Beat (HLTB) entegrasyonu
- İndirme yolu özelleştirmesi
- Windows ve Linux desteği
- Sürekli güncelleme
- Ve daha fazlası...
## <a name="kurulum"></a> Kurulum
Aşağıdaki adımları izleyerek Hydra'yı kurun:
1. Hydra'nın en son sürümünü [Releases](https://github.com/hydralauncher/hydra/releases/latest) sayfasından indirin.
- Hydra'yı Windows'a kurmak istiyorsanız sadece .exe dosyasını indirin.
- Hydra'yı Linux'a kurmak istiyorsanız .deb, .rpm veya .zip dosyasını indirin (kullandığınız Linux dağıtımına bağlı olarak).
2. İndirilen dosyayı çalıştırın.
3. Hydra'nın keyfini çıkarın!
## <a name="katkıda-bulunma"></a> Katkıda Bulunma
### <a name="telegram-katıl"></a> Telegram grubumuza katılın
Tartışmalarımızı [Telegram](https://t.me/hydralauncher) kanalımız üzerinde yürütüyoruz.
### <a name="repo-fork-klon"></a> Repoyu forklayın ve klonlayın
1. Depoyu fork'layın [(şimdi forklamak için tıklayın)](https://github.com/hydralauncher/hydra/fork)
2. Forkladığınız kodu klonlayın `git clone https://github.com/kullanıcı_adınız/hydra`
3. Yeni bir branch oluşturun
4. Commitlerinizi gönderin (push)
5. Yeni bir Pull Request gönderin
### <a name="katkı-yolları"></a> Katkıda bulunabileceğin yollar
- Çeviri: Hydra'nın mümkün olduğunca fazla kişiye ulaşmasını istiyoruz. Yeni dillere çeviri yapmak ya da mevcut dillere güncelleme ve iyileştirme yapmak için yardımcı olmaktan çekinmeyin.
- Kod: Hydra, Typescript, Electron ve biraz Python ile inşa edilmiştir. Katkıda bulunmak isterseniz, [Telegram](https://t.me/hydralauncher) kanalımıza katılın!
### <a name="proje-yapısı"></a> Proje yapısı
- torrent-client: Torrent indirmelerini yönetmek için libtorrent adlı bir Python kütüphanesini kullanıyoruz.
- src/renderer: Uygulamanın kullanıcı arayüzü burada bulunur.
- src/main: Uygulamanın tüm işleyişi ve iş mantığı bu bölümde bulunur.
## <a name="kaynak-kodundan-derleme"></a> Kaynak kodundan derleme
### <a name="nodejs-yükle"></a> Node.js'i yükleme
Makinenizde Node.js'in yüklü olduğundan emin olun. Yüklü değilse, [nodejs.org](https://nodejs.org/) adresinden indirip kurun.
### <a name="yarn-yükle"></a> Yarn'ı yükleme
Yarn, Node.js için bir paket yöneticisidir. Eğer Yarn'ı henüz kurmadıysanız, [yarnpkg.com](https://classic.yarnpkg.com/lang/en/docs/install/) adresindeki talimatları izleyerek kurabilirsiniz.
### <a name="node-bağımlılık-yükle"></a> Node bağımlılıklarını yükleme
Proje dizinine gidin ve Yarn kullanarak Node bağımlılıklarını yükleyin:
```bash
cd hydra
yarn
```
### <a name="openssl-1-1-yükle"></a> OpenSSL 1.1'i yükleme
Windows ortamlarında libtorrent tarafından gerekli olan [OpenSSL 1.1](https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe)'i indirip yükleyin.
### <a name="python-3-9-yükle"></a> Python 3.9'u yükleme
Makinenizde Python 3.9'un yüklü olduğundan emin olun. Bunu [python.org](https://www.python.org/downloads/release/python-3913/) adresinden indirip kurarak yapabilirsiniz.
### <a name="python-bağımlılık-yükle"></a> Python bağımlılıklarını yükleme
Gerekli Python bağımlılıklarını pip kullanarak yükleyin:
```bash
pip install -r requirements.txt
```
## <a name="ortam-değişkenleri"></a> Ortam değişkenleri
Oyun simgelerini yüklemek için bir SteamGridDB API Anahtarına ihtiyacınız olacak.
Bu anahtara sahip olduktan sonra, `.env.example` dosyasını kopyalayabilir veya adını `.env` olarak değiştirebilir ve `STEAMGRIDDB_API_KEY` değerini buraya ekleyebilirsiniz.
## <a name="çalıştırma"></a> Çalıştırma
Tüm ayarları tamamladıktan sonra, hem Electron sürecini hem de bittorrent istemcisini başlatmak için aşağıdaki komutu çalıştırabilirsiniz:
```bash
yarn dev
```
## <a name="derleme"></a> Derleme
### <a name="bittorrent-istemci-derle"></a> BitTorrent istemcisini derleme
Bittorrent istemcisini aşağıdaki komutla derleyin:
```bash
python torrent-client/setup.py build
```
### <a name="electron-uygulama-derle"></a> Electron uygulamasını derleme
Electron uygulamasını aşağıdaki komutlarla derleyebilirsiniz:
Windows'ta:
```bash
yarn build:win
```
Linux'ta:
```bash
yarn build:linux
```
## <a name="katkıda-bulunanlar"></a> Katkıda bulunanlar
<a href="https://github.com/hydralauncher/hydra/graphs/contributors">
<img src="https://contrib.rocks/image?repo=hydralauncher/hydra" />
</a>
## <a name="lisans"></a> Lisans
Hydra, [MIT Lisansı](https://github.com/hydralauncher/hydra/blob/main/LICENSE) altında lisanlanmıştır.

View File

@@ -26,7 +26,6 @@
[![da](https://img.shields.io/badge/lang-da-red)](README.da.md) [![da](https://img.shields.io/badge/lang-da-red)](README.da.md)
[![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md) [![nb](https://img.shields.io/badge/lang-nb-blue)](README.nb.md)
[![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md) [![et](https://img.shields.io/badge/lang-et-blue.svg)](README.et.md)
[![tr](https://img.shields.io/badge/lang-tr-red.svg)](README.tr.md)
![Hydra Catalogue](screenshot.png) ![Hydra Catalogue](screenshot.png)

View File

@@ -20,9 +20,6 @@ asarUnpack:
- resources/** - resources/**
win: win:
executableName: Hydra executableName: Hydra
extraResources:
- from: binaries/7z.exe
- from: binaries/7z.dll
target: target:
- nsis - nsis
- portable - portable
@@ -38,8 +35,6 @@ portable:
artifactName: ${name}-${version}-portable.${ext} artifactName: ${name}-${version}-portable.${ext}
mac: mac:
entitlementsInherit: build/entitlements.mac.plist entitlementsInherit: build/entitlements.mac.plist
extraResources:
- from: binaries/7zz
extendInfo: extendInfo:
- NSCameraUsageDescription: Application requests access to the device's camera. - NSCameraUsageDescription: Application requests access to the device's camera.
- NSMicrophoneUsageDescription: Application requests access to the device's microphone. - NSMicrophoneUsageDescription: Application requests access to the device's microphone.
@@ -49,8 +44,6 @@ mac:
dmg: dmg:
artifactName: ${name}-${version}.${ext} artifactName: ${name}-${version}.${ext}
linux: linux:
extraResources:
- from: binaries/7zzs
target: target:
- AppImage - AppImage
- snap - snap

View File

@@ -16,6 +16,9 @@ export default defineConfig(({ mode }) => {
main: { main: {
build: { build: {
sourcemap: true, sourcemap: true,
rollupOptions: {
external: ["better-sqlite3"],
},
}, },
resolve: { resolve: {
alias: { alias: {

View File

@@ -1,6 +1,6 @@
{ {
"name": "hydralauncher", "name": "hydralauncher",
"version": "3.4.3", "version": "3.2.2",
"description": "Hydra", "description": "Hydra",
"main": "./out/main/index.js", "main": "./out/main/index.js",
"author": "Los Broxas", "author": "Los Broxas",
@@ -28,7 +28,8 @@
"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"
}, },
"dependencies": { "dependencies": {
"@electron-toolkit/preload": "^3.0.0", "@electron-toolkit/preload": "^3.0.0",
@@ -43,7 +44,7 @@
"@sentry/vite-plugin": "^2.22.7", "@sentry/vite-plugin": "^2.22.7",
"auto-launch": "^5.0.6", "auto-launch": "^5.0.6",
"axios": "^1.7.9", "axios": "^1.7.9",
"axios-cookiejar-support": "^5.0.5", "better-sqlite3": "^11.7.0",
"classic-level": "^2.0.0", "classic-level": "^2.0.0",
"classnames": "^2.5.1", "classnames": "^2.5.1",
"color": "^4.2.3", "color": "^4.2.3",
@@ -53,13 +54,14 @@
"dexie": "^4.0.10", "dexie": "^4.0.10",
"diskusage": "^1.2.0", "diskusage": "^1.2.0",
"electron-log": "^5.2.4", "electron-log": "^5.2.4",
"electron-updater": "^6.6.2", "electron-updater": "^6.3.9",
"file-type": "^19.6.0", "file-type": "^19.6.0",
"i18next": "^23.11.2", "i18next": "^23.11.2",
"i18next-browser-languagedetector": "^7.2.1", "i18next-browser-languagedetector": "^7.2.1",
"jsdom": "^24.0.0", "jsdom": "^24.0.0",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"kill-port": "^2.0.1", "kill-port": "^2.0.1",
"knex": "^3.1.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"parse-torrent": "^11.0.17", "parse-torrent": "^11.0.17",
"piscina": "^4.7.0", "piscina": "^4.7.0",
@@ -69,11 +71,9 @@
"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",
"react-tooltip": "^5.28.0",
"sound-play": "^1.1.0", "sound-play": "^1.1.0",
"sudo-prompt": "^9.2.1", "sudo-prompt": "^9.2.1",
"tar": "^7.4.3", "tar": "^7.4.3",
"tough-cookie": "^5.1.1",
"user-agents": "^1.1.387", "user-agents": "^1.1.387",
"yaml": "^2.6.1", "yaml": "^2.6.1",
"yup": "^1.5.0", "yup": "^1.5.0",
@@ -100,7 +100,7 @@
"@types/user-agents": "^1.0.4", "@types/user-agents": "^1.0.4",
"@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react": "^4.2.1",
"electron": "^31.7.7", "electron": "^31.7.7",
"electron-builder": "^26.0.12", "electron-builder": "^25.1.8",
"electron-vite": "^2.3.0", "electron-vite": "^2.3.0",
"eslint": "^8.56.0", "eslint": "^8.56.0",
"eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-jsx-a11y": "^6.10.2",

View File

@@ -35,7 +35,7 @@ if start_download_payload:
http_downloader = HttpDownloader() http_downloader = HttpDownloader()
downloads[initial_download['game_id']] = http_downloader downloads[initial_download['game_id']] = http_downloader
try: try:
http_downloader.start_download(initial_download['url'], initial_download['save_path'], initial_download.get('header'), initial_download.get('out')) http_downloader.start_download(initial_download['url'], initial_download['save_path'], initial_download.get('header'), initial_download.get("out"))
except Exception as e: except Exception as e:
print("Error starting http download", e) print("Error starting http download", e)
@@ -182,3 +182,4 @@ def action():
if __name__ == "__main__": if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(http_port)) app.run(host="0.0.0.0", port=int(http_port))

View File

@@ -6,3 +6,4 @@ psutil
Pillow Pillow
flask flask
aria2p aria2p

View File

@@ -20,7 +20,7 @@ const s3 = new S3Client({
const dist = path.resolve(__dirname, "..", "dist"); const dist = path.resolve(__dirname, "..", "dist");
const extensionsToUpload = [".deb", ".exe", ".pacman"]; const extensionsToUpload = [".deb", ".exe", ".pacman", ".dmg"];
fs.readdir(dist, async (err, files) => { fs.readdir(dist, async (err, files) => {
if (err) throw err; if (err) throw err;

File diff suppressed because one or more lines are too long

View File

@@ -188,8 +188,8 @@
"reset_achievements_error": "فشل في إعادة تعيين الإنجازات", "reset_achievements_error": "فشل في إعادة تعيين الإنجازات",
"download_error_gofile_quota_exceeded": "لقد تجاوزت الحصة الشهرية لـ Gofile. يرجى الانتظار حتى إعادة تعيين الحصة.", "download_error_gofile_quota_exceeded": "لقد تجاوزت الحصة الشهرية لـ Gofile. يرجى الانتظار حتى إعادة تعيين الحصة.",
"download_error_real_debrid_account_not_authorized": "حساب Real-Debrid الخاص بك غير مصرح له بإجراء تنزيلات جديدة. يرجى مراجعة إعدادات الحساب والمحاولة مرة أخرى.", "download_error_real_debrid_account_not_authorized": "حساب Real-Debrid الخاص بك غير مصرح له بإجراء تنزيلات جديدة. يرجى مراجعة إعدادات الحساب والمحاولة مرة أخرى.",
"download_error_not_cached_on_real_debrid": "هذا التنزيل غير متوفر على Real-Debrid وجلب حالة التنزيل من Real-Debrid غير متاح حاليًا.", "download_error_not_cached_in_real_debrid": "هذا التنزيل غير متوفر على Real-Debrid وجلب حالة التنزيل من Real-Debrid غير متاح حاليًا.",
"download_error_not_cached_on_torbox": "هذا التنزيل غير متوفر على TorBox وجلب حالة التنزيل من TorBox غير متاح حاليًا.", "download_error_not_cached_in_torbox": "هذا التنزيل غير متوفر على Torbox وجلب حالة التنزيل من Torbox غير متاح حاليًا.",
"game_removed_from_favorites": "تمت إزالة اللعبة من المفضلة", "game_removed_from_favorites": "تمت إزالة اللعبة من المفضلة",
"game_added_to_favorites": "تمت إضافة اللعبة إلى المفضلة" "game_added_to_favorites": "تمت إضافة اللعبة إلى المفضلة"
}, },
@@ -255,12 +255,6 @@
"download_sources_description": "سيقوم Hydra بجلب روابط التنزيل من هذه المصادر. يجب أن يكون عنوان URL للمصدر رابطًا مباشرًا لملف .json يحتوي على روابط التنزيل.", "download_sources_description": "سيقوم Hydra بجلب روابط التنزيل من هذه المصادر. يجب أن يكون عنوان URL للمصدر رابطًا مباشرًا لملف .json يحتوي على روابط التنزيل.",
"validate_download_source": "تحقق", "validate_download_source": "تحقق",
"remove_download_source": "إزالة", "remove_download_source": "إزالة",
"removed_download_sources": "تمت إزالة مصادر التنزيل",
"cancel_button_confirmation_delete_all_sources": "لا",
"confirm_button_confirmation_delete_all_sources": "نعم، احذف كل شيء",
"description_confirmation_delete_all_sources": "سوف تقوم بحذف جميع مصادر التنزيل",
"title_confirmation_delete_all_sources": "احذف جميع مصادر التنزيل",
"button_delete_all_sources": "قم بإزالة جميع مصادر التنزيل",
"add_download_source": "إضافة مصدر", "add_download_source": "إضافة مصدر",
"download_count_zero": "لا توجد خيارات تنزيل", "download_count_zero": "لا توجد خيارات تنزيل",
"download_count_one": "{{countFormatted}} خيار تنزيل", "download_count_one": "{{countFormatted}} خيار تنزيل",
@@ -330,7 +324,7 @@
"delete_theme_description": "سيؤدي هذا إلى حذف السمة {{theme}}", "delete_theme_description": "سيؤدي هذا إلى حذف السمة {{theme}}",
"cancel": "إلغاء", "cancel": "إلغاء",
"appearance": "المظهر", "appearance": "المظهر",
"enable_torbox": "تفعيل TorBox", "enable_torbox": "تفعيل Torbox",
"torbox_description": "TorBox هي خدمة seedbox متميزة تنافس أفضل الخوادم في السوق.", "torbox_description": "TorBox هي خدمة seedbox متميزة تنافس أفضل الخوادم في السوق.",
"torbox_account_linked": "تم ربط حساب TorBox", "torbox_account_linked": "تم ربط حساب TorBox",
"real_debrid_account_linked": "تم ربط حساب Real-Debrid", "real_debrid_account_linked": "تم ربط حساب Real-Debrid",

View File

@@ -107,12 +107,6 @@
"notifications": "Апавяшчэнні", "notifications": "Апавяшчэнні",
"enable_download_notifications": "Па сканчэнні сцягванні", "enable_download_notifications": "Па сканчэнні сцягванні",
"enable_repack_list_notifications": "Пры даданні новага рэпака", "enable_repack_list_notifications": "Пры даданні новага рэпака",
"cancel_button_confirmation_delete_all_sources": "Няма",
"confirm_button_confirmation_delete_all_sources": "Так,выдаліць усё",
"description_confirmation_delete_all_sources": "Вы выдаліце ​​ўсе крыніцы сцягвання",
"title_confirmation_delete_all_sources": "Выдаліць усе крыніцы сцягвання",
"removed_download_sources": "Крыніцы сцягвання выдалены",
"button_delete_all_sources": "Премахнете всички източници на изтегляне",
"behavior": "Паводзіны", "behavior": "Паводзіны",
"quit_app_instead_hiding": "Закрываць праграму замест таго, каб хаваць яе ў трэй", "quit_app_instead_hiding": "Закрываць праграму замест таго, каб хаваць яе ў трэй",
"launch_with_system": "Запускаць праграму пры запуску сыстэмы" "launch_with_system": "Запускаць праграму пры запуску сыстэмы"

View File

@@ -253,12 +253,6 @@
"download_source_errored": "Сгрешен", "download_source_errored": "Сгрешен",
"sync_download_sources": "Синхронизирай източниците", "sync_download_sources": "Синхронизирай източниците",
"removed_download_source": "Източника за сваляне е премахнат", "removed_download_source": "Източника за сваляне е премахнат",
"cancel_button_confirmation_delete_all_sources": "не",
"confirm_button_confirmation_delete_all_sources": "Да, удалить все",
"description_confirmation_delete_all_sources": "Вы удалите все источники загрузки",
"title_confirmation_delete_all_sources": "Удалить все источники загрузки",
"removed_download_sources": "Шрифты удалены",
"button_delete_all_sources": "Удалить все источники загрузки",
"added_download_source": "Добавен източник за сваляне", "added_download_source": "Добавен източник за сваляне",
"download_sources_synced": "Всички източници за сваляне са синхронизирани", "download_sources_synced": "Всички източници за сваляне са синхронизирани",
"insert_valid_json_url": "Добавете ваиден JSON линк", "insert_valid_json_url": "Добавете ваиден JSON линк",

View File

@@ -175,12 +175,6 @@
"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.", "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", "validate_download_source": "Valida",
"remove_download_source": "Elimina", "remove_download_source": "Elimina",
"cancel_button_confirmation_delete_all_sources": "No",
"confirm_button_confirmation_delete_all_sources": "Sí, esborra-ho tot",
"description_confirmation_delete_all_sources": "Eliminareu totes les fonts de descàrrega",
"title_confirmation_delete_all_sources": "Suprimeix totes les fonts de baixada",
"removed_download_sources": "S'han eliminat les fonts de descàrrega",
"button_delete_all_sources": "Elimina totes les fonts de baixada",
"add_download_source": "Afegeix font", "add_download_source": "Afegeix font",
"download_count_zero": "No hi ha baixades a la llista", "download_count_zero": "No hi ha baixades a la llista",
"download_count_one": "{{countFormatted}} a la llista de baixades", "download_count_one": "{{countFormatted}} a la llista de baixades",

View File

@@ -44,21 +44,11 @@
"downloading_metadata": "Stahuji metadata: {{title}}…", "downloading_metadata": "Stahuji metadata: {{title}}…",
"downloading": "Stahuji {{title}}… ({{percentage}} staženo) - Odhadovaný čas {{eta}} - {{speed}}", "downloading": "Stahuji {{title}}… ({{percentage}} staženo) - Odhadovaný čas {{eta}} - {{speed}}",
"calculating_eta": "Stahuji {{title}}… ({{percentage}} staženo) - Počítám zbývající čas…", "calculating_eta": "Stahuji {{title}}… ({{percentage}} staženo) - Počítám zbývající čas…",
"checking_files": "Kontroluji soubory: {{title}}… ({{percentage}} ověřeno)", "checking_files": "Kontroluji soubory: {{title}}… ({{percentage}} ověřeno)"
"installing_common_redist": "{{log}}…",
"installation_complete": "Instalace dokončena",
"installation_complete_message": "Běžné redistribuovatelné komponenty byly úspěšně nainstalovány"
}, },
"catalogue": { "catalogue": {
"search": "Filtr…", "next_page": "Další strana",
"developers": "Vývojáři", "previous_page": "Předchozí strana"
"genres": "Žánry",
"tags": "Tagy",
"publishers": "Vydavatelé",
"download_sources": "Zdroje stahování",
"result_count": "Výsledky: {{resultCount}}",
"filter_count": "Dostupné: {{filterCount}}",
"clear_filters": "Vyčistit vybrané filtry: {{filterCount}}"
}, },
"game_details": { "game_details": {
"open_download_options": "Otevřít možnosti stahování", "open_download_options": "Otevřít možnosti stahování",
@@ -117,7 +107,6 @@
"open_download_location": "Zobrazit stažené soubory", "open_download_location": "Zobrazit stažené soubory",
"create_shortcut": "Vytvořit zástupce na ploše", "create_shortcut": "Vytvořit zástupce na ploše",
"remove_files": "Odebrat soubory", "remove_files": "Odebrat soubory",
"clear": "Vyčistit",
"remove_from_library_title": "Jste si jisti?", "remove_from_library_title": "Jste si jisti?",
"remove_from_library_description": "Tohle odstraní {{game}} z vaší knihovny", "remove_from_library_description": "Tohle odstraní {{game}} z vaší knihovny",
"options": "Možnosti", "options": "Možnosti",
@@ -171,9 +160,6 @@
"loading_save_preview": "Hledání uložených her...", "loading_save_preview": "Hledání uložených her...",
"wine_prefix": "Wine Prefix", "wine_prefix": "Wine Prefix",
"wine_prefix_description": "Wine Prefix použit pro spuštění této hry", "wine_prefix_description": "Wine Prefix použit pro spuštění této hry",
"launch_options": "Možnosti spuštění",
"launch_options_description": "Pokročilí uživatelé mohou zadat speciální parametry spuštění (experimentální funkce)",
"launch_options_placeholder": "Žádné parametery nebyly specifikovány",
"no_download_option_info": "Žádné informace nejsou dostupny", "no_download_option_info": "Žádné informace nejsou dostupny",
"backup_deletion_failed": "Nepovedlo se odstranit zálohu", "backup_deletion_failed": "Nepovedlo se odstranit zálohu",
"max_number_of_artifacts_reached": "Dosáhli jste maximálního počtu záloh pro tuto hru", "max_number_of_artifacts_reached": "Dosáhli jste maximálního počtu záloh pro tuto hru",
@@ -181,23 +167,7 @@
"manage_files_description": "Spravovat, které soubory budou zálohovány a obnoveny", "manage_files_description": "Spravovat, které soubory budou zálohovány a obnoveny",
"select_folder": "Vybrat složku", "select_folder": "Vybrat složku",
"backup_from": "Zálohy z {{date}}", "backup_from": "Zálohy z {{date}}",
"custom_backup_location_set": "Vlastní umístění záloh nastaveno", "custom_backup_location_set": "Vlastní umístění záloh nastaveno"
"automatic_backup_from": "Automatická záloha z {{date}}",
"enable_automatic_cloud_sync": "Povolit automatické zálohy v cloudu",
"no_directory_selected": "Žádná složka není zvolena",
"no_write_permission": "Nemohu stahovat do této složky. Klikni sem pro více informací.",
"reset_achievements": "Resetovat achievementy",
"reset_achievements_description": "Toto zresetuje všechny achievementy pro hru {{game}}",
"reset_achievements_title": "Jste si jisti?",
"reset_achievements_success": "Achievementy úspěšně resetovány",
"reset_achievements_error": "Nepodařilo se resetovat achievementy",
"download_error_gofile_quota_exceeded": "Překročili jste vaši měsíční GoFile kvótu. Prosím vyčkejte na resetování kvóty.",
"download_error_real_debrid_account_not_authorized": "Váš Real-Debrid účet není autorizován pro vytváření nových stahování. Prosím zkontrolujte nastavení vašeho účtu a zkuste to znovu.",
"download_error_not_cached_on_real_debrid": "Toto stahování není dostupné na Real-Debrid a získávání informací o stahování z Real-Debrid není zatím dostupné.",
"download_error_not_cached_on_torbox": "Toto stahování není dostupné na TorBox a získávání informací o stahování z TorBox není zatím dostupné.",
"game_removed_from_favorites": "Hra odebrána z oblíbených",
"game_added_to_favorites": "Hra přidána do oblíbených",
"automatically_extract_downloaded_files": "Automaticky rozbalit stažené soubory"
}, },
"activation": { "activation": {
"title": "Aktivovat hydru", "title": "Aktivovat hydru",
@@ -230,13 +200,7 @@
"queued": "V řadě", "queued": "V řadě",
"no_downloads_title": "Prázdno..", "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.", "no_downloads_description": "Ještě jsi zatím nic nestáhl přes Hydru, ale furt není pozdě začít.",
"checking_files": "Kontroluji soubory…", "checking_files": "Kontroluji soubory…"
"seeding": "Seedování",
"stop_seeding": "Zastavování seedování",
"resume_seeding": "Obnovit seedování",
"options": "Spravovat",
"extract": "Rozbalit soubory",
"extracting": "Rozbalování souborů…"
}, },
"settings": { "settings": {
"downloads_path": "Umístění stahování", "downloads_path": "Umístění stahování",
@@ -273,12 +237,6 @@
"download_source_errored": "Chyba", "download_source_errored": "Chyba",
"sync_download_sources": "Synchronizovat zdroje", "sync_download_sources": "Synchronizovat zdroje",
"removed_download_source": "Zdroj odebrán", "removed_download_source": "Zdroj odebrán",
"cancel_button_confirmation_delete_all_sources": "Žádný",
"confirm_button_confirmation_delete_all_sources": "Ano, smazat vše",
"description_confirmation_delete_all_sources": "Smažete všechny zdroje stahování",
"title_confirmation_delete_all_sources": "Odstraňte všechny zdroje stahování",
"removed_download_sources": "Zdroje stahování byly odstraněny",
"button_delete_all_sources": "Odstraňte všechny zdroje stahování",
"added_download_source": "Zdroj přidán", "added_download_source": "Zdroj přidán",
"download_sources_synced": "Všechny zdroje jsou synchronizovány", "download_sources_synced": "Všechny zdroje jsou synchronizovány",
"insert_valid_json_url": "Zadej platnou JSON adresu", "insert_valid_json_url": "Zadej platnou JSON adresu",
@@ -297,65 +255,9 @@
"must_be_valid_url": "Zdroj musí být platký odkaz URL", "must_be_valid_url": "Zdroj musí být platký odkaz URL",
"blocked_users": "Zablokovaní uživatelé", "blocked_users": "Zablokovaní uživatelé",
"user_unblocked": "Uživatel byl odblokován", "user_unblocked": "Uživatel byl odblokován",
"enable_achievement_notifications": "Když je odemčen achievement", "enable_achievement_notifications": "Když je odemknut achievement",
"launch_minimized": "Spustit v minimalizovaném režimu", "launch_minimized": "Spustit v minimalizovaném režimu",
"disable_nsfw_alert": "Deaktivovat upozornění na nevhodný obsah", "disable_nsfw_alert": "Deaktivovat upozornění na nevhodný obsah"
"seed_after_download_complete": "Seedovat až skončí stahování",
"show_hidden_achievement_description": "Zobrazit popisy skrytých achievementů dříve, než jsou odemčeny",
"account": "Účet",
"no_users_blocked": "Nemáte žádného uživatele zablokovaného",
"subscription_active_until": "Vaše Hydra cloud předplatné je platné do {{date}}",
"manage_subscription": "Spravovat předplatné",
"update_email": "Změnit email",
"update_password": "Změnit heslo",
"current_email": "Současný email:",
"no_email_account": "Zatím nemáte nastavený email",
"account_data_updated_successfully": "Data vašeho účtu byly úspěšně upraveny",
"renew_subscription": "Obnovit předplatné Hydra Cloud",
"subscription_expired_at": "Vaše předplatné vypršelo {{date}}",
"no_subscription": "Užijte si Hydru v nejlepší možné podobě",
"become_subscriber": "Připojit se k předplatnému Hydra Cloud",
"subscription_renew_cancelled": "Automatické obnovování je zrušenu",
"subscription_renews_on": "Vaše předplatné se obnoví {{date}}",
"bill_sent_until": "Vaše příští faktura bude odeslána nejpozději do tohoto dne",
"no_themes": "Vypadá to že ještě nemáte žádné vzhledy, ale nebojte, klikněte sem pro vytvoření vašeho prvního mistrovského díla!",
"editor_tab_code": "Kód",
"editor_tab_info": "Info",
"editor_tab_save": "Uložit",
"web_store": "Webový obchod",
"clear_themes": "Vyčistit",
"create_theme": "Vytvořit",
"create_theme_modal_title": "Vytvořit vlastní vzhled",
"create_theme_modal_description": "Vytvořte si vlastní styl, abyste si mohli ozdobit Hydru",
"theme_name": "Název",
"insert_theme_name": "Vložte název vzhledu",
"set_theme": "Nastavit vzhled",
"unset_theme": "Zrušit vzhled",
"delete_theme": "Odstranit vzhled",
"edit_theme": "Upravit vzhled",
"delete_all_themes": "Smazat všechny vzhledy",
"delete_all_themes_description": "Toto smaže všechny vaše vzhledy",
"delete_theme_description": "Toto smaže vzhled {{theme}}",
"cancel": "Zrušit",
"appearance": "Vzhled",
"enable_torbox": "Povolit TorBox",
"torbox_description": "TorBox je prémiový seedbox server který se vyrovná i těm nejlepším seedbox serverům na trhu.",
"torbox_account_linked": "TorBox účet propojen",
"create_real_debrid_account": "Klikni sem pokud ještě nemáš Real-Debrid účet",
"create_torbox_account": "Klikni sem pokud ještě nemáš TorBox účet",
"real_debrid_account_linked": "Real-Debrid účet propojen",
"name_min_length": "Název vzhledu musí být minimálně 3 znaky dlouhý",
"import_theme": "Vložit vzhled",
"import_theme_description": "Chystáte se vložit vzhled {{theme}} z obchodu vzhledů",
"error_importing_theme": "Nastala chyba při vkládání vzhledu",
"theme_imported": "Vzhled úspěšně vložen",
"enable_friend_request_notifications": "Při obdržení žádosti o přátelství",
"enable_auto_install": "Automaticky stahovat aktualizace",
"common_redist": "Běžné redistribuovatelné komponenty",
"common_redist_description": "Běžné redistribuovatelné komponenty jsou potřeba pro spuštění určitých her. Je doporučeno je nainstalovat, aby se předešlo problémům.",
"install_common_redist": "Nainstalovat",
"installing_common_redist": "Instalování…",
"show_download_speed_in_megabytes": "Ukázat rychlost stahování v megabytech"
}, },
"notifications": { "notifications": {
"download_complete": "Stahování dokončeno", "download_complete": "Stahování dokončeno",
@@ -365,20 +267,14 @@
"repack_count_other": "{{count}} repacky přidány", "repack_count_other": "{{count}} repacky přidány",
"new_update_available": "Version {{version}} je dostupná", "new_update_available": "Version {{version}} je dostupná",
"restart_to_install_update": "Restartuj Hydru pro aktualizaci", "restart_to_install_update": "Restartuj Hydru pro aktualizaci",
"notification_achievement_unlocked_title": "Achievement pro {{game}} byl odemčen", "notification_achievement_unlocked_title": "Achievement pro {{game}} byl odemknut",
"notification_achievement_unlocked_body": "{{achievement}} a dalších {{count}} byly odemčeny", "notification_achievement_unlocked_body": "{{achievement}} a dalších {{count}} byly odemknuty"
"new_friend_request_description": "Obdrželi jste novou žádost o přátelství",
"new_friend_request_title": "Nová žádost o přátelství",
"extraction_complete": "Rozbalování dokončeno",
"game_extracted": "{{title}} úspěšně rozbaleno"
}, },
"system_tray": { "system_tray": {
"open": "Otevřít Hydru", "open": "Otevřít Hydru",
"quit": "Odejít" "quit": "Odejít"
}, },
"game_card": { "game_card": {
"available_one": "Dostupné",
"available_other": "Dostupné",
"no_downloads": "Žádné možnosti stahování nenalezeny" "no_downloads": "Žádné možnosti stahování nenalezeny"
}, },
"binary_not_found_modal": { "binary_not_found_modal": {
@@ -461,17 +357,7 @@
"your_friend_code": "Tvůj kód přítele:", "your_friend_code": "Tvůj kód přítele:",
"upload_banner": "Nahrát banner profilu", "upload_banner": "Nahrát banner profilu",
"uploading_banner": "Nahrávání banneru", "uploading_banner": "Nahrávání banneru",
"background_image_updated": "Obrázek pozadí byl změněn", "background_image_updated": "Obrázek pozadí byl změněn"
"stats": "Statistiky",
"achievements": "Achievementy",
"games": "Hry",
"top_percentile": "Top {{percentile}}%",
"ranking_updated_weekly": "Žebříčky jsou aktualizovány každý týden",
"playing": "Hraje {{game}}",
"achievements_unlocked": "Achievements odemčen",
"earned_points": "Získané body",
"show_achievements_on_profile": "Zobrazit vaše odemčené achievementy na profilu",
"show_points_on_profile": "Zobrazit vaše získané body na profilu"
}, },
"achievement": { "achievement": {
"achievement_unlocked": "Achievement odemčen", "achievement_unlocked": "Achievement odemčen",
@@ -481,12 +367,7 @@
"subscription_needed": "Je vyžadováno předplatné Hydra Cloud pro zobrazení tohoto obsahu", "subscription_needed": "Je vyžadováno předplatné Hydra Cloud pro zobrazení tohoto obsahu",
"new_achievements_unlocked": "Odemčeno {{achievementCount}} nových achievementů z {{gameCount}} her", "new_achievements_unlocked": "Odemčeno {{achievementCount}} nových achievementů z {{gameCount}} her",
"achievement_progress": "{{unlockedCount}}/{{totalCount}} achievementů", "achievement_progress": "{{unlockedCount}}/{{totalCount}} achievementů",
"achievements_unlocked_for_game": "Odemčeno {{achievementCount}} nových achievementů pro {{gameTitle}}", "achievements_unlocked_for_game": "Odemčeno {{achievementCount}} nových achievementů pro {{gameTitle}}"
"hidden_achievement_tooltip": "Toho je skrytý achievement",
"achievement_earn_points": "Získej {{points}} bodů tímto achievementem",
"earned_points": "Získané body",
"available_points": "Dostupné body:",
"how_to_earn_achievements_points": "Jak získat body achievementů?"
}, },
"hydra_cloud": { "hydra_cloud": {
"subscription_tour_title": "Předplatné Hydra Cloud", "subscription_tour_title": "Předplatné Hydra Cloud",
@@ -496,10 +377,6 @@
"animated_profile_picture": "Animované profilové obrázky", "animated_profile_picture": "Animované profilové obrázky",
"premium_support": "Prémiová podpora", "premium_support": "Prémiová podpora",
"show_and_compare_achievements": "Zobraz a porovnej achievementy s ostatními uživateli", "show_and_compare_achievements": "Zobraz a porovnej achievementy s ostatními uživateli",
"animated_profile_banner": "Animovaný banner na profilu", "animated_profile_banner": "Animovaný banner na profilu"
"hydra_cloud": "Hydra Cloud",
"hydra_cloud_feature_found": "Právě jste objevili funkci předplatného Hydra Cloud!",
"learn_more": "Zjistit více",
"debrid_description": "Stahovat až 4x rychleji s Nimbus"
} }
} }

View File

@@ -201,12 +201,6 @@
"download_source_errored": "Fejlede", "download_source_errored": "Fejlede",
"sync_download_sources": "Synkronisér kilder", "sync_download_sources": "Synkronisér kilder",
"removed_download_source": "Download kilde fjernet", "removed_download_source": "Download kilde fjernet",
"cancel_button_confirmation_delete_all_sources": "Ingen",
"confirm_button_confirmation_delete_all_sources": "Ja, slet alt",
"description_confirmation_delete_all_sources": "Du vil slette alle downloadkilder",
"title_confirmation_delete_all_sources": "Slet alle downloadkilder",
"removed_download_sources": "Download kilder fjernet",
"button_delete_all_sources": "Fjern alle downloadkilder",
"added_download_source": "Tilføjede download kilde", "added_download_source": "Tilføjede download kilde",
"download_sources_synced": "Alle download kilder er synkroniserede", "download_sources_synced": "Alle download kilder er synkroniserede",
"insert_valid_json_url": "Indsæt en gyldig JSON url", "insert_valid_json_url": "Indsæt en gyldig JSON url",

View File

@@ -185,12 +185,6 @@
"download_source_errored": "Fehlgeschlagen", "download_source_errored": "Fehlgeschlagen",
"sync_download_sources": "Quellen synchronisieren", "sync_download_sources": "Quellen synchronisieren",
"removed_download_source": "Download-Quelle entfernt", "removed_download_source": "Download-Quelle entfernt",
"cancel_button_confirmation_delete_all_sources": "Nein",
"confirm_button_confirmation_delete_all_sources": "Ja, alles löschen",
"description_confirmation_delete_all_sources": "Du löschen alle Downloadquellen",
"title_confirmation_delete_all_sources": "Löschen du alle Downloadquellen",
"removed_download_sources": "Download-Quellen entfernt",
"button_delete_all_sources": "Entfernen Sie alle Downloadquellen",
"added_download_source": "Download-Quelle hinzugefügt", "added_download_source": "Download-Quelle hinzugefügt",
"download_sources_synced": "Alle Download-Quellen sind synchronisiert", "download_sources_synced": "Alle Download-Quellen sind synchronisiert",
"insert_valid_json_url": "Füge eine gültige JSON URL ein", "insert_valid_json_url": "Füge eine gültige JSON URL ein",

View File

@@ -44,10 +44,7 @@
"downloading_metadata": "Downloading {{title}} metadata…", "downloading_metadata": "Downloading {{title}} metadata…",
"downloading": "Downloading {{title}}… ({{percentage}} complete) - Completion {{eta}} - {{speed}}", "downloading": "Downloading {{title}}… ({{percentage}} complete) - Completion {{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)", "checking_files": "Checking {{title}} files… ({{percentage}} complete)"
"installing_common_redist": "{{log}}…",
"installation_complete": "Installation complete",
"installation_complete_message": "Common redistributables installed successfully"
}, },
"catalogue": { "catalogue": {
"search": "Filter…", "search": "Filter…",
@@ -181,8 +178,6 @@
"manage_files_description": "Manage which files will be backed up and restored", "manage_files_description": "Manage which files will be backed up and restored",
"select_folder": "Select folder", "select_folder": "Select folder",
"backup_from": "Backup from {{date}}", "backup_from": "Backup from {{date}}",
"automatic_backup_from": "Automatic backup from {{date}}",
"enable_automatic_cloud_sync": "Enable automatic cloud sync",
"custom_backup_location_set": "Custom backup location set", "custom_backup_location_set": "Custom backup location set",
"no_directory_selected": "No directory selected", "no_directory_selected": "No directory selected",
"no_write_permission": "Cannot download into this directory. Click here to learn more.", "no_write_permission": "Cannot download into this directory. Click here to learn more.",
@@ -193,12 +188,10 @@
"reset_achievements_error": "Failed to reset achievements", "reset_achievements_error": "Failed to reset achievements",
"download_error_gofile_quota_exceeded": "You have exceeded your Gofile monthly quota. Please await the quota to reset.", "download_error_gofile_quota_exceeded": "You have exceeded your Gofile monthly quota. Please await the quota to reset.",
"download_error_real_debrid_account_not_authorized": "Your Real-Debrid account is not authorized to make new downloads. Please check your account settings and try again.", "download_error_real_debrid_account_not_authorized": "Your Real-Debrid account is not authorized to make new downloads. Please check your account settings and try again.",
"download_error_not_cached_on_real_debrid": "This download is not available on Real-Debrid and polling download status from Real-Debrid is not yet available.", "download_error_not_cached_in_real_debrid": "This download is not available on Real-Debrid and polling download status from Real-Debrid is not yet available.",
"download_error_not_cached_on_torbox": "This download is not available on TorBox and polling download status from TorBox is not yet available.", "download_error_not_cached_in_torbox": "This download is not available on Torbox and polling download status from Torbox is not yet available.",
"download_error_not_cached_on_hydra": "This download is not available on Nimbus.",
"game_removed_from_favorites": "Game removed from favorites", "game_removed_from_favorites": "Game removed from favorites",
"game_added_to_favorites": "Game added to favorites", "game_added_to_favorites": "Game added to favorites"
"automatically_extract_downloaded_files": "Automatically extract downloaded files"
}, },
"activation": { "activation": {
"title": "Activate Hydra", "title": "Activate Hydra",
@@ -235,9 +228,7 @@
"seeding": "Seeding", "seeding": "Seeding",
"stop_seeding": "Stop seeding", "stop_seeding": "Stop seeding",
"resume_seeding": "Resume seeding", "resume_seeding": "Resume seeding",
"options": "Manage", "options": "Manage"
"extract": "Extract files",
"extracting": "Extracting files…"
}, },
"settings": { "settings": {
"downloads_path": "Downloads path", "downloads_path": "Downloads path",
@@ -274,12 +265,6 @@
"download_source_errored": "Errored", "download_source_errored": "Errored",
"sync_download_sources": "Sync sources", "sync_download_sources": "Sync sources",
"removed_download_source": "Download source removed", "removed_download_source": "Download source removed",
"removed_download_sources": "Download sources removed",
"cancel_button_confirmation_delete_all_sources": "No",
"confirm_button_confirmation_delete_all_sources": "Yes, delete everything",
"title_confirmation_delete_all_sources": "Delete all download sources",
"description_confirmation_delete_all_sources": "You will delete all download sources",
"button_delete_all_sources": "Remove all",
"added_download_source": "Added download source", "added_download_source": "Added download source",
"download_sources_synced": "All download sources are synced", "download_sources_synced": "All download sources are synced",
"insert_valid_json_url": "Insert a valid JSON url", "insert_valid_json_url": "Insert a valid JSON url",
@@ -339,24 +324,15 @@
"delete_theme_description": "This will delete the theme {{theme}}", "delete_theme_description": "This will delete the theme {{theme}}",
"cancel": "Cancel", "cancel": "Cancel",
"appearance": "Appearance", "appearance": "Appearance",
"enable_torbox": "Enable TorBox", "enable_torbox": "Enable Torbox",
"torbox_description": "TorBox is your premium seedbox service rivaling even the best servers on the market.", "torbox_description": "TorBox is your premium seedbox service rivaling even the best servers on the market.",
"torbox_account_linked": "TorBox account linked", "torbox_account_linked": "TorBox account linked",
"create_real_debrid_account": "Click here if you don't have a Real-Debrid account yet",
"create_torbox_account": "Click here if you don't have a TorBox account yet",
"real_debrid_account_linked": "Real-Debrid account linked", "real_debrid_account_linked": "Real-Debrid account linked",
"name_min_length": "Theme name must be at least 3 characters long", "name_min_length": "Theme name must be at least 3 characters long",
"import_theme": "Import theme", "import_theme": "Import theme",
"import_theme_description": "You will import {{theme}} from the theme store", "import_theme_description": "You will import {{theme}} from the theme store",
"error_importing_theme": "Error importing theme", "error_importing_theme": "Error importing theme",
"theme_imported": "Theme imported successfully", "theme_imported": "Theme imported successfully"
"enable_friend_request_notifications": "When a friend request is received",
"enable_auto_install": "Download updates automatically",
"common_redist": "Common redistributables",
"common_redist_description": "Common redistributables are required to run some games. Installing them is recommended to avoid issues.",
"install_common_redist": "Install",
"installing_common_redist": "Installing…",
"show_download_speed_in_megabytes": "Show download speed in megabytes per second"
}, },
"notifications": { "notifications": {
"download_complete": "Download complete", "download_complete": "Download complete",
@@ -367,19 +343,13 @@
"new_update_available": "Version {{version}} available", "new_update_available": "Version {{version}} available",
"restart_to_install_update": "Restart Hydra to install the update", "restart_to_install_update": "Restart Hydra to install the update",
"notification_achievement_unlocked_title": "Achievement unlocked for {{game}}", "notification_achievement_unlocked_title": "Achievement unlocked for {{game}}",
"notification_achievement_unlocked_body": "{{achievement}} and other {{count}} were unlocked", "notification_achievement_unlocked_body": "{{achievement}} and other {{count}} were unlocked"
"new_friend_request_description": "You have received a new friend request",
"new_friend_request_title": "New friend request",
"extraction_complete": "Extraction complete",
"game_extracted": "{{title}} extracted successfully"
}, },
"system_tray": { "system_tray": {
"open": "Open Hydra", "open": "Open Hydra",
"quit": "Quit" "quit": "Quit"
}, },
"game_card": { "game_card": {
"available_one": "Available",
"available_other": "Available",
"no_downloads": "No downloads available" "no_downloads": "No downloads available"
}, },
"binary_not_found_modal": { "binary_not_found_modal": {
@@ -474,6 +444,9 @@
"show_achievements_on_profile": "Show your achievements on your profile", "show_achievements_on_profile": "Show your achievements on your profile",
"show_points_on_profile": "Show your earned points on your profile" "show_points_on_profile": "Show your earned points on your profile"
}, },
"badge": {
"badge_description_theme_creator": "Awarded to those who created a custom theme"
},
"achievement": { "achievement": {
"achievement_unlocked": "Achievement unlocked", "achievement_unlocked": "Achievement unlocked",
"user_achievements": "{{displayName}}'s Achievements", "user_achievements": "{{displayName}}'s Achievements",
@@ -500,7 +473,6 @@
"animated_profile_banner": "Animated profile banner", "animated_profile_banner": "Animated profile banner",
"hydra_cloud": "Hydra Cloud", "hydra_cloud": "Hydra Cloud",
"hydra_cloud_feature_found": "You've just discovered a Hydra Cloud feature!", "hydra_cloud_feature_found": "You've just discovered a Hydra Cloud feature!",
"learn_more": "Learn More", "learn_more": "Learn More"
"debrid_description": "Download up to 4x faster with Nimbus"
} }
} }

View File

@@ -174,8 +174,6 @@
"manage_files_description": "Gestiona los archivos que serán respaldados y restaurados", "manage_files_description": "Gestiona los archivos que serán respaldados y restaurados",
"select_folder": "Seleccionar carpeta", "select_folder": "Seleccionar carpeta",
"backup_from": "Copia de seguridad de {{date}}", "backup_from": "Copia de seguridad de {{date}}",
"automatic_backup_from": "Copia de seguridad automática de {{date}}",
"enable_automatic_cloud_sync": "Habilitar sincronización automática en la nube",
"custom_backup_location_set": "Se configuró la carpeta de copia de seguridad", "custom_backup_location_set": "Se configuró la carpeta de copia de seguridad",
"clear": "Limpiar", "clear": "Limpiar",
"no_directory_selected": "No se seleccionó un directorio", "no_directory_selected": "No se seleccionó un directorio",
@@ -187,13 +185,7 @@
"reset_achievements_description": "Esto reiniciará todos los logros de {{game}}", "reset_achievements_description": "Esto reiniciará todos los logros de {{game}}",
"reset_achievements_title": "¿Estás seguro?", "reset_achievements_title": "¿Estás seguro?",
"reset_achievements_success": "Logros reiniciados exitosamente", "reset_achievements_success": "Logros reiniciados exitosamente",
"reset_achievements_error": "Se produjo un error al reiniciar los logros", "reset_achievements_error": "Se produjo un error al reiniciar los logros"
"download_error_gofile_quota_exceeded": "Has excedido la cuota mensual de Gofile. Por favor espera a que se reinicie la cuota.",
"download_error_real_debrid_account_not_authorized": "Tu cuenta de Real-Debrid no está autorizada para nueva descargas. Por favor, revisa los ajustes de tu cuenta e intenta de nuevo.",
"download_error_not_cached_on_real_debrid": "Esta descarga no está disponible en Real-Debrid y el estado de descarga del sondeo de Real-Debrid aún no está disponible.",
"download_error_not_cached_on_torbox": "Esta descarga no está disponible en TorBox y el estado de descarga del sondeo aún no está disponible.",
"game_added_to_favorites": "Juego añadido a favoritos",
"game_removed_from_favorites": "Juego removido de favoritos"
}, },
"activation": { "activation": {
"title": "Activar Hydra", "title": "Activar Hydra",
@@ -267,12 +259,6 @@
"download_source_errored": "Error", "download_source_errored": "Error",
"sync_download_sources": "Sincronizar fuentes", "sync_download_sources": "Sincronizar fuentes",
"removed_download_source": "Fuente de descarga eliminada", "removed_download_source": "Fuente de descarga eliminada",
"cancel_button_confirmation_delete_all_sources": "No",
"confirm_button_confirmation_delete_all_sources": "Sí, eliminar todo",
"description_confirmation_delete_all_sources": "Eliminarás todas las fuentes de descarga",
"title_confirmation_delete_all_sources": "Eliminar todas las fuentes de descarga",
"removed_download_sources": "Fuentes de descarga eliminadas",
"button_delete_all_sources": "Eliminar todas las fuentes de descarga",
"added_download_source": "Fuente de descarga añadida", "added_download_source": "Fuente de descarga añadida",
"download_sources_synced": "Todas las fuentes de descargas están actualizadas.", "download_sources_synced": "Todas las fuentes de descargas están actualizadas.",
"insert_valid_json_url": "Introduce una URL JSON válida", "insert_valid_json_url": "Introduce una URL JSON válida",
@@ -304,45 +290,14 @@
"no_email_account": "No has configurado un correo aún", "no_email_account": "No has configurado un correo aún",
"no_subscription": "Disfruta Hydra de la mejor manera", "no_subscription": "Disfruta Hydra de la mejor manera",
"no_users_blocked": "No tienes usuarios bloqueados", "no_users_blocked": "No tienes usuarios bloqueados",
"notifications": "Notificaciones",
"renew_subscription": "Renovar Hydra Cloud", "renew_subscription": "Renovar Hydra Cloud",
"subscription_active_until": "Tu Hydra Cloud está activa hasta {{date}}", "subscription_active_until": "Tu Hydra Cloud está activa hasta {{date}}",
"subscription_expired_at": "Tú suscripción expiró el {{date}}", "subscription_expired_at": "Tú suscripción expiró el {{date}}",
"subscription_renew_cancelled": "Está desactivada la renovación automática", "subscription_renew_cancelled": "Está desactivada la renovación automática",
"subscription_renews_on": "Tú suscripción se renueva el {{date}}", "subscription_renews_on": "Tú suscripción se renueva el {{date}}",
"update_email": "Actualizar correo", "update_email": "Actualizar correo",
"update_password": "Actualizar contraseña", "update_password": "Actualizar contraseña"
"appearance": "Apariencia",
"become_subscriber": "Sé Hydra Cloud",
"cancel": "Cancelar",
"clear_themes": "Limpiar",
"create_theme": "Crear",
"create_theme_modal_description": "Crea un nuevo tema para personalizar la apariencia de Hydra",
"create_theme_modal_title": "Crear tema personalizado",
"delete_all_themes": "Eliminar todos los temas",
"delete_all_themes_description": "Esto eliminará todos tus temas personalizados",
"delete_theme": "Eliminar tema",
"delete_theme_description": "Esto eliminará el tema {{theme}}",
"edit_theme": "Editar tema",
"editor_tab_code": "Código",
"editor_tab_info": "Info",
"editor_tab_save": "Guardar",
"enable_torbox": "Habilitar TorBox",
"error_importing_theme": "Error al importar el tema",
"import_theme": "Importar tema",
"import_theme_description": "Vas a importar el tema {{theme}} desde la tienda de temas",
"insert_theme_name": "Introducí el nombre del tema",
"name_min_length": "El tema tiene que tener 3 carácteres de largo mínimo",
"no_themes": "Parece que no tenés ningún tema aún, pero no te preocupes, presiona acá para crear tu primer tema.",
"real_debrid_account_linked": "Cuenta de Real-Debrid vinculada",
"set_theme": "Establecer tema",
"theme_imported": "Tema importado exitosamente",
"theme_name": "Nombre",
"torbox_account_linked": "Cuenta de TorBox vinculada",
"torbox_description": "TorBox es tu servicio premium de seedbox que rivaliza incluso a los mejores servidores del mercado.",
"unset_theme": "Desactivar tema",
"web_store": "Tienda Web",
"enable_friend_request_notifications": "Cuando se recibe una solicitud de amistad",
"enable_auto_install": "Descargar actualizaciones automáticamente"
}, },
"notifications": { "notifications": {
"download_complete": "Descarga completada", "download_complete": "Descarga completada",
@@ -353,17 +308,13 @@
"new_update_available": "Version {{version}} disponible", "new_update_available": "Version {{version}} disponible",
"restart_to_install_update": "Reinicia Hydra para instalar la actualización", "restart_to_install_update": "Reinicia Hydra para instalar la actualización",
"notification_achievement_unlocked_title": "Logro desbloqueado de {{game}}", "notification_achievement_unlocked_title": "Logro desbloqueado de {{game}}",
"notification_achievement_unlocked_body": "{{achievement}} y otros {{count}} fueron desbloqueados", "notification_achievement_unlocked_body": "{{achievement}} y otros {{count}} fueron desbloqueados"
"new_friend_request_title": "Nueva solicitud de amistad",
"new_friend_request_description": "Has recibido una nueva solicitud de amistad"
}, },
"system_tray": { "system_tray": {
"open": "Abrir Hydra", "open": "Abrir Hydra",
"quit": "Salir" "quit": "Salir"
}, },
"game_card": { "game_card": {
"available_one": "Disponible",
"available_other": "Disponibles",
"no_downloads": "No hay descargas disponibles" "no_downloads": "No hay descargas disponibles"
}, },
"binary_not_found_modal": { "binary_not_found_modal": {

View File

@@ -236,12 +236,6 @@
"download_source_errored": "Vigane", "download_source_errored": "Vigane",
"sync_download_sources": "Sünkroniseeri allikad", "sync_download_sources": "Sünkroniseeri allikad",
"removed_download_source": "Allalaadimise allikas eemaldatud", "removed_download_source": "Allalaadimise allikas eemaldatud",
"cancel_button_confirmation_delete_all_sources": "Ei",
"confirm_button_confirmation_delete_all_sources": "Jah, kustuta kõik",
"description_confirmation_delete_all_sources": "Kustutate kõik allalaadimisallikad",
"title_confirmation_delete_all_sources": "Kustutage kõik allalaadimisallikad",
"removed_download_sources": "Allalaadimise allikas eemaldati",
"button_delete_all_sources": "Eemaldage kõik allalaadimisallikad",
"added_download_source": "Allalaadimise allikas lisatud", "added_download_source": "Allalaadimise allikas lisatud",
"download_sources_synced": "Kõik allalaadimise allikad on sünkroniseeritud", "download_sources_synced": "Kõik allalaadimise allikad on sünkroniseeritud",
"insert_valid_json_url": "Sisesta kehtiv JSON url", "insert_valid_json_url": "Sisesta kehtiv JSON url",

View File

@@ -111,12 +111,6 @@
"launch_with_system": "زمانی که سیستم روشن می‌شود، هایدرا را باز کن", "launch_with_system": "زمانی که سیستم روشن می‌شود، هایدرا را باز کن",
"general": "کلی", "general": "کلی",
"behavior": "رفتار", "behavior": "رفتار",
"cancel_button_confirmation_delete_all_sources": "خیر",
"confirm_button_confirmation_delete_all_sources": "ہاں، سب کچھ حذف کر دیں۔",
"description_confirmation_delete_all_sources": "آپ ڈاؤن لوڈ کے تمام ذرائع کو حذف کر دیں گے۔",
"title_confirmation_delete_all_sources": "تمام منابع دانلود را حذف کنید",
"removed_download_sources": "منابع دانلود حذف شد",
"button_delete_all_sources": "تمام منابع دانلود را حذف کنید",
"enable_real_debrid": "فعال‌سازی Real-Debrid", "enable_real_debrid": "فعال‌سازی Real-Debrid",
"debrid_api_token_hint": "کلید API خود را از <ب0>اینجا</0> بگیرید.", "debrid_api_token_hint": "کلید API خود را از <ب0>اینجا</0> بگیرید.",
"save_changes": "ذخیره تغییرات" "save_changes": "ذخیره تغییرات"

View File

@@ -99,13 +99,7 @@
"notifications": "Notifications", "notifications": "Notifications",
"enable_download_notifications": "Quand un téléchargement est terminé", "enable_download_notifications": "Quand un téléchargement est terminé",
"enable_repack_list_notifications": "Quand un nouveau repack est ajouté", "enable_repack_list_notifications": "Quand un nouveau repack est ajouté",
"language": "Langue", "language": "Langue"
"cancel_button_confirmation_delete_all_sources": "Non",
"confirm_button_confirmation_delete_all_sources": "Oui, tout supprimer",
"description_confirmation_delete_all_sources": "Vous supprimerez toutes les sources de téléchargement",
"title_confirmation_delete_all_sources": "Supprimer toutes les sources de téléchargement",
"removed_download_sources": "Sources de téléchargement supprimées",
"button_delete_all_sources": "Supprimer toutes les sources de téléchargement"
}, },
"notifications": { "notifications": {
"download_complete": "Téléchargement terminé", "download_complete": "Téléchargement terminé",

View File

@@ -106,12 +106,6 @@
"change": "Frissítés", "change": "Frissítés",
"notifications": "Értesítések", "notifications": "Értesítések",
"enable_download_notifications": "Amikor egy letöltés befejeződik", "enable_download_notifications": "Amikor egy letöltés befejeződik",
"cancel_button_confirmation_delete_all_sources": "Nem",
"confirm_button_confirmation_delete_all_sources": "Igen, törölj mindent",
"description_confirmation_delete_all_sources": "Törölni fog minden letöltési forrást",
"title_confirmation_delete_all_sources": "Törölje az összes letöltési forrást",
"removed_download_sources": "Betűtípusok eltávolítva",
"button_delete_all_sources": "Távolítsa el az összes letöltési forrást",
"enable_repack_list_notifications": "Amikor egy új repack hozzáadásra kerül" "enable_repack_list_notifications": "Amikor egy új repack hozzáadásra kerül"
}, },
"notifications": { "notifications": {

View File

@@ -175,12 +175,6 @@
"download_sources_description": "Hydra akan mencari link unduhan dari sini. URL harus menuju file .json dengan link unduhan.", "download_sources_description": "Hydra akan mencari link unduhan dari sini. URL harus menuju file .json dengan link unduhan.",
"validate_download_source": "Validasi", "validate_download_source": "Validasi",
"remove_download_source": "Hapus", "remove_download_source": "Hapus",
"cancel_button_confirmation_delete_all_sources": "TIDAK",
"confirm_button_confirmation_delete_all_sources": "Ya, hapus semuanya",
"description_confirmation_delete_all_sources": "Anda akan menghapus semua sumber unduhan",
"title_confirmation_delete_all_sources": "Hapus semua sumber unduhan",
"removed_download_sources": "Font dihapus",
"button_delete_all_sources": "Hapus semua sumber unduhan",
"add_download_source": "Tambahkan sumber", "add_download_source": "Tambahkan sumber",
"download_count_zero": "Tidak ada unduhan dalam daftar", "download_count_zero": "Tidak ada unduhan dalam daftar",
"download_count_one": "{{countFormatted}} unduhan dalam daftar", "download_count_one": "{{countFormatted}} unduhan dalam daftar",

View File

@@ -120,12 +120,6 @@
"general": "Generale", "general": "Generale",
"behavior": "Comportamento", "behavior": "Comportamento",
"enable_real_debrid": "Abilita Real Debrid", "enable_real_debrid": "Abilita Real Debrid",
"cancel_button_confirmation_delete_all_sources": "NO",
"confirm_button_confirmation_delete_all_sources": "Sì, cancella tutto",
"description_confirmation_delete_all_sources": "Eliminerai tutte le fonti di download",
"title_confirmation_delete_all_sources": "Elimina tutte le fonti di download",
"removed_download_sources": "Fonti di download rimosse",
"button_delete_all_sources": "Rimuovi tutte le fonti di download",
"debrid_api_token_hint": "Puoi trovare la tua chiave API <0>here</0>", "debrid_api_token_hint": "Puoi trovare la tua chiave API <0>here</0>",
"save_changes": "Salva modifiche" "save_changes": "Salva modifiche"
}, },

View File

@@ -173,12 +173,6 @@
"download_sources_description": "Hydra осы көздерден жүктеу сілтемелерін алады. URL-да жүктеу сілтемелері бар .json файлына тікелей сілтеме болуы керек.", "download_sources_description": "Hydra осы көздерден жүктеу сілтемелерін алады. URL-да жүктеу сілтемелері бар .json файлына тікелей сілтеме болуы керек.",
"validate_download_source": "Тексеру", "validate_download_source": "Тексеру",
"remove_download_source": "Жою", "remove_download_source": "Жою",
"cancel_button_confirmation_delete_all_sources": "Жоқ",
"confirm_button_confirmation_delete_all_sources": "Иә, бәрін жойыңыз",
"description_confirmation_delete_all_sources": "Барлық жүктеу көздерін жоясыз",
"title_confirmation_delete_all_sources": "Барлық жүктеу көздерін жойыңыз",
"removed_download_sources": "Қаріптер жойылды",
"button_delete_all_sources": "Барлық жүктеу көздерін жойыңыз",
"add_download_source": "Жүктеу көзін қосу", "add_download_source": "Жүктеу көзін қосу",
"download_count_zero": "Жүктеулер тізімінде жоқ", "download_count_zero": "Жүктеулер тізімінде жоқ",
"download_count_one": "{{countFormatted}} жүктеу тізімде", "download_count_one": "{{countFormatted}} жүктеу тізімде",

View File

@@ -111,12 +111,6 @@
"launch_with_system": "컴퓨터가 시작되었을 때 Hydra 실행", "launch_with_system": "컴퓨터가 시작되었을 때 Hydra 실행",
"general": "일반", "general": "일반",
"behavior": "행동", "behavior": "행동",
"cancel_button_confirmation_delete_all_sources": "아니요",
"confirm_button_confirmation_delete_all_sources": "네, 모두 삭제합니다",
"description_confirmation_delete_all_sources": "모든 다운로드 소스를 삭제합니다.",
"title_confirmation_delete_all_sources": "모든 다운로드 소스 삭제",
"removed_download_sources": "제거된 글꼴",
"button_delete_all_sources": "모든 다운로드 소스 제거",
"enable_real_debrid": "Real-Debrid 활성화", "enable_real_debrid": "Real-Debrid 활성화",
"debrid_api_token_hint": "API 키를 <0>이곳</0>에서 얻으세요.", "debrid_api_token_hint": "API 키를 <0>이곳</0>에서 얻으세요.",
"save_changes": "변경 사항 저장" "save_changes": "변경 사항 저장"

View File

@@ -201,12 +201,6 @@
"download_source_errored": "Mislyktes", "download_source_errored": "Mislyktes",
"sync_download_sources": "Synkroniser kilder", "sync_download_sources": "Synkroniser kilder",
"removed_download_source": "Nedlastingskilde fjernet", "removed_download_source": "Nedlastingskilde fjernet",
"cancel_button_confirmation_delete_all_sources": "Ingen",
"confirm_button_confirmation_delete_all_sources": "Ja, slett alt",
"description_confirmation_delete_all_sources": "Du vil slette alle nedlastingskilder",
"title_confirmation_delete_all_sources": "Slett alle nedlastingskilder",
"removed_download_sources": "Fonter fjernet",
"button_delete_all_sources": "Fjern alle nedlastingskilder",
"added_download_source": "La til Nedlastingskilde", "added_download_source": "La til Nedlastingskilde",
"download_sources_synced": "Alle nedlastingskilder er synkroniserte", "download_sources_synced": "Alle nedlastingskilder er synkroniserte",
"insert_valid_json_url": "Innsett en gyldig JSON url", "insert_valid_json_url": "Innsett en gyldig JSON url",

View File

@@ -112,12 +112,6 @@
"launch_with_system": "Start Hydra bij het opstarten van het systeem", "launch_with_system": "Start Hydra bij het opstarten van het systeem",
"general": "Algemeen", "general": "Algemeen",
"behavior": "Gedrag", "behavior": "Gedrag",
"cancel_button_confirmation_delete_all_sources": "Nee",
"confirm_button_confirmation_delete_all_sources": "Ja, verwijder alles",
"description_confirmation_delete_all_sources": "Je verwijdert alle downloadbronnen",
"title_confirmation_delete_all_sources": "Verwijder alle downloadbronnen",
"removed_download_sources": "Downloadbronnen verwijderd",
"button_delete_all_sources": "Verwijder alle downloadbronnen",
"enable_real_debrid": "Enable Real-Debrid", "enable_real_debrid": "Enable Real-Debrid",
"debrid_api_token_hint": "U kunt uw API-sleutel <0>hier</0> verkrijgen.", "debrid_api_token_hint": "U kunt uw API-sleutel <0>hier</0> verkrijgen.",
"save_changes": "Wijzigingen opslaan" "save_changes": "Wijzigingen opslaan"

View File

@@ -120,11 +120,6 @@
"general": "Ogólne", "general": "Ogólne",
"behavior": "Zachowania", "behavior": "Zachowania",
"language": "Język", "language": "Język",
"cancel_button_confirmation_delete_all_sources": "NIE",
"confirm_button_confirmation_delete_all_sources": "Tak, usuń wszystko",
"description_confirmation_delete_all_sources": "Usuniesz wszystkie źródła pobierania",
"title_confirmation_delete_all_sources": "Usuń wszystkie źródła pobierania",
"button_delete_all_sources": "Usuń wszystkie źródła pobierania",
"enable_real_debrid": "Włącz Real-Debrid", "enable_real_debrid": "Włącz Real-Debrid",
"debrid_api_token_hint": "Możesz uzyskać swój klucz API <0>tutaj</0>", "debrid_api_token_hint": "Możesz uzyskać swój klucz API <0>tutaj</0>",
"save_changes": "Zapisz zmiany" "save_changes": "Zapisz zmiany"

View File

@@ -31,6 +31,7 @@
}, },
"header": { "header": {
"search": "Buscar jogos", "search": "Buscar jogos",
"catalogue": "Catálogo", "catalogue": "Catálogo",
"downloads": "Downloads", "downloads": "Downloads",
"search_results": "Resultados da busca", "search_results": "Resultados da busca",
@@ -44,10 +45,7 @@
"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}}…", "checking_files": "Verificando arquivos de {{title}}…"
"installing_common_redist": "{{log}}…",
"installation_complete": "Instalação concluída",
"installation_complete_message": "Componentes recomendados instalados com sucesso"
}, },
"game_details": { "game_details": {
"open_download_options": "Ver opções de download", "open_download_options": "Ver opções de download",
@@ -167,8 +165,6 @@
"max_number_of_artifacts_reached": "Número máximo de backups atingido para este jogo", "max_number_of_artifacts_reached": "Número máximo de backups atingido para este jogo",
"achievements_not_sync": "Veja como exibir suas conquistas no perfil", "achievements_not_sync": "Veja como exibir suas conquistas no perfil",
"backup_from": "Backup de {{date}}", "backup_from": "Backup de {{date}}",
"automatic_backup_from": "Backup automático de {{date}}",
"enable_automatic_cloud_sync": "Habilitar sincronização automática na nuvem",
"custom_backup_location_set": "Localização customizada selecionada", "custom_backup_location_set": "Localização customizada selecionada",
"select_folder": "Selecione a pasta", "select_folder": "Selecione a pasta",
"manage_files_description": "Gerencie quais arquivos serão feitos backup", "manage_files_description": "Gerencie quais arquivos serão feitos backup",
@@ -182,12 +178,10 @@
"no_write_permission": "Não é possível baixar nesse diretório. Clique aqui para saber mais.", "no_write_permission": "Não é possível baixar nesse diretório. Clique aqui para saber mais.",
"download_error_gofile_quota_exceeded": "Você excedeu sua cota mensal do Gofile. Por favor, aguarde a cota resetar.", "download_error_gofile_quota_exceeded": "Você excedeu sua cota mensal do Gofile. Por favor, aguarde a cota resetar.",
"download_error_real_debrid_account_not_authorized": "Sua conta do Real-Debrid não está autorizada a fazer novos downloads. Por favor, verifique sua assinatura e tente novamente.", "download_error_real_debrid_account_not_authorized": "Sua conta do Real-Debrid não está autorizada a fazer novos downloads. Por favor, verifique sua assinatura e tente novamente.",
"download_error_not_cached_on_real_debrid": "Este download não está disponível no Real-Debrid e a verificação do status do download não está disponível.", "download_error_not_cached_in_real_debrid": "Este download não está disponível no Real-Debrid e a verificação do status do download não está disponível.",
"download_error_not_cached_on_torbox": "Este download não está disponível no TorBox e a verificação do status do download não está disponível.", "download_error_not_cached_in_torbox": "Este download não está disponível no Torbox e a verificação do status do download não está disponível.",
"download_error_not_cached_on_hydra": "Este download não está disponível no Nimbus.",
"game_removed_from_favorites": "Jogo removido dos favoritos", "game_removed_from_favorites": "Jogo removido dos favoritos",
"game_added_to_favorites": "Jogo adicionado aos favoritos", "game_added_to_favorites": "Jogo adicionado aos favoritos"
"automatically_extract_downloaded_files": "Extrair automaticamente os arquivos baixados"
}, },
"activation": { "activation": {
"title": "Ativação", "title": "Ativação",
@@ -224,9 +218,7 @@
"seeding": "Semeando", "seeding": "Semeando",
"stop_seeding": "Parar de semear", "stop_seeding": "Parar de semear",
"resume_seeding": "Semear", "resume_seeding": "Semear",
"options": "Gerenciar", "options": "Gerenciar"
"extract": "Extrair arquivos",
"extracting": "Extraindo arquivos…"
}, },
"settings": { "settings": {
"downloads_path": "Diretório dos downloads", "downloads_path": "Diretório dos downloads",
@@ -263,12 +255,6 @@
"download_source_errored": "Falhou", "download_source_errored": "Falhou",
"sync_download_sources": "Sincronizar", "sync_download_sources": "Sincronizar",
"removed_download_source": "Fonte removida", "removed_download_source": "Fonte removida",
"removed_download_sources": "Fontes removidas",
"cancel_button_confirmation_delete_all_sources": "Não",
"confirm_button_confirmation_delete_all_sources": "Sim, excluir tudo",
"title_confirmation_delete_all_sources": "Remover todas as fontes de download",
"description_confirmation_delete_all_sources": "Você irá remover todas as fontes de download. Deseja prosseguir?",
"button_delete_all_sources": "Remover todas",
"added_download_source": "Fonte adicionada", "added_download_source": "Fonte adicionada",
"download_sources_synced": "As fontes foram sincronizadas", "download_sources_synced": "As fontes foram sincronizadas",
"insert_valid_json_url": "Insira a url de um JSON válido", "insert_valid_json_url": "Insira a url de um JSON válido",
@@ -326,24 +312,15 @@
"delete_theme_description": "Isso irá deletar o tema {{theme}}", "delete_theme_description": "Isso irá deletar o tema {{theme}}",
"cancel": "Cancelar", "cancel": "Cancelar",
"appearance": "Aparência", "appearance": "Aparência",
"enable_torbox": "Habilitar TorBox", "enable_torbox": "Habilitar Torbox",
"torbox_description": "TorBox é o seu serviço de seedbox premium que rivaliza até com os melhores servidores do mercado.", "torbox_description": "TorBox é o seu serviço de seedbox premium que rivaliza até com os melhores servidores do mercado.",
"torbox_account_linked": "Conta do TorBox vinculada", "torbox_account_linked": "Conta do TorBox vinculada",
"create_real_debrid_account": "Clique aqui se você ainda não tem uma conta do Real-Debrid",
"create_torbox_account": "Clique aqui se você ainda não tem uma conta do TorBox",
"real_debrid_account_linked": "Conta Real-Debrid associada", "real_debrid_account_linked": "Conta Real-Debrid associada",
"name_min_length": "O nome do tema deve ter pelo menos 3 caracteres", "name_min_length": "O nome do tema deve ter pelo menos 3 caracteres",
"import_theme": "Importar tema", "import_theme": "Importar tema",
"import_theme_description": "Você irá importar {{theme}} da loja de temas", "import_theme_description": "Você irá importar {{theme}} da loja de temas",
"error_importing_theme": "Erro ao importar tema", "error_importing_theme": "Erro ao importar tema",
"theme_imported": "Tema importado com sucesso", "theme_imported": "Tema importado com sucesso"
"enable_friend_request_notifications": "Quando um pedido de amizade é recebido",
"enable_auto_install": "Baixar atualizações automaticamente",
"common_redist": "Componentes recomendados",
"common_redist_description": "Componentes recomendados são necessários para executar alguns jogos. A instalação deles é recomendada para evitar problemas.",
"install_common_redist": "Instalar",
"installing_common_redist": "Instalando…",
"show_download_speed_in_megabytes": "Exibir taxas de download em megabytes por segundo"
}, },
"notifications": { "notifications": {
"download_complete": "Download concluído", "download_complete": "Download concluído",
@@ -352,19 +329,13 @@
"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", "new_update_available": "Versão {{version}} disponível",
"restart_to_install_update": "Reinicie o Hydra para instalar a nova versão", "restart_to_install_update": "Reinicie o Hydra para instalar a nova versão"
"new_friend_request_title": "Novo pedido de amizade",
"new_friend_request_description": "Você recebeu um novo pedido de amizade",
"extraction_complete": "Extração concluída",
"game_extracted": "{{title}} extraído com sucesso"
}, },
"system_tray": { "system_tray": {
"open": "Abrir Hydra", "open": "Abrir Hydra",
"quit": "Fechar" "quit": "Fechar"
}, },
"game_card": { "game_card": {
"available_one": "Disponível",
"available_other": "Disponíveis",
"no_downloads": "Sem downloads disponíveis" "no_downloads": "Sem downloads disponíveis"
}, },
"binary_not_found_modal": { "binary_not_found_modal": {
@@ -469,6 +440,9 @@
"show_achievements_on_profile": "Exiba suas conquistas no perfil", "show_achievements_on_profile": "Exiba suas conquistas no perfil",
"show_points_on_profile": "Exiba seus pontos ganhos no perfil" "show_points_on_profile": "Exiba seus pontos ganhos no perfil"
}, },
"badge": {
"badge_description_theme_creator": "Concedido àqueles que criaram um tema customizado"
},
"achievement": { "achievement": {
"achievement_unlocked": "Conquista desbloqueada", "achievement_unlocked": "Conquista desbloqueada",
"your_achievements": "Suas Conquistas", "your_achievements": "Suas Conquistas",
@@ -495,7 +469,6 @@
"animated_profile_banner": "Banner animado no perfil", "animated_profile_banner": "Banner animado no perfil",
"cloud_saving": "Saves de jogos em nuvem", "cloud_saving": "Saves de jogos em nuvem",
"hydra_cloud_feature_found": "Você descobriu uma funcionalidade Hydra Cloud!", "hydra_cloud_feature_found": "Você descobriu uma funcionalidade Hydra Cloud!",
"learn_more": "Saiba mais", "learn_more": "Saiba mais"
"debrid_description": "Baixe até 4x mais rápido com Nimbus"
} }
} }

View File

@@ -30,6 +30,7 @@
}, },
"header": { "header": {
"search": "Procurar jogos", "search": "Procurar jogos",
"catalogue": "Catálogo", "catalogue": "Catálogo",
"downloads": "Transferências", "downloads": "Transferências",
"search_results": "Resultados da pesquisa", "search_results": "Resultados da pesquisa",
@@ -102,7 +103,7 @@
"open_download_location": "Ver ficheiros transferidos", "open_download_location": "Ver ficheiros transferidos",
"create_shortcut": "Criar atalho no ambiente de trabalho", "create_shortcut": "Criar atalho no ambiente de trabalho",
"remove_files": "Remover ficheiros", "remove_files": "Remover ficheiros",
"options": "Opções", "options": "Gerir",
"remove_from_library_description": "Isto vai remover {{game}} da tua biblioteca", "remove_from_library_description": "Isto vai remover {{game}} da tua biblioteca",
"remove_from_library_title": "Tens a certeza?", "remove_from_library_title": "Tens a certeza?",
"executable_section_title": "Executável", "executable_section_title": "Executável",
@@ -158,27 +159,7 @@
"no_download_option_info": "Sem informações disponíveis", "no_download_option_info": "Sem informações disponíveis",
"backup_deletion_failed": "Falha ao apagar o backup", "backup_deletion_failed": "Falha ao apagar o backup",
"max_number_of_artifacts_reached": "Número máximo de backups atingido para este jogo", "max_number_of_artifacts_reached": "Número máximo de backups atingido para este jogo",
"achievements_not_sync": "As tuas conquistas não estão sincronizadas", "achievements_not_sync": "As tuas conquistas não estão sincronizadas"
"backup_from": "Backup de {{date}}",
"automatic_backup_from": "Backup automático de {{date}}",
"enable_automatic_cloud_sync": "Ativar sincronização automática na nuvem",
"custom_backup_location_set": "Localização customizada selecionada",
"select_folder": "Selecione a pasta",
"manage_files_description": "Gerencie quais arquivos serão feitos backup",
"clear": "Limpar",
"no_directory_selected": "Nenhum diretório selecionado",
"reset_achievements": "Repor conquistas",
"reset_achievements_description": "Isto irá apagar todas as conquistas de {{game}}",
"reset_achievements_title": "Tem certeza?",
"reset_achievements_success": "Conquistas repostas com sucesso",
"reset_achievements_error": "Falha ao repor conquistas",
"no_write_permission": "Não é possível descarregar neste diretório. Clique aqui para saber mais.",
"download_error_gofile_quota_exceeded": "Você excedeu sua cota mensal do Gofile. Por favor, aguarde o reset da cota.",
"download_error_real_debrid_account_not_authorized": "A sua conta do Real-Debrid não está autorizada a fazer novos downloads. Por favor, verifique a sua assinatura e tente novamente.",
"download_error_not_cached_on_real_debrid": "Este download não está disponível no Real-Debrid e a verificação do status do download não está disponível.",
"download_error_not_cached_on_torbox": "Este download não está disponível no TorBox e a verificação do status do download não está disponível.",
"game_removed_from_favorites": "Jogo removido dos favoritos",
"game_added_to_favorites": "Jogo adicionado aos favoritos"
}, },
"activation": { "activation": {
"title": "Ativação", "title": "Ativação",
@@ -211,11 +192,7 @@
"queued": "Na fila", "queued": "Na fila",
"no_downloads_title": "Nada por aqui…", "no_downloads_title": "Nada por aqui…",
"no_downloads_description": "Ainda não descarregaste nada pelo Hydra, mas nunca é tarde para começar.", "no_downloads_description": "Ainda não descarregaste nada pelo Hydra, mas nunca é tarde para começar.",
"checking_files": "A verificar ficheiros…", "checking_files": "A verificar ficheiros…"
"seeding": "A semear",
"stop_seeding": "Parar de semear",
"resume_seeding": "Semear",
"options": "Opções"
}, },
"settings": { "settings": {
"downloads_path": "Local das transferências", "downloads_path": "Local das transferências",
@@ -255,12 +232,6 @@
"download_source_errored": "Falhou", "download_source_errored": "Falhou",
"sync_download_sources": "Sincronizar", "sync_download_sources": "Sincronizar",
"removed_download_source": "Fonte removida", "removed_download_source": "Fonte removida",
"cancel_button_confirmation_delete_all_sources": "Não",
"confirm_button_confirmation_delete_all_sources": "Sim, apague tudo",
"description_confirmation_delete_all_sources": "Irá remover todas as fontes de download",
"title_confirmation_delete_all_sources": "Remover todas as fontes de download",
"removed_download_sources": "Fontes de download removidas",
"button_delete_all_sources": "Remover todas",
"added_download_source": "Fonte adicionada", "added_download_source": "Fonte adicionada",
"download_sources_synced": "As fontes foram sincronizadas", "download_sources_synced": "As fontes foram sincronizadas",
"insert_valid_json_url": "Insere o URL de um JSON válido", "insert_valid_json_url": "Insere o URL de um JSON válido",
@@ -279,57 +250,7 @@
"must_be_valid_url": "A fonte deve ser um URL válido", "must_be_valid_url": "A fonte deve ser um URL válido",
"blocked_users": "Utilizadores bloqueados", "blocked_users": "Utilizadores bloqueados",
"user_unblocked": "Utilizador desbloqueado", "user_unblocked": "Utilizador desbloqueado",
"enable_achievement_notifications": "Quando uma conquista é desbloqueada", "enable_achievement_notifications": "Quando uma conquista é desbloqueada"
"enable_friend_request_notifications": "Quando um pedido de amizade é recebido",
"launch_minimized": "Iniciar Hydra minimizado",
"disable_nsfw_alert": "Desativar alertas NSFW",
"seed_after_download_complete": "Semear após concluir o download",
"show_hidden_achievement_description": "Mostrar descrição de conquistas ocultas antes de as desbloquear",
"account": "Conta",
"no_users_blocked": "Não tem utilizadores bloqueados",
"subscription_active_until": "O teu Hydra Cloud está ativo até {{date}}",
"manage_subscription": "Gerir subscrições",
"update_email": "Atualizar email",
"update_password": "Atualizar password",
"current_email": "Email atual:",
"no_email_account": "Ainda não adicionou nenhum email à sua conta",
"account_data_updated_successfully": "Dados da conta atualizados com sucesso",
"renew_subscription": "Renovar Hydra Cloud",
"subscription_expired_at": "A sua subscrição expirou a {{date}}",
"no_subscription": "Aproveite o Hydra da melhor forma possível",
"become_subscriber": "Subscreva o Hydra Cloud",
"subscription_renew_cancelled": "A renovação automática está desativada",
"subscription_renews_on": "Sua assinatura renova dia {{date}}",
"bill_sent_until": "A próxima cobrança será enviada até esse dia",
"no_themes": "Parece que ainda não tem nenhum tema. Não se preocupe, clique aqui para criar a sua primeira obra de arte.",
"editor_tab_code": "Código",
"editor_tab_info": "Info",
"editor_tab_save": "Guardar",
"web_store": "Loja de temas",
"clear_themes": "Limpar",
"create_theme": "Criar",
"create_theme_modal_title": "Criar tema customizado",
"create_theme_modal_description": "Criar um novo tema para customizar a aparência do Hydra",
"theme_name": "Nome",
"insert_theme_name": "Insira o nome do tema",
"set_theme": "Definir tema",
"unset_theme": "Redefinir tema",
"delete_theme": "Apagar tema",
"edit_theme": "Editar tema",
"delete_all_themes": "Apagar todos os temas",
"delete_all_themes_description": "Isto irá apagar todos os seus temas",
"delete_theme_description": "Isto irá apagar o tema {{theme}}",
"cancel": "Cancelar",
"appearance": "Aparência",
"enable_torbox": "Ativar TorBox",
"torbox_description": "TorBox é um serviço de seedbox premium sendo um dos melhores servidores do mercado.",
"torbox_account_linked": "Conta do TorBox associada",
"real_debrid_account_linked": "Conta Real-Debrid associada",
"name_min_length": "O nome do tema deve ter pelo menos 3 caracteres",
"import_theme": "Importar tema",
"import_theme_description": "Irá importar {{theme}} da loja de temas",
"error_importing_theme": "Erro ao importar tema",
"theme_imported": "Tema importado com sucesso"
}, },
"notifications": { "notifications": {
"download_complete": "Transferência concluída", "download_complete": "Transferência concluída",
@@ -338,17 +259,13 @@
"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", "new_update_available": "Versão {{version}} disponível",
"restart_to_install_update": "Reinicia o Hydra para instalar a nova versão", "restart_to_install_update": "Reinicia o Hydra para instalar a nova versão"
"new_friend_request_title": "Novo pedido de amizade",
"new_friend_request_description": "Recebeste um novo pedido de amizade"
}, },
"system_tray": { "system_tray": {
"open": "Abrir o Hydra", "open": "Abrir o Hydra",
"quit": "Sair" "quit": "Sair"
}, },
"game_card": { "game_card": {
"available_one": "Disponível",
"available_other": "Disponíveis",
"no_downloads": "Sem downloads disponíveis" "no_downloads": "Sem downloads disponíveis"
}, },
"binary_not_found_modal": { "binary_not_found_modal": {
@@ -358,16 +275,7 @@
}, },
"catalogue": { "catalogue": {
"next_page": "Página seguinte", "next_page": "Página seguinte",
"previous_page": "Página anterior", "previous_page": "Página anterior"
"search": "Filtrar…",
"developers": "Desenvolvedores",
"genres": "Géneros",
"tags": "Marcadores",
"publishers": "Distribuidoras",
"download_sources": "Fontes de download",
"result_count": "{{resultCount}} resultados",
"filter_count": "{{filterCount}} disponíveis",
"clear_filters": "Limpar {{filterCount}} selecionados"
}, },
"modal": { "modal": {
"close": "Botão de fechar" "close": "Botão de fechar"
@@ -444,17 +352,7 @@
"profile_reported": "Perfil denunciado", "profile_reported": "Perfil denunciado",
"your_friend_code": "O teu código de amigo:", "your_friend_code": "O teu código de amigo:",
"upload_banner": "Fazer upload do banner", "upload_banner": "Fazer upload do banner",
"uploading_banner": "A fazer upload do banner…", "uploading_banner": "A fazer upload do banner…"
"background_image_updated": "Imagem de fundo salva",
"stats": "Estatísticas",
"achievements": "conquistas",
"games": "Jogos",
"ranking_updated_weekly": "O ranking é atualizado semanalmente",
"playing": "A jogar {{game}}",
"achievements_unlocked": "Conquistas desbloqueadas",
"earned_points": "Pontos ganhos",
"show_achievements_on_profile": "Mostre as suas conquistas no perfil",
"show_points_on_profile": "Mostre os seus pontos ganhos no perfil"
}, },
"achievement": { "achievement": {
"achievement_unlocked": "Conquista desbloqueada", "achievement_unlocked": "Conquista desbloqueada",
@@ -462,25 +360,15 @@
"user_achievements": "Conquistas de {{displayName}}", "user_achievements": "Conquistas de {{displayName}}",
"unlocked_at": "Desbloqueada em: {{date}}", "unlocked_at": "Desbloqueada em: {{date}}",
"subscription_needed": "Precisas de uma subscrição Hydra Cloud para visualizar este conteúdo", "subscription_needed": "Precisas de uma subscrição Hydra Cloud para visualizar este conteúdo",
"new_achievements_unlocked": "{{achievementCount}} novas conquistas de {{gameCount}} jogos", "new_achievements_unlocked": "{{achievementCount}} novas conquistas de {{gameCount}} jogos"
"achievement_progress": "{{unlockedCount}}/{{totalCount}} conquistas",
"achievements_unlocked_for_game": "Desbloqueadas {{achievementCount}} novas conquistas em {{gameTitle}}",
"hidden_achievement_tooltip": "Esta é uma conquista oculta",
"achievement_earn_points": "Ganhe {{points}} pontos com essa conquista",
"earned_points": "Pontos ganhos:",
"available_points": "Pontos disponíveis:",
"how_to_earn_achievements_points": "Como desbloquear pontos nas conquistas?"
}, },
"hydra_cloud": { "hydra_cloud": {
"subscription_tour_title": "Subscrição Hydra Cloud", "subscription_tour_title": "Subscrição Hydra Cloud",
"subscribe_now": "Subscreve agora", "subscribe_now": "Subscreve agora",
"cloud_achievements": "Gravação de conquistas na nuvem", "cloud_achievements": "Gravação de conquistas na nuvem",
"animated_profile_picture": "Fotos de perfil animadas", "animated_profile_picture": "Fotos de perfil animadas",
"premium_support": "Suporte Premium", "premium_support": "Apoio Premium",
"show_and_compare_achievements": "Mostra e compara as tuas conquistas com as de outros utilizadores", "show_and_compare_achievements": "Mostra e compara as tuas conquistas com as de outros utilizadores",
"animated_profile_banner": "Banner animado no perfil", "animated_profile_banner": "Banner animado no perfil"
"cloud_saving": "Progresso dos jogos na nuvem",
"hydra_cloud_feature_found": "Descubriste uma funcionalidade Hydra Cloud!",
"learn_more": "Saber mais"
} }
} }

View File

@@ -127,12 +127,6 @@
"behavior": "Comportament", "behavior": "Comportament",
"language": "Limbă", "language": "Limbă",
"api_token": "Token API", "api_token": "Token API",
"cancel_button_confirmation_delete_all_sources": "Nu",
"confirm_button_confirmation_delete_all_sources": "Da, șterge totul",
"description_confirmation_delete_all_sources": "Veți șterge toate sursele de descărcare",
"title_confirmation_delete_all_sources": "Ștergeți toate sursele de descărcare",
"removed_download_sources": "Sursele de descărcare au fost eliminate",
"button_delete_all_sources": "Eliminați toate sursele de descărcare",
"enable_real_debrid": "Activează Real-Debrid", "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_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.",
"debrid_invalid_token": "Token API invalid", "debrid_invalid_token": "Token API invalid",

View File

@@ -10,7 +10,7 @@
"hot": "Сейчас популярно", "hot": "Сейчас популярно",
"start_typing": "Начинаю вводить текст...", "start_typing": "Начинаю вводить текст...",
"weekly": "📅 Лучшие игры недели", "weekly": "📅 Лучшие игры недели",
"achievements": "🏆 Игры с достижениями" "achievements": "🏆 Игры, в которых нужно победить"
}, },
"sidebar": { "sidebar": {
"catalogue": "Каталог", "catalogue": "Каталог",
@@ -36,7 +36,7 @@
"downloads": "Загрузки", "downloads": "Загрузки",
"search_results": "Результаты поиска", "search_results": "Результаты поиска",
"settings": "Настройки", "settings": "Настройки",
"version_available_install": "Доступна версия {{version}}. Нажмите здесь для установки.", "version_available_install": "Доступна версия {{version}}. Нажмите здесь для перезапуска и установки.",
"version_available_download": "Доступна версия {{version}}. Нажмите здесь для загрузки." "version_available_download": "Доступна версия {{version}}. Нажмите здесь для загрузки."
}, },
"bottom_panel": { "bottom_panel": {
@@ -44,16 +44,13 @@
"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}} завершено)", "checking_files": "Проверка файлов {{title}}… ({{percentage}} завершено)"
"installing_common_redist": "{{log}}…",
"installation_complete": "Установка завершена",
"installation_complete_message": "Библиотеки успешно установлены"
}, },
"catalogue": { "catalogue": {
"search": "Фильтр…", "search": "Фильтр…",
"developers": "Разработчики", "developers": "Разработчики",
"genres": "Жанры", "genres": "Жанры",
"tags": "Теги", "tags": "Маркеры",
"publishers": "Издательства", "publishers": "Издательства",
"download_sources": "Источники загрузки", "download_sources": "Источники загрузки",
"result_count": "{{resultCount}} результатов", "result_count": "{{resultCount}} результатов",
@@ -181,23 +178,18 @@
"manage_files_description": "Управляйте файлами, которые будут сохраняться и восстанавливаться", "manage_files_description": "Управляйте файлами, которые будут сохраняться и восстанавливаться",
"select_folder": "Выбрать папку", "select_folder": "Выбрать папку",
"backup_from": "Резервная копия от {{date}}", "backup_from": "Резервная копия от {{date}}",
"automatic_backup_from": "Автоматическая резервная копия от {{date}}",
"enable_automatic_cloud_sync": "Включить автоматическую синхронизацию в облаке",
"custom_backup_location_set": "Установлено настраиваемое местоположение резервной копии", "custom_backup_location_set": "Установлено настраиваемое местоположение резервной копии",
"no_directory_selected": "Не выбран каталог", "no_directory_selected": "Не выбран каталог",
"no_write_permission": "Невозможно загрузить в эту директорию. Нажмите здесь, чтобы узнать больше.", "no_write_permission": "Невозможно загрузить в эту директорию. Нажмите здесь, чтобы узнать больше.",
"reset_achievements": "Сброс достижений",
"reset_achievements_description": "Это сбросит все достижения для {{game}}",
"reset_achievements_title": "Вы уверены?", "reset_achievements_title": "Вы уверены?",
"reset_achievements_success": "Достижения успешно сброшены", "reset_achievements_success": "Достижения успешно сброшены",
"reset_achievements_error": "Не удалось сбросить достижения", "reset_achievements_error": "Не удалось сбросить достижения",
"download_error_gofile_quota_exceeded": "Вы превысили месячную квоту Gofile. Пожалуйста, подождите, пока квота не будет восстановлена.", "download_error_gofile_quota_exceeded": "Вы превысили месячную квоту Gofile. Пожалуйста, подождите, пока квота не будет восстановлена.",
"download_error_real_debrid_account_not_authorized": "Ваш аккаунт Real-Debrid не авторизован для осуществления новых загрузок. Пожалуйста, проверьте настройки учетной записи и повторите попытку.", "download_error_real_debrid_account_not_authorized": "Ваш аккаунт Real-Debrid не авторизован для осуществления новых загрузок. Пожалуйста, проверьте настройки учетной записи и повторите попытку.",
"download_error_not_cached_on_real_debrid": "Эта загрузка недоступна на Real-Debrid, и получение статуса загрузки с Real-Debrid пока недоступно.", "download_error_not_cached_in_real_debrid": "Эта загрузка недоступна на Real-Debrid, а опрос статуса загрузки с Real-Debrid пока недоступен.",
"download_error_not_cached_on_torbox": "Эта загрузка недоступна на TorBox, и получить статус загрузки с TorBox пока невозможно.", "download_error_not_cached_in_torbox": "Эта загрузка недоступна на Torbox, и опросить статус загрузки с Torbox пока невозможно.",
"game_added_to_favorites": "Игра добавлена в избранное", "game_added_to_favorites": "Игра добавлена в избранное",
"game_removed_from_favorites": "Игра удалена из избранного", "game_removed_from_favorites": "Игра удалена из избранного"
"automatically_extract_downloaded_files": "Автоматическая распаковка загруженных файлов"
}, },
"activation": { "activation": {
"title": "Активировать Hydra", "title": "Активировать Hydra",
@@ -234,9 +226,7 @@
"seeding": "Раздача", "seeding": "Раздача",
"stop_seeding": "Остановить раздачу", "stop_seeding": "Остановить раздачу",
"resume_seeding": "Продолжить раздачу", "resume_seeding": "Продолжить раздачу",
"options": "Управлять", "options": "Управлять"
"extract": "Распаковать файлы",
"extracting": "Распаковка файлов…"
}, },
"settings": { "settings": {
"downloads_path": "Путь загрузок", "downloads_path": "Путь загрузок",
@@ -275,15 +265,9 @@
"download_source_up_to_date": "Обновлён", "download_source_up_to_date": "Обновлён",
"download_source_errored": "Ошибка", "download_source_errored": "Ошибка",
"sync_download_sources": "Обновить источники", "sync_download_sources": "Обновить источники",
"removed_download_source": "Источник удален", "removed_download_source": "Источник загрузок удален",
"cancel_button_confirmation_delete_all_sources": "Нет", "added_download_source": "Источник загрузок добавлен",
"confirm_button_confirmation_delete_all_sources": "Да, удалить все", "download_sources_synced": "Все источники загрузок синхронизированы",
"description_confirmation_delete_all_sources": "Вы удалите все источники",
"title_confirmation_delete_all_sources": "Удалить все источники",
"removed_download_sources": "Источники удалены",
"button_delete_all_sources": "Удалить все источники",
"added_download_source": "Источник добавлен",
"download_sources_synced": "Все источники обновлены",
"insert_valid_json_url": "Вставьте действительный URL JSON-файла", "insert_valid_json_url": "Вставьте действительный URL JSON-файла",
"found_download_option_zero": "Не найдено вариантов загрузки", "found_download_option_zero": "Не найдено вариантов загрузки",
"found_download_option_one": "Найден {{countFormatted}} вариант загрузки", "found_download_option_one": "Найден {{countFormatted}} вариант загрузки",
@@ -291,7 +275,7 @@
"import": "Импортировать", "import": "Импортировать",
"blocked_users": "Заблокированные пользователи", "blocked_users": "Заблокированные пользователи",
"friends_only": "Только для друзей", "friends_only": "Только для друзей",
"must_be_valid_url": "У источника должен быть правильный URL", "must_be_valid_url": "Источник должен быть действительным URL-адресом.",
"privacy": "Конфиденциальность", "privacy": "Конфиденциальность",
"private": "Частный", "private": "Частный",
"profile_visibility": "Видимость профиля", "profile_visibility": "Видимость профиля",
@@ -338,24 +322,15 @@
"delete_theme_description": "Это приведет к удалению темы {{theme}}", "delete_theme_description": "Это приведет к удалению темы {{theme}}",
"cancel": "Отменить", "cancel": "Отменить",
"appearance": "Внешний вид", "appearance": "Внешний вид",
"enable_torbox": "Включить TorBox", "enable_torbox": "Включить Torbox",
"torbox_description": "TorBox - это ваш премиум-сервис, конкурирующий даже с лучшими серверами на рынке.", "torbox_description": "TorBox - это ваш премиум-сервис, конкурирующий даже с лучшими серверами на рынке.",
"torbox_account_linked": "Аккаунт TorBox привязан", "torbox_account_linked": "Аккаунт TorBox привязан",
"real_debrid_account_linked": "Аккаунт Real-Debrid привязан", "real_debrid_account_linked": "Аккаунт Real-Debrid привязан",
"create_real_debrid_account": "Нажмите здесь, если у вас еще нет аккаунта Real-Debrid",
"create_torbox_account": "Нажмите здесь, если у вас еще нет учетной записи TorBox",
"name_min_length": "Название темы должно содержать не менее 3 символов", "name_min_length": "Название темы должно содержать не менее 3 символов",
"import_theme": "Импортировать тему", "import_theme": "Импортировать тему",
"import_theme_description": "Вы импортируете {{theme}} из магазина тем", "import_theme_description": "Вы импортируете {{theme}} из магазина тем",
"error_importing_theme": "Ошибка при импорте темы", "error_importing_theme": "Ошибка при импорте темы",
"theme_imported": "Тема успешно импортирована", "theme_imported": "Тема успешно импортирована"
"enable_friend_request_notifications": "При получении запроса на добавление в друзья",
"enable_auto_install": "Загружать обновления автоматически",
"common_redist": "Библиотеки",
"common_redist_description": "Для запуска некоторых игр требуются библиотеки. Во избежание проблем рекомендуется установить их.",
"install_common_redist": "Установить",
"installing_common_redist": "Установка…",
"show_download_speed_in_megabytes": "Показать скорость загрузки в мегабайтах в секунду"
}, },
"notifications": { "notifications": {
"download_complete": "Загрузка завершена", "download_complete": "Загрузка завершена",
@@ -366,19 +341,13 @@
"new_update_available": "Доступна новая версия {{version}}", "new_update_available": "Доступна новая версия {{version}}",
"restart_to_install_update": "Перезапустите Hydra для установки обновления", "restart_to_install_update": "Перезапустите Hydra для установки обновления",
"notification_achievement_unlocked_title": "Достижение разблокировано для {{game}}", "notification_achievement_unlocked_title": "Достижение разблокировано для {{game}}",
"notification_achievement_unlocked_body": "были разблокированы {{achievement}} и другие {{count}}", "notification_achievement_unlocked_body": "были разблокированы {{achievement}} и другие {{count}}"
"new_friend_request_title": "Новый запрос на добавление в друзья",
"new_friend_request_description": "Вы получили новый запрос на добавление в друзья",
"extraction_complete": "Распаковка завершена",
"game_extracted": "{{title}} успешно распакован"
}, },
"system_tray": { "system_tray": {
"open": "Открыть Hydra", "open": "Открыть Hydra",
"quit": "Выйти" "quit": "Выйти"
}, },
"game_card": { "game_card": {
"available_one": "Доступный",
"available_other": "Доступный",
"no_downloads": "Нет доступных источников" "no_downloads": "Нет доступных источников"
}, },
"binary_not_found_modal": { "binary_not_found_modal": {
@@ -463,13 +432,11 @@
"uploading_banner": "Загрузка баннера...", "uploading_banner": "Загрузка баннера...",
"background_image_updated": "Фоновое изображение обновлено", "background_image_updated": "Фоновое изображение обновлено",
"stats": "Статистика", "stats": "Статистика",
"achievements": "Достижения",
"games": "Игры", "games": "Игры",
"top_percentile": "Топ {{percentile}}%", "top_percentile": "Топ {{percentile}}%",
"ranking_updated_weekly": "Рейтинг обновляется еженедельно", "ranking_updated_weekly": "Рейтинг обновляется еженедельно",
"playing": "Играет в {{game}}", "playing": "Играет в {{game}}",
"achievements_unlocked": "Достижения разблокированы", "achievements_unlocked": "Достижения разблокированы",
"earned_points": "Заработано очков:",
"show_achievements_on_profile": "Покажите свои достижения в профиле", "show_achievements_on_profile": "Покажите свои достижения в профиле",
"show_points_on_profile": "Показывать заработанные очки в своем профиле" "show_points_on_profile": "Показывать заработанные очки в своем профиле"
}, },
@@ -499,7 +466,6 @@
"animated_profile_banner": "Анимированный баннер профиля", "animated_profile_banner": "Анимированный баннер профиля",
"hydra_cloud": "Hydra Cloud", "hydra_cloud": "Hydra Cloud",
"hydra_cloud_feature_found": "Вы только что открыли для себя функцию Hydra Cloud!", "hydra_cloud_feature_found": "Вы только что открыли для себя функцию Hydra Cloud!",
"learn_more": "Подробнее", "learn_more": "Подробнее"
"debrid_description": "Скачивайте в 4 раза быстрее с Nimbus"
} }
} }

View File

@@ -16,7 +16,7 @@
"catalogue": "Katalog", "catalogue": "Katalog",
"downloads": "İndirilenler", "downloads": "İndirilenler",
"settings": "Ayarlar", "settings": "Ayarlar",
"my_library": "Kütüphane", "my_library": "Kütüphanem",
"downloading_metadata": "{{title}} (Meta verileri indiriliyor…)", "downloading_metadata": "{{title}} (Meta verileri indiriliyor…)",
"paused": "{{title}} (Durduruldu)", "paused": "{{title}} (Durduruldu)",
"downloading": "{{title}} ({{percentage}} - İndiriliyor…)", "downloading": "{{title}} ({{percentage}} - İndiriliyor…)",
@@ -36,18 +36,15 @@
"downloads": "İndirilenler", "downloads": "İndirilenler",
"search_results": "Arama sonuçları", "search_results": "Arama sonuçları",
"settings": "Ayarlar", "settings": "Ayarlar",
"version_available_install": "{{version}} sürümü mevcut. Yüklemek ve yeniden başlatmak için buraya tıklayın.", "version_available_install": "Sürüm {{version}} mevcut. Yüklemek ve yeniden başlatmak için buraya tıklayın.",
"version_available_download": "{{version}} sürümü mevcut. İndirmek için buraya tıklayın." "version_available_download": "Sürüm {{version}} mevcut. İndirmek için buraya tıklayın."
}, },
"bottom_panel": { "bottom_panel": {
"no_downloads_in_progress": "Devam eden indirme yok", "no_downloads_in_progress": "Devam eden indirme yok",
"downloading_metadata": "{{title}} meta verileri indiriliyor…", "downloading_metadata": "{{title}} meta verileri indiriliyor…",
"downloading": "{{title}} indiriliyor… ({{percentage}} tamamlandı) - Tamamlanma: {{eta}} - Hız: {{speed}}", "downloading": "{{title}} indiriliyor… ({{percentage}} tamamlandı) - Tamamlama: {{eta}} - Hız: {{speed}}",
"calculating_eta": "{{title}} indiriliyor… ({{percentage}} tamamlandı) - Kalan süre hesaplanıyor…", "calculating_eta": "{{title}} indiriliyor… ({{percentage}} tamamlandı) - Kalan süre hesaplanıyor…",
"checking_files": "{{title}} dosyaları kontrol ediliyor… ({{percentage}} tamamlandı)", "checking_files": "{{title}} dosyaları kontrol ediliyor… ({{percentage}} tamamlandı)"
"installing_common_redist": "{{log}}…",
"installation_complete": "İndirme tamamlandı",
"installation_complete_message": "Genel bağımlılıklar başarıyla yüklendi."
}, },
"catalogue": { "catalogue": {
"search": "Filtrele…", "search": "Filtrele…",
@@ -119,14 +116,14 @@
"clear": "Temizle", "clear": "Temizle",
"remove_files": "Dosyaları kaldır", "remove_files": "Dosyaları kaldır",
"remove_from_library_title": "Emin misiniz?", "remove_from_library_title": "Emin misiniz?",
"remove_from_library_description": "Bu işlem sonrasında {{game}} oyunu kütüphanenizden kaldıracaktır", "remove_from_library_description": "Bu işlem {{game}} oyununu kütüphanenizden kaldıracaktır",
"options": "Seçenekler", "options": "Seçenekler",
"executable_section_title": "Çalıştırılabilir dosya", "executable_section_title": "Çalıştırılabilir dosya",
"executable_section_description": "\"Oyna\" butonuna tıklandığında çalıştırılacak dosyanın yolu", "executable_section_description": "\"Oyna\" tıklandığında çalıştırılacak dosyanın yolu",
"downloads_secion_title": "İndirmeler", "downloads_secion_title": "İndirmeler",
"downloads_section_description": "Bu oyun için güncellemeleri veya diğer sürümleri kontrol edin", "downloads_section_description": "Bu oyun için güncellemeleri veya diğer sürümleri kontrol edin",
"danger_zone_section_title": "Tehlike bölgesi", "danger_zone_section_title": "Tehlike bölgesi",
"danger_zone_section_description": "Bu oyunu kütüphanenizden kaldırın veya Hydra tarafından indirilen dosyaları silin.", "danger_zone_section_description": "Bu oyunu kütüphanenizden veya Hydra tarafından indirilen dosyaları kaldırın",
"download_in_progress": "İndirme devam ediyor", "download_in_progress": "İndirme devam ediyor",
"download_paused": "İndirme durduruldu", "download_paused": "İndirme durduruldu",
"last_downloaded_option": "Son indirilen seçenek", "last_downloaded_option": "Son indirilen seçenek",
@@ -144,8 +141,8 @@
"executable_path_in_use": "\"{{game}}\" tarafından kullanılan çalıştırılabilir dosya", "executable_path_in_use": "\"{{game}}\" tarafından kullanılan çalıştırılabilir dosya",
"warning": "Uyarı:", "warning": "Uyarı:",
"hydra_needs_to_remain_open": "Bu indirmenin tamamlanması için Hydra açık kalmalıdır. Eğer Hydra kapanırsa, ilerleme kaydedilmez.", "hydra_needs_to_remain_open": "Bu indirmenin tamamlanması için Hydra açık kalmalıdır. Eğer Hydra kapanırsa, ilerleme kaydedilmez.",
"achievements": "Başarımlar", "achievements": "Başarılar",
"achievements_count": "Başarımlar {{unlockedCount}}/{{achievementsCount}}", "achievements_count": "Başarılar {{unlockedCount}}/{{achievementsCount}}",
"cloud_save": "Bulut kaydı", "cloud_save": "Bulut kaydı",
"cloud_save_description": "İlerlemenizi buluta kaydedin ve herhangi bir cihazda oynamaya devam edin", "cloud_save_description": "İlerlemenizi buluta kaydedin ve herhangi bir cihazda oynamaya devam edin",
"backups": "Yedekler", "backups": "Yedekler",
@@ -153,15 +150,15 @@
"delete_backup": "Sil", "delete_backup": "Sil",
"create_backup": "Yeni yedek oluştur", "create_backup": "Yeni yedek oluştur",
"last_backup_date": "{{date}} tarihindeki son yedek", "last_backup_date": "{{date}} tarihindeki son yedek",
"no_backup_preview": "Bu oyun için bir kayıt dosyası bulunamadı", "no_backup_preview": "Bu oyun için kayıtlı oyun bulunamadı",
"restoring_backup": "Yedek geri yükleniyor ({{progress}} tamamlandı)…", "restoring_backup": "Yedek geri yükleniyor ({{progress}} tamamlandı)…",
"uploading_backup": "Yedek yükleniyor…", "uploading_backup": "Yedek yükleniyor…",
"no_backups": "Bu oyun için henüz bir yedek oluşturmadınız", "no_backups": "Bu oyun için henüz bir yedek oluşturmadınız",
"backup_uploaded": "Yedek yüklendi", "backup_uploaded": "Yedek yüklendi",
"backup_deleted": "Yedek silindi", "backup_deleted": "Yedek silindi",
"backup_restored": "Yedek geri yüklendi", "backup_restored": "Yedek geri yüklendi",
"see_all_achievements": "Tüm başarımları gör", "see_all_achievements": "Tüm başarıları gör",
"sign_in_to_see_achievements": "Başarımları görmek için oturum açın", "sign_in_to_see_achievements": "Başarıları görmek için giriş yapın",
"mapping_method_automatic": "Otomatik", "mapping_method_automatic": "Otomatik",
"mapping_method_manual": "Manuel", "mapping_method_manual": "Manuel",
"mapping_method_label": "Eşleme yöntemi", "mapping_method_label": "Eşleme yöntemi",
@@ -172,38 +169,29 @@
"wine_prefix": "Wine Prefix", "wine_prefix": "Wine Prefix",
"wine_prefix_description": "Bu oyunu çalıştırmak için kullanılan Wine Prefix", "wine_prefix_description": "Bu oyunu çalıştırmak için kullanılan Wine Prefix",
"launch_options": "Başlatma Seçenekleri", "launch_options": "Başlatma Seçenekleri",
"launch_options_description": "İleri düzey kullanıcılar, başlatma seçeneklerine parametreler girebilir (deneysel özellik)", "launch_options_description": "İleri düzey kullanıcılar, başlatma seçeneklerine değişiklikler girebilir (deneysel özellik)",
"launch_options_placeholder": "Belirtilen bir parametre yok", "launch_options_placeholder": "Belirtilen bir parametre yok",
"no_download_option_info": "Bilgi mevcut değil", "no_download_option_info": "Bilgi mevcut değil",
"backup_deletion_failed": "Yedek silinemedi", "backup_deletion_failed": "Yedek silinemedi",
"max_number_of_artifacts_reached": "Bu oyun için maksimum yedek sayısına ulaşıldı", "max_number_of_artifacts_reached": "Bu oyun için maksimum yedek sayısına ulaşıldı",
"achievements_not_sync": "Başarımlarınızı senkronize etmeyi öğrenin", "achievements_not_sync": "Başarılarınızı senkronize etmeyi öğrenin",
"manage_files_description": "Hangi dosyaların yedeklenip geri yükleneceğini yönetin", "manage_files_description": "Hangi dosyaların yedeklenip geri yükleneceğini yönetin",
"select_folder": "Klasör seç", "select_folder": "Klasör seç",
"backup_from": "{{date}} tarihinden yedek", "backup_from": "{{date}} tarihinden yedek",
"automatic_backup_from": "{{date}} tarihinden otomatik kayıt",
"enable_automatic_cloud_sync": "Otomatik bulut kaydı senkronizasyonunu aktifleştir",
"custom_backup_location_set": "Özel yedekleme konumu ayarlandı", "custom_backup_location_set": "Özel yedekleme konumu ayarlandı",
"no_directory_selected": "Bir dizin seçilmedi", "no_directory_selected": "Bir dizin seçilmedi",
"no_write_permission": "Bu dizine indirme yapılamaz. Daha fazla bilgi için buraya tıklayın.", "no_write_permission": "Bu dizine indirme yapılamaz. Daha fazla bilgi için buraya tıklayın.",
"reset_achievements": "Başarımları sıfırla", "reset_achievements": "Başarıları sıfırla",
"reset_achievements_description": "Bu işlem {{game}} için tüm başarımları sıfırlar", "reset_achievements_description": "Bu işlem {{game}} için tüm başarıları sıfırlar",
"reset_achievements_title": "Emin misiniz?", "reset_achievements_title": "Emin misiniz?",
"reset_achievements_success": "Başarımlar başarıyla sıfırlandı", "reset_achievements_success": "Başarılar başarıyla sıfırlandı",
"reset_achievements_error": "Başarımlar sıfırlanamadı", "reset_achievements_error": "Başarılar sıfırlanamadı"
"download_error_gofile_quota_exceeded": "Gofile aylık kotanızı doldurdunuz. Kotanın yenilenmesini bekleyin.",
"download_error_real_debrid_account_not_authorized": "Real-Debrid hesabınız yeni indirme işlemleri yapmak için yetkilendirilmemiş. Lütfen hesap ayarlarınızı kontrol edip tekrar deneyin.",
"download_error_not_cached_on_real_debrid": "Bu indirme Real-Debrid üzerinde mevcut değil ve Real-Debrid'den indirme durumu henüz sorgulanamıyor.",
"download_error_not_cached_on_torbox": "Bu indirme TorBox'ta mevcut değil ve TorBox'tan indirme durumu henüz sorgulanamıyor.",
"game_removed_from_favorites": "Oyun favorilerden silindi",
"game_added_to_favorites": "Oyun favorilere eklendi",
"automatically_extract_downloaded_files": "Yüklenmiş dosyaları otomatik olarak çıkart"
}, },
"activation": { "activation": {
"title": "Hydra'yı Aktive Et", "title": "Hydra'yı Aktive Et",
"installation_id": "Kurulum Kimliği:", "installation_id": "Kurulum Kimliği:",
"enter_activation_code": "Aktivasyon kodunuzu girin", "enter_activation_code": "Aktivasyon kodunuzu girin",
"message": "Bunu nasıl edineceğini bilmiyorsan, buna sahip olmamalısın.", "message": "Bunu nereden soracağınızı bilmiyorsanız, bu sizin için olmamalı.",
"activate": "Aktive Et", "activate": "Aktive Et",
"loading": "Yükleniyor…" "loading": "Yükleniyor…"
}, },
@@ -218,7 +206,7 @@
"cancel": "İptal Et", "cancel": "İptal Et",
"filter": "İndirilen oyunları filtrele", "filter": "İndirilen oyunları filtrele",
"remove": "Kaldır", "remove": "Kaldır",
"downloading_metadata": "Meta verileri indiriliyor…", "downloading_metadata": "Metadata indiriliyor…",
"deleting": "Yükleyici siliniyor…", "deleting": "Yükleyici siliniyor…",
"delete": "Yükleyiciyi kaldır", "delete": "Yükleyiciyi kaldır",
"delete_modal_title": "Emin misiniz?", "delete_modal_title": "Emin misiniz?",
@@ -234,9 +222,7 @@
"seeding": "Paylaşılıyor", "seeding": "Paylaşılıyor",
"stop_seeding": "Paylaşımı durdur", "stop_seeding": "Paylaşımı durdur",
"resume_seeding": "Paylaşımı sürdür", "resume_seeding": "Paylaşımı sürdür",
"options": "Yönet", "options": "Yönet"
"extract": "Dosyaları çıkart",
"extracting": "Dosyalar çıkartılıyor…"
}, },
"settings": { "settings": {
"downloads_path": "İndirme yolu", "downloads_path": "İndirme yolu",
@@ -245,7 +231,7 @@
"enable_download_notifications": "Bir indirme tamamlandığında", "enable_download_notifications": "Bir indirme tamamlandığında",
"enable_repack_list_notifications": "Yeni bir repack eklendiğinde", "enable_repack_list_notifications": "Yeni bir repack eklendiğinde",
"real_debrid_api_token_label": "Real-Debrid API anahtarı", "real_debrid_api_token_label": "Real-Debrid API anahtarı",
"quit_app_instead_hiding": "Hydra'yı kapatınca sistem tepsisine gitmesin", "quit_app_instead_hiding": "Hydra'yı kapatırken gizlemeyin",
"launch_with_system": "Hydra'yı sistem başlatıldığında çalıştır", "launch_with_system": "Hydra'yı sistem başlatıldığında çalıştır",
"general": "Genel", "general": "Genel",
"behavior": "Davranış", "behavior": "Davranış",
@@ -264,12 +250,6 @@
"validate_download_source": "Doğrula", "validate_download_source": "Doğrula",
"remove_download_source": "Kaldır", "remove_download_source": "Kaldır",
"add_download_source": "Kaynak ekle", "add_download_source": "Kaynak ekle",
"cancel_button_confirmation_delete_all_sources": "Hayır",
"confirm_button_confirmation_delete_all_sources": "Evet, her şeyi sil",
"description_confirmation_delete_all_sources": "Tüm indirme kaynaklarını sileceksiniz",
"title_confirmation_delete_all_sources": "Tüm indirme kaynaklarını sil",
"removed_download_sources": "Yazı tipleri kaldırıldı",
"button_delete_all_sources": "Tüm indirme kaynaklarını kaldır",
"download_count_zero": "İndirme seçeneği yok", "download_count_zero": "İndirme seçeneği yok",
"download_count_one": "{{countFormatted}} indirme seçeneği", "download_count_one": "{{countFormatted}} indirme seçeneği",
"download_count_other": "{{countFormatted}} indirme seçeneği", "download_count_other": "{{countFormatted}} indirme seçeneği",
@@ -297,64 +277,11 @@
"must_be_valid_url": "Kaynak geçerli bir URL olmalıdır", "must_be_valid_url": "Kaynak geçerli bir URL olmalıdır",
"blocked_users": "Engellenen kullanıcılar", "blocked_users": "Engellenen kullanıcılar",
"user_unblocked": "Kullanıcının engeli kaldırıldı", "user_unblocked": "Kullanıcının engeli kaldırıldı",
"enable_achievement_notifications": "Bir başarım kilidi açıldığında", "enable_achievement_notifications": "Bir başarı kilidi açıldığında",
"launch_minimized": "Hydra'yı küçültülmüş başlat", "launch_minimized": "Hydra'yı küçültülmüş başlat",
"disable_nsfw_alert": "NSFW uyarısını devre dışı bırak", "disable_nsfw_alert": "NSFW uyarısını devre dışı bırak",
"seed_after_download_complete": "İndirme tamamlandıktan sonra paylaş", "seed_after_download_complete": "İndirme tamamlandıktan sonra paylaş",
"show_hidden_achievement_description": "Gizli başarımıklamalarını kilitlenmeden önce göster", "show_hidden_achievement_description": "Gizli başarııklamalarını kilitlenmeden önce göster"
"account": "Hesap",
"no_users_blocked": "Hiçbir kullanıcıyı engellemediniz",
"subscription_active_until": "Hydra Cloud'unuz {{date}} tarihine kadar aktif",
"manage_subscription": "Aboneliği yönet",
"update_email": "E-posta'yı güncelle",
"update_password": "Şifreyi güncelle",
"current_email": "Aktif e-posta'nız",
"no_email_account": "Henüz ayarlanmış bir e-postanız yok",
"account_data_updated_successfully": "Hesap bilgileri başarıyla güncellendi",
"renew_subscription": "Hydra Cloud'u yenile",
"subscription_expired_at": "Aboneliğiniz {{date}} tarihinde sona erdi",
"no_subscription": "Hydra'yı en iyi şekilde deneyimleyin",
"become_subscriber": "Hydra Cloud'lu ol",
"subscription_renew_cancelled": "Otomatik yenileme devre dışı",
"subscription_renews_on": "Aboneliğiniz {{date}} tarihinde yenilenecek",
"bill_sent_until": "Bir sonraki faturanız bu tarihe kadar gönderilecek",
"no_themes": "Henüz bir temanız yok gibi görünüyor, ama endişelenmeyin, ilk şaheserinizi oluşturmak için buraya tıklayın.",
"editor_tab_code": "Kod",
"editor_tab_info": "Bilgi",
"editor_tab_save": "Kaydet",
"web_store": "İnternet mağazası",
"clear_themes": "Temizle",
"create_theme": "Oluştur",
"create_theme_modal_title": "Tema oluştur",
"create_theme_modal_description": "Hydra'nın görünümünü özelleştirmek için yeni bir tema oluştur",
"theme_name": "İsim",
"insert_theme_name": "Tema ismini gir",
"set_theme": "Temayı seç",
"unset_theme": "Tema seçimini kaldır",
"delete_theme": "Temayı sil",
"edit_theme": "Temayı düzenle",
"delete_all_themes": "Tüm temaları sil",
"delete_all_themes_description": "Bu tüm temalarınızı silecektir",
"delete_theme_description": "Bu {{theme}} temasını silecektir",
"cancel": "İptal",
"appearance": "Görünüm",
"enable_torbox": "TorBox'u etkinleştir",
"torbox_description": "TorBox, piyasadaki en iyi sunucularla bile rekabet edebilen premium seedbox hizmetinizdir.",
"torbox_account_linked": "TorBox hesabı bağlandı",
"create_real_debrid_account": "Henüz bir Real-Debrid hesabınız yoksa buraya tıklayın",
"create_torbox_account": "Henüz bir TorBox hesabınız yoksa buraya tıklayın",
"real_debrid_account_linked": "Real-Debrid hesabı bağlandı",
"name_min_length": "Tema ismi en az 3 karakter uzunluğunda olmalıdır",
"import_theme": "Temayı içe aktar",
"import_theme_description": "{{theme}} teması, tema mağazasından içeri aktarılacak",
"error_importing_theme": "Temayı içe aktarmada bir sorun oluştu",
"theme_imported": "Tema başarıyla içe aktarıldı",
"enable_friend_request_notifications": "Bir arkadaşlık isteği alındığında",
"enable_auto_install": "Güncellemeleri otomatik yükle",
"common_redist": "Ortak bağımlılıklar",
"common_redist_description": "Bazı oyunların çalışabilmesi için genel bağımlılıklar gereklidir. Sorun yaşamamak için bunların yüklenmesi önerilir.",
"install_common_redist": "Yükle",
"installing_common_redist": "Yükleniyor…"
}, },
"notifications": { "notifications": {
"download_complete": "İndirme tamamlandı", "download_complete": "İndirme tamamlandı",
@@ -362,23 +289,17 @@
"repack_list_updated": "Repack listesi güncellendi", "repack_list_updated": "Repack listesi güncellendi",
"repack_count_one": "{{count}} repack eklendi", "repack_count_one": "{{count}} repack eklendi",
"repack_count_other": "{{count}} repack eklendi", "repack_count_other": "{{count}} repack eklendi",
"new_update_available": "{{version}} sürümü mevcut", "new_update_available": "Sürüm {{version}} mevcut",
"restart_to_install_update": "Güncellemeyi yüklemek için Hydra'yı yeniden başlatın", "restart_to_install_update": "Güncellemeyi yüklemek için Hydra'yı yeniden başlatın",
"notification_achievement_unlocked_title": "{{game}} için başarım kilidi açıldı", "notification_achievement_unlocked_title": "{{game}} için başarı kilidi açıldı",
"notification_achievement_unlocked_body": "{{achievement}} ve diğer {{count}} başarımıldı", "notification_achievement_unlocked_body": "{{achievement}} ve diğer {{count}} başarılarıldı"
"new_friend_request_description": "Yeni bir arkadaşlık isteğin var",
"new_friend_request_title": "Yeni arkadaşlık isteği",
"extraction_complete": ıkartma tamamlandı",
"game_extracted": "{{title}} başarıyla çıkartıldı"
}, },
"system_tray": { "system_tray": {
"open": "Hydra'yı Aç", "open": "Hydra'yı Aç",
"quit": ık" "quit": ık"
}, },
"game_card": { "game_card": {
"no_downloads": "İndirilebilir içerik bulunmuyor", "no_downloads": "İndirilebilir içerik bulunmuyor"
"available_one": "Mevcut",
"available_other": "Mevcut"
}, },
"binary_not_found_modal": { "binary_not_found_modal": {
"title": "Programlar Yüklü Değil", "title": "Programlar Yüklü Değil",
@@ -411,7 +332,7 @@
"successfully_signed_out": "Başarıyla çıkış yapıldı", "successfully_signed_out": "Başarıyla çıkış yapıldı",
"sign_out": ıkış yap", "sign_out": ıkış yap",
"playing_for": "{{amount}} oynanıyor", "playing_for": "{{amount}} oynanıyor",
"sign_out_modal_text": "Kütüphaneniz mevcut hesabınıza bağlı. Oturumu kapattığınızda kütüphaneniz görünür olmayacak ve herhangi bir ilerleme kaydedilmeyecek. Oturumu kapatmaya devam etmek istiyor musunuz?", "sign_out_modal_text": "Kütüphaneniz mevcut hesabınıza bağlı. Çıkış yaptığınızda kütüphaneniz görünür olmayacak ve herhangi bir ilerleme kaydedilmeyecek. Çıkışa devam etmek istiyor musunuz?",
"add_friends": "Arkadaş Ekle", "add_friends": "Arkadaş Ekle",
"add": "Ekle", "add": "Ekle",
"friend_code": "Arkadaş kodu", "friend_code": "Arkadaş kodu",
@@ -462,39 +383,39 @@
"uploading_banner": "Afiş yükleniyor…", "uploading_banner": "Afiş yükleniyor…",
"background_image_updated": "Arka plan görüntüsü güncellendi", "background_image_updated": "Arka plan görüntüsü güncellendi",
"stats": "İstatistikler", "stats": "İstatistikler",
"achievements": "Başarımlar", "achievements": "Başarılar",
"games": "Oyunlar", "games": "Oyunlar",
"top_percentile": "En üst {{percentile}}%", "top_percentile": "En üst {{percentile}}%",
"ranking_updated_weekly": "Sıralama haftalık olarak güncellenir", "ranking_updated_weekly": "Sıralama haftalık olarak güncellenir",
"playing": "{{game}} oynanıyor", "playing": "{{game}} oynanıyor",
"achievements_unlocked": "Başarımlar açıldı", "achievements_unlocked": "Başarılar açıldı",
"earned_points": "Kazanılan puanlar", "earned_points": "Kazanılan puanlar",
"show_achievements_on_profile": "Başarımlarınızı profilinizde gösterin", "show_achievements_on_profile": "Başarılarınızı profilinizde gösterin",
"show_points_on_profile": "Kazandığınız puanları profilinizde gösterin" "show_points_on_profile": "Kazandığınız puanları profilinizde gösterin"
}, },
"achievement": { "achievement": {
"achievement_unlocked": "Başarımıldı", "achievement_unlocked": "Başarııldı",
"user_achievements": "{{displayName}} oyununun Başarımları", "user_achievements": "{{displayName}}'in Başarıları",
"your_achievements": "Başarımlarınız", "your_achievements": "Başarılarınız",
"unlocked_at": "Açılma zamanı: {{date}}", "unlocked_at": "Açılma zamanı: {{date}}",
"subscription_needed": "Bu içeriği görmek için bir Hydra Cloud aboneliği gereklidir", "subscription_needed": "Bu içeriği görmek için bir Hydra Cloud aboneliği gereklidir",
"new_achievements_unlocked": "{{gameCount}} oyundan {{achievementCount}} yeni başarımıldı", "new_achievements_unlocked": "{{gameCount}} oyundan {{achievementCount}} yeni başarııldı",
"achievement_progress": "{{unlockedCount}}/{{totalCount}} başarım", "achievement_progress": "{{unlockedCount}}/{{totalCount}} başarı",
"achievements_unlocked_for_game": "{{gameTitle}} oyunu için {{achievementCount}} yeni başarımıldı", "achievements_unlocked_for_game": "{{gameTitle}} oyunu için {{achievementCount}} yeni başarııldı",
"hidden_achievement_tooltip": "Bu gizli bir başarımdır", "hidden_achievement_tooltip": "Bu gizli bir başarıdır",
"achievement_earn_points": "Bu başarım ile {{points}} puan kazanın", "achievement_earn_points": "Bu başarı ile {{points}} puan kazanın",
"earned_points": "Kazanılan puanlar:", "earned_points": "Kazanılan puanlar:",
"available_points": "Mevcut puanlar:", "available_points": "Mevcut puanlar:",
"how_to_earn_achievements_points": "Başarım puanları nasıl kazanılır?" "how_to_earn_achievements_points": "Başarı puanları nasıl kazanılır?"
}, },
"hydra_cloud": { "hydra_cloud": {
"subscription_tour_title": "Hydra Cloud Aboneliği", "subscription_tour_title": "Hydra Cloud Aboneliği",
"subscribe_now": "Şimdi abone olun", "subscribe_now": "Şimdi abone olun",
"cloud_saving": "Bulut kaydetme", "cloud_saving": "Bulut kaydetme",
"cloud_achievements": "Başarımlarınızı buluta kaydedin", "cloud_achievements": "Başarılarınızı buluta kaydedin",
"animated_profile_picture": "Animasyonlu profil resimleri", "animated_profile_picture": "Animasyonlu profil resimleri",
"premium_support": "Premium Destek", "premium_support": "Premium Destek",
"show_and_compare_achievements": "Başarımlarınızı diğer kullanıcılarla karşılaştırın ve gösterin", "show_and_compare_achievements": "Başarılarınızı diğer kullanıcılarla karşılaştırın ve gösterin",
"animated_profile_banner": "Animasyonlu profil afişi", "animated_profile_banner": "Animasyonlu profil afişi",
"hydra_cloud": "Hydra Cloud", "hydra_cloud": "Hydra Cloud",
"hydra_cloud_feature_found": "Bir Hydra Cloud özelliği keşfettiniz!", "hydra_cloud_feature_found": "Bir Hydra Cloud özelliği keşfettiniz!",

View File

@@ -176,12 +176,6 @@
"import": "Імпортувати", "import": "Імпортувати",
"insert_valid_json_url": "Вставте дійсний URL JSON-файлу", "insert_valid_json_url": "Вставте дійсний URL JSON-файлу",
"language": "Мова", "language": "Мова",
"cancel_button_confirmation_delete_all_sources": "немає",
"confirm_button_confirmation_delete_all_sources": "Так, видалити все",
"description_confirmation_delete_all_sources": "Ви видалите всі джерела завантаження",
"title_confirmation_delete_all_sources": "Видалити всі джерела завантаження",
"removed_download_sources": "Джерела завантажень видалено",
"button_delete_all_sources": "Видаліть усі джерела завантаження",
"api_token": "API-токен", "api_token": "API-токен",
"debrid_api_token_hint": "API токен можливо отримати <0>тут</0>", "debrid_api_token_hint": "API токен можливо отримати <0>тут</0>",
"real_debrid_api_token_label": "Real-Debrid API-токен", "real_debrid_api_token_label": "Real-Debrid API-токен",

View File

@@ -226,12 +226,6 @@
"download_sources_description": "Hydra 将从这些源获取下载链接。源 URL 必须是直接链接到包含下载链接的 .json 文件。", "download_sources_description": "Hydra 将从这些源获取下载链接。源 URL 必须是直接链接到包含下载链接的 .json 文件。",
"validate_download_source": "验证", "validate_download_source": "验证",
"remove_download_source": "移除", "remove_download_source": "移除",
"cancel_button_confirmation_delete_all_sources": "不",
"confirm_button_confirmation_delete_all_sources": "是的,删除所有内容",
"description_confirmation_delete_all_sources": "您将删除所有下载源",
"title_confirmation_delete_all_sources": "删除所有下载源",
"removed_download_sources": "已删除字体",
"button_delete_all_sources": "删除所有下载源",
"add_download_source": "添加源", "add_download_source": "添加源",
"download_count_zero": "列表中无下载", "download_count_zero": "列表中无下载",
"download_count_one": "列表中有 {{countFormatted}} 个下载", "download_count_one": "列表中有 {{countFormatted}} 个下载",

View File

@@ -12,9 +12,10 @@ export const levelDatabasePath = path.join(
`hydra-db${isStaging ? "-staging" : ""}` `hydra-db${isStaging ? "-staging" : ""}`
); );
export const commonRedistPath = path.join( export const databaseDirectory = path.join(app.getPath("appData"), "hydra");
app.getPath("userData"), export const databasePath = path.join(
"CommonRedist" databaseDirectory,
isStaging ? "hydra_test.db" : "hydra.db"
); );
export const logsPath = path.join(app.getPath("userData"), "logs"); export const logsPath = path.join(app.getPath("userData"), "logs");
@@ -30,5 +31,3 @@ export const achievementSoundPath = app.isPackaged
export const backupsPath = path.join(app.getPath("userData"), "Backups"); export const backupsPath = path.join(app.getPath("userData"), "Backups");
export const appVersion = app.getVersion() + (isStaging ? "-staging" : ""); export const appVersion = app.getVersion() + (isStaging ? "-staging" : "");
export const MAIN_LOOP_INTERVAL = 1500;

View File

@@ -4,15 +4,11 @@ import updater from "electron-updater";
const { autoUpdater } = updater; const { autoUpdater } = updater;
export const restartAndInstallUpdate = () => { const restartAndInstallUpdate = async (_event: Electron.IpcMainInvokeEvent) => {
autoUpdater.removeAllListeners(); autoUpdater.removeAllListeners();
if (app.isPackaged) { if (app.isPackaged) {
autoUpdater.quitAndInstall(false); autoUpdater.quitAndInstall(false);
} }
}; };
const restartAndInstallUpdateEvent = async ( registerEvent("restartAndInstallUpdate", restartAndInstallUpdate);
_event: Electron.IpcMainInvokeEvent
) => restartAndInstallUpdate();
registerEvent("restartAndInstallUpdate", restartAndInstallUpdateEvent);

View File

@@ -1,8 +1,44 @@
import { CloudSync } from "@main/services"; import { HydraApi, logger, Ludusavi, WindowManager } from "@main/services";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import fs from "node:fs";
import path from "node:path";
import * as tar from "tar";
import crypto from "node:crypto";
import type { GameShop } from "@types"; import type { GameShop } from "@types";
import i18next, { t } from "i18next"; import axios from "axios";
import { formatDate } from "date-fns"; import os from "node:os";
import { backupsPath } from "@main/constants";
import { app } from "electron";
import { normalizePath } from "@main/helpers";
import { gamesSublevel, levelKeys } from "@main/level";
const bundleBackup = async (
shop: GameShop,
objectId: string,
winePrefix: string | null
) => {
const backupPath = path.join(backupsPath, `${shop}-${objectId}`);
// Remove existing backup
if (fs.existsSync(backupPath)) {
fs.rmSync(backupPath, { recursive: true });
}
await Ludusavi.backupGame(shop, objectId, backupPath, winePrefix);
const tarLocation = path.join(backupsPath, `${crypto.randomUUID()}.tar`);
await tar.create(
{
gzip: false,
file: tarLocation,
cwd: backupPath,
},
["."]
);
return tarLocation;
};
const uploadSaveGame = async ( const uploadSaveGame = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
@@ -10,17 +46,61 @@ const uploadSaveGame = async (
shop: GameShop, shop: GameShop,
downloadOptionTitle: string | null downloadOptionTitle: string | null
) => { ) => {
const { language } = i18next; const game = await gamesSublevel.get(levelKeys.game(shop, objectId));
return CloudSync.uploadSaveGame( const bundleLocation = await bundleBackup(
objectId,
shop, shop,
downloadOptionTitle, objectId,
t("backup_from", { game?.winePrefixPath ?? null
ns: "game_details",
date: formatDate(new Date(), language),
})
); );
fs.stat(bundleLocation, async (err, stat) => {
if (err) {
logger.error("Failed to get zip file stats", err);
throw err;
}
const { uploadUrl } = await HydraApi.post<{
id: string;
uploadUrl: string;
}>("/profile/games/artifacts", {
artifactLengthInBytes: stat.size,
shop,
objectId,
hostname: os.hostname(),
homeDir: normalizePath(app.getPath("home")),
downloadOptionTitle,
platform: os.platform(),
});
fs.readFile(bundleLocation, async (err, fileBuffer) => {
if (err) {
logger.error("Failed to read zip file", err);
throw err;
}
await axios.put(uploadUrl, fileBuffer, {
headers: {
"Content-Type": "application/tar",
},
onUploadProgress: (progressEvent) => {
logger.log(progressEvent);
},
});
WindowManager.mainWindow?.webContents.send(
`on-upload-complete-${objectId}-${shop}`,
true
);
fs.rm(bundleLocation, (err) => {
if (err) {
logger.error("Failed to remove tar file", err);
throw err;
}
});
});
});
}; };
registerEvent("uploadSaveGame", uploadSaveGame); registerEvent("uploadSaveGame", uploadSaveGame);

View File

@@ -1,13 +0,0 @@
import { HydraApi } from "@main/services";
import { registerEvent } from "../register-event";
const createDownloadSources = async (
_event: Electron.IpcMainInvokeEvent,
urls: string[]
) => {
await HydraApi.post("/profile/download-sources", {
urls,
});
};
registerEvent("createDownloadSources", createDownloadSources);

View File

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

View File

@@ -1,18 +0,0 @@
import { HydraApi } from "@main/services";
import { registerEvent } from "../register-event";
const removeDownloadSource = async (
_event: Electron.IpcMainInvokeEvent,
url?: string,
removeAll = false
) => {
const params = new URLSearchParams({
all: removeAll.toString(),
});
if (url) params.set("url", url);
return HydraApi.delete(`/profile/download-sources?${params.toString()}`);
};
registerEvent("removeDownloadSource", removeDownloadSource);

View File

@@ -20,7 +20,6 @@ import "./library/close-game";
import "./library/delete-game-folder"; import "./library/delete-game-folder";
import "./library/get-game-by-object-id"; import "./library/get-game-by-object-id";
import "./library/get-library"; import "./library/get-library";
import "./library/extract-game-download";
import "./library/open-game"; import "./library/open-game";
import "./library/open-game-executable-path"; import "./library/open-game-executable-path";
import "./library/open-game-installer"; import "./library/open-game-installer";
@@ -32,22 +31,17 @@ import "./library/remove-game";
import "./library/remove-game-from-library"; import "./library/remove-game-from-library";
import "./library/select-game-wine-prefix"; import "./library/select-game-wine-prefix";
import "./library/reset-game-achievements"; import "./library/reset-game-achievements";
import "./library/toggle-automatic-cloud-sync";
import "./misc/open-checkout"; import "./misc/open-checkout";
import "./misc/open-external"; import "./misc/open-external";
import "./misc/show-open-dialog"; import "./misc/show-open-dialog";
import "./misc/get-features"; import "./misc/get-features";
import "./misc/show-item-in-folder"; import "./misc/show-item-in-folder";
import "./misc/get-badges";
import "./misc/install-common-redist";
import "./misc/can-install-common-redist";
import "./torrenting/cancel-game-download"; import "./torrenting/cancel-game-download";
import "./torrenting/pause-game-download"; import "./torrenting/pause-game-download";
import "./torrenting/resume-game-download"; import "./torrenting/resume-game-download";
import "./torrenting/start-game-download"; import "./torrenting/start-game-download";
import "./torrenting/pause-game-seed"; import "./torrenting/pause-game-seed";
import "./torrenting/resume-game-seed"; import "./torrenting/resume-game-seed";
import "./torrenting/check-debrid-availability";
import "./user-preferences/get-user-preferences"; import "./user-preferences/get-user-preferences";
import "./user-preferences/update-user-preferences"; import "./user-preferences/update-user-preferences";
import "./user-preferences/auto-launch"; import "./user-preferences/auto-launch";
@@ -64,7 +58,6 @@ import "./user/get-blocked-users";
import "./user/block-user"; import "./user/block-user";
import "./user/unblock-user"; import "./user/unblock-user";
import "./user/get-user-friends"; import "./user/get-user-friends";
import "./user/get-auth";
import "./user/get-user-stats"; import "./user/get-user-stats";
import "./user/report-user"; import "./user/report-user";
import "./user/get-unlocked-achievements"; import "./user/get-unlocked-achievements";
@@ -94,9 +87,6 @@ import "./themes/get-custom-theme-by-id";
import "./themes/get-active-custom-theme"; import "./themes/get-active-custom-theme";
import "./themes/close-editor-window"; import "./themes/close-editor-window";
import "./themes/toggle-custom-theme"; import "./themes/toggle-custom-theme";
import "./download-sources/create-download-sources";
import "./download-sources/remove-download-source";
import "./download-sources/get-download-sources";
import { isPortableVersion } from "@main/helpers"; import { isPortableVersion } from "@main/helpers";
ipcMain.handle("ping", () => "pong"); ipcMain.handle("ping", () => "pong");

View File

@@ -13,42 +13,35 @@ const deleteGameFolder = async (
objectId: string objectId: string
): Promise<void> => { ): Promise<void> => {
const downloadKey = levelKeys.game(shop, objectId); const downloadKey = levelKeys.game(shop, objectId);
const download = await downloadsSublevel.get(downloadKey); const download = await downloadsSublevel.get(downloadKey);
if (!download?.folderName) return; if (!download) return;
const folderPath = path.join( if (download.folderName) {
download.downloadPath ?? (await getDownloadsPath()), const folderPath = path.join(
download.folderName download.downloadPath ?? (await getDownloadsPath()),
); download.folderName
);
const metaPath = `${folderPath}.meta`; if (fs.existsSync(folderPath)) {
const deleteFile = async (filePath: string, isDirectory = false) => {
if (fs.existsSync(filePath)) {
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {
fs.rm( fs.rm(
filePath, folderPath,
{ { recursive: true, force: true, maxRetries: 5, retryDelay: 200 },
recursive: isDirectory,
force: true,
maxRetries: 5,
retryDelay: 200,
},
(error) => { (error) => {
if (error) { if (error) {
logger.error(error); logger.error(error);
reject(); reject();
} }
resolve(); resolve();
} }
); );
}); });
} }
}; }
await deleteFile(folderPath, true);
await deleteFile(metaPath);
await downloadsSublevel.del(downloadKey); await downloadsSublevel.del(downloadKey);
}; };

View File

@@ -1,46 +0,0 @@
import { registerEvent } from "../register-event";
import { GameShop } from "@types";
import path from "node:path";
import { GameFilesManager } from "@main/services";
import { downloadsSublevel, gamesSublevel, levelKeys } from "@main/level";
import { FILE_EXTENSIONS_TO_EXTRACT } from "@shared";
const extractGameDownload = async (
_event: Electron.IpcMainInvokeEvent,
shop: GameShop,
objectId: string
): Promise<boolean> => {
const gameKey = levelKeys.game(shop, objectId);
const [download, game] = await Promise.all([
downloadsSublevel.get(gameKey),
gamesSublevel.get(gameKey),
]);
if (!download || !game) return false;
await downloadsSublevel.put(gameKey, {
...download,
extracting: true,
});
const gameFilesManager = new GameFilesManager(shop, objectId);
if (
FILE_EXTENSIONS_TO_EXTRACT.some((ext) => download.folderName?.endsWith(ext))
) {
gameFilesManager.extractDownloadedFile();
} else {
gameFilesManager
.extractFilesInDirectory(
path.join(download.downloadPath, download.folderName!)
)
.then(() => {
gameFilesManager.setExtractionComplete(false);
});
}
return true;
};
registerEvent("extractGameDownload", extractGameDownload);

View File

@@ -1,23 +0,0 @@
import { registerEvent } from "../register-event";
import { levelKeys, gamesSublevel } from "@main/level";
import type { GameShop } from "@types";
const toggleAutomaticCloudSync = async (
_event: Electron.IpcMainInvokeEvent,
shop: GameShop,
objectId: string,
automaticCloudSync: boolean
) => {
const gameKey = levelKeys.game(shop, objectId);
const game = await gamesSublevel.get(gameKey);
if (!game) return;
await gamesSublevel.put(gameKey, {
...game,
automaticCloudSync,
});
};
registerEvent("toggleAutomaticCloudSync", toggleAutomaticCloudSync);

View File

@@ -21,8 +21,6 @@ const updateExecutablePath = async (
await gamesSublevel.put(gameKey, { await gamesSublevel.put(gameKey, {
...game, ...game,
executablePath: parsedPath, executablePath: parsedPath,
automaticCloudSync:
executablePath === null ? false : game.automaticCloudSync,
}); });
}; };

View File

@@ -1,7 +0,0 @@
import { registerEvent } from "../register-event";
import { CommonRedistManager } from "@main/services/common-redist-manager";
const canInstallCommonRedist = async (_event: Electron.IpcMainInvokeEvent) =>
CommonRedistManager.canInstallCommonRedist();
registerEvent("canInstallCommonRedist", canInstallCommonRedist);

View File

@@ -1,22 +0,0 @@
import { Badge } from "@types";
import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services";
import { db, levelKeys } from "@main/level";
const getBadges = async (_event: Electron.IpcMainInvokeEvent) => {
const language = await db
.get<string, string>(levelKeys.language, {
valueEncoding: "utf-8",
})
.then((language) => language || "en");
const params = new URLSearchParams({
locale: language,
});
return HydraApi.get<Badge[]>(`/badges?${params.toString()}`, null, {
needsAuth: false,
});
};
registerEvent("getBadges", getBadges);

View File

@@ -1,10 +0,0 @@
import { registerEvent } from "../register-event";
import { CommonRedistManager } from "@main/services/common-redist-manager";
const installCommonRedist = async (_event: Electron.IpcMainInvokeEvent) => {
if (await CommonRedistManager.canInstallCommonRedist()) {
CommonRedistManager.installCommonRedist();
}
};
registerEvent("installCommonRedist", installCommonRedist);

View File

@@ -1,59 +1,17 @@
import { MAIN_LOOP_INTERVAL } from "@main/constants";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import { HydraApi, WindowManager } from "@main/services"; import { HydraApi } from "@main/services";
import { publishNewFriendRequestNotification } from "@main/services/notifications";
import { UserNotLoggedInError } from "@shared"; import { UserNotLoggedInError } from "@shared";
import type { FriendRequestSync } from "@types"; import type { FriendRequestSync } from "@types";
interface SyncState { const syncFriendRequests = async (_event: Electron.IpcMainInvokeEvent) => {
friendRequestCount: number | null; return HydraApi.get<FriendRequestSync>(`/profile/friend-requests/sync`).catch(
tick: number; (err) => {
}
const ticksToUpdate = (2 * 60 * 1000) / MAIN_LOOP_INTERVAL; // 2 minutes
const syncState: SyncState = {
friendRequestCount: null,
tick: 0,
};
const syncFriendRequests = async () => {
return HydraApi.get<FriendRequestSync>(`/profile/friend-requests/sync`)
.then((res) => {
if (
syncState.friendRequestCount != null &&
syncState.friendRequestCount < res.friendRequestCount
) {
publishNewFriendRequestNotification();
}
syncState.friendRequestCount = res.friendRequestCount;
WindowManager.mainWindow?.webContents.send(
"on-sync-friend-requests",
res
);
return res;
})
.catch((err) => {
if (err instanceof UserNotLoggedInError) { if (err instanceof UserNotLoggedInError) {
return { friendRequestCount: 0 } as FriendRequestSync; return { friendRequests: [] };
} }
throw err; throw err;
}); }
);
}; };
const syncFriendRequestsEvent = async (_event: Electron.IpcMainInvokeEvent) => { registerEvent("syncFriendRequests", syncFriendRequests);
return syncFriendRequests();
};
export const watchFriendRequests = async () => {
if (syncState.tick % ticksToUpdate === 0) {
await syncFriendRequests();
}
syncState.tick++;
};
registerEvent("syncFriendRequests", syncFriendRequestsEvent);

View File

@@ -1,11 +0,0 @@
import { HydraDebridClient } from "@main/services/download/hydra-debrid";
import { registerEvent } from "../register-event";
const checkDebridAvailability = async (
_event: Electron.IpcMainInvokeEvent,
magnets: string[]
) => {
return HydraDebridClient.getAvailableMagnets(magnets);
};
registerEvent("checkDebridAvailability", checkDebridAvailability);

View File

@@ -12,15 +12,7 @@ const startGameDownload = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
payload: StartGameDownloadPayload payload: StartGameDownloadPayload
) => { ) => {
const { const { objectId, title, shop, downloadPath, downloader, uri } = payload;
objectId,
title,
shop,
downloadPath,
downloader,
uri,
automaticallyExtract,
} = payload;
const gameKey = levelKeys.game(shop, objectId); const gameKey = levelKeys.game(shop, objectId);
@@ -82,8 +74,6 @@ const startGameDownload = async (
shouldSeed: false, shouldSeed: false,
timestamp: Date.now(), timestamp: Date.now(),
queued: true, queued: true,
extracting: false,
automaticallyExtract,
}; };
try { try {

View File

@@ -23,6 +23,10 @@ const updateUserPreferences = async (
patchUserProfile({ language: preferences.language }).catch(() => {}); patchUserProfile({ language: preferences.language }).catch(() => {});
} }
if (!preferences.downloadsPath) {
preferences.downloadsPath = null;
}
await db.put<string, UserPreferences>( await db.put<string, UserPreferences>(
levelKeys.userPreferences, levelKeys.userPreferences,
{ {

View File

@@ -1,11 +0,0 @@
import { db, levelKeys } from "@main/level";
import type { Auth } from "@types";
import { registerEvent } from "../register-event";
const getAuth = async (_event: Electron.IpcMainInvokeEvent) =>
db.get<string, Auth>(levelKeys.auth, {
valueEncoding: "json",
});
registerEvent("getAuth", getAuth);

View File

@@ -8,6 +8,7 @@ import { electronApp, optimizer } from "@electron-toolkit/utils";
import { logger, WindowManager } from "@main/services"; import { logger, WindowManager } from "@main/services";
import resources from "@locales"; import resources from "@locales";
import { PythonRPC } from "./services/python-rpc"; import { PythonRPC } from "./services/python-rpc";
import { Aria2 } from "./services/aria2";
import { db, levelKeys } from "./level"; import { db, levelKeys } from "./level";
import { loadState } from "./main"; import { loadState } from "./main";
@@ -142,6 +143,7 @@ app.on("window-all-closed", () => {
app.on("before-quit", () => { app.on("before-quit", () => {
/* Disconnects libtorrent */ /* Disconnects libtorrent */
PythonRPC.kill(); PythonRPC.kill();
Aria2.kill();
}); });
app.on("activate", () => { app.on("activate", () => {

11
src/main/knex-client.ts Normal file
View File

@@ -0,0 +1,11 @@
import knex from "knex";
import { databasePath } from "./constants";
import { app } from "electron";
export const knexClient = knex({
debug: !app.isPackaged,
client: "better-sqlite3",
connection: {
filename: databasePath,
},
});

10
src/main/knexfile.ts Normal file
View File

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

View File

@@ -13,5 +13,5 @@ export const levelKeys = {
downloads: "downloads", downloads: "downloads",
userPreferences: "userPreferences", userPreferences: "userPreferences",
language: "language", language: "language",
screenState: "screenState", sqliteMigrationDone: "sqliteMigrationDone",
}; };

View File

@@ -1,22 +1,31 @@
import { Aria2, DownloadManager, Ludusavi, startMainLoop } from "./services"; import { DownloadManager, logger, Ludusavi, startMainLoop } from "./services";
import { RealDebridClient } from "./services/download/real-debrid"; import { RealDebridClient } from "./services/download/real-debrid";
import { HydraApi } from "./services/hydra-api"; import { HydraApi } from "./services/hydra-api";
import { uploadGamesBatch } from "./services/library-sync"; import { uploadGamesBatch } from "./services/library-sync";
import { Aria2 } from "./services/aria2";
import { downloadsSublevel } from "./level/sublevels/downloads"; import { downloadsSublevel } from "./level/sublevels/downloads";
import { sortBy } from "lodash-es"; import { sortBy } from "lodash-es";
import { Downloader } from "@shared"; import { Downloader } from "@shared";
import { levelKeys, db } from "./level"; import {
import type { UserPreferences } from "@types"; gameAchievementsSublevel,
gamesSublevel,
levelKeys,
db,
} from "./level";
import { Auth, User, type UserPreferences } from "@types";
import { knexClient } from "./knex-client";
import { TorBoxClient } from "./services/download/torbox"; import { TorBoxClient } from "./services/download/torbox";
import { CommonRedistManager } from "./services/common-redist-manager";
export const loadState = async () => { export const loadState = async () => {
const userPreferences = await db.get<string, UserPreferences | null>( const userPreferences = await migrateFromSqlite().then(async () => {
levelKeys.userPreferences, await db.put<string, boolean>(levelKeys.sqliteMigrationDone, true, {
{
valueEncoding: "json", valueEncoding: "json",
} });
);
return db.get<string, UserPreferences | null>(levelKeys.userPreferences, {
valueEncoding: "json",
});
});
await import("./events"); await import("./events");
@@ -43,15 +52,6 @@ export const loadState = async () => {
return sortBy(games, "timestamp", "DESC"); return sortBy(games, "timestamp", "DESC");
}); });
downloads.forEach((download) => {
if (download.extracting) {
downloadsSublevel.put(levelKeys.game(download.shop, download.objectId), {
...download,
extracting: false,
});
}
});
const [nextItemOnQueue] = downloads.filter((game) => game.queued); const [nextItemOnQueue] = downloads.filter((game) => game.queued);
const downloadsToSeed = downloads.filter( const downloadsToSeed = downloads.filter(
@@ -62,9 +62,141 @@ export const loadState = async () => {
game.uri !== null game.uri !== null
); );
console.log("downloadsToSeed", downloadsToSeed);
await DownloadManager.startRPC(nextItemOnQueue, downloadsToSeed); await DownloadManager.startRPC(nextItemOnQueue, downloadsToSeed);
startMainLoop(); startMainLoop();
};
CommonRedistManager.downloadCommonRedist();
const migrateFromSqlite = async () => {
const sqliteMigrationDone = await db.get(levelKeys.sqliteMigrationDone);
if (sqliteMigrationDone) {
return;
}
const migrateGames = knexClient("game")
.select("*")
.then((games) => {
return gamesSublevel.batch(
games.map((game) => ({
type: "put",
key: levelKeys.game(game.shop, game.objectID),
value: {
objectId: game.objectID,
shop: game.shop,
title: game.title,
iconUrl: game.iconUrl,
playTimeInMilliseconds: game.playTimeInMilliseconds,
lastTimePlayed: game.lastTimePlayed,
remoteId: game.remoteId,
winePrefixPath: game.winePrefixPath,
launchOptions: game.launchOptions,
executablePath: game.executablePath,
isDeleted: game.isDeleted === 1,
},
}))
);
})
.then(() => {
logger.info("Games migrated successfully");
});
const migrateUserPreferences = knexClient("user_preferences")
.select("*")
.then(async (userPreferences) => {
if (userPreferences.length > 0) {
const { realDebridApiToken, ...rest } = userPreferences[0];
await db.put<string, UserPreferences>(
levelKeys.userPreferences,
{
...rest,
realDebridApiToken,
preferQuitInsteadOfHiding: rest.preferQuitInsteadOfHiding === 1,
runAtStartup: rest.runAtStartup === 1,
startMinimized: rest.startMinimized === 1,
disableNsfwAlert: rest.disableNsfwAlert === 1,
seedAfterDownloadComplete: rest.seedAfterDownloadComplete === 1,
showHiddenAchievementsDescription:
rest.showHiddenAchievementsDescription === 1,
downloadNotificationsEnabled:
rest.downloadNotificationsEnabled === 1,
repackUpdatesNotificationsEnabled:
rest.repackUpdatesNotificationsEnabled === 1,
achievementNotificationsEnabled:
rest.achievementNotificationsEnabled === 1,
},
{ valueEncoding: "json" }
);
if (rest.language) {
await db.put(levelKeys.language, rest.language);
}
}
})
.then(() => {
logger.info("User preferences migrated successfully");
});
const migrateAchievements = knexClient("game_achievement")
.select("*")
.then((achievements) => {
return gameAchievementsSublevel.batch(
achievements.map((achievement) => ({
type: "put",
key: levelKeys.game(achievement.shop, achievement.objectId),
value: {
achievements: JSON.parse(achievement.achievements),
unlockedAchievements: JSON.parse(achievement.unlockedAchievements),
},
}))
);
})
.then(() => {
logger.info("Achievements migrated successfully");
});
const migrateUser = knexClient("user_auth")
.select("*")
.then(async (users) => {
if (users.length > 0) {
await db.put<string, User>(
levelKeys.user,
{
id: users[0].userId,
displayName: users[0].displayName,
profileImageUrl: users[0].profileImageUrl,
backgroundImageUrl: users[0].backgroundImageUrl,
subscription: users[0].subscription,
},
{
valueEncoding: "json",
}
);
await db.put<string, Auth>(
levelKeys.auth,
{
accessToken: users[0].accessToken,
refreshToken: users[0].refreshToken,
tokenExpirationTimestamp: users[0].tokenExpirationTimestamp,
},
{
valueEncoding: "json",
}
);
}
})
.then(() => {
logger.info("User data migrated successfully");
});
return Promise.allSettled([
migrateGames,
migrateUserPreferences,
migrateAchievements,
migrateUser,
]);
}; };

View File

@@ -1,74 +0,0 @@
import { app } from "electron";
import cp from "node:child_process";
import path from "node:path";
import { logger } from "./logger";
export const binaryName = {
linux: "7zzs",
darwin: "7zz",
win32: "7z.exe",
};
export class SevenZip {
private static readonly binaryPath = app.isPackaged
? path.join(process.resourcesPath, binaryName[process.platform])
: path.join(
__dirname,
"..",
"..",
"binaries",
binaryName[process.platform]
);
public static extractFile(
{
filePath,
outputPath,
cwd,
passwords = [],
}: {
filePath: string;
outputPath?: string;
cwd?: string;
passwords?: string[];
},
successCb: () => void,
errorCb: () => void
) {
const tryPassword = (index = -1) => {
const password = passwords[index] ?? "";
logger.info(`Trying password ${password} on ${filePath}`);
const args = ["x", filePath, "-y", "-p" + password];
if (outputPath) {
args.push("-o" + outputPath);
}
const child = cp.execFile(this.binaryPath, args, {
cwd,
});
child.once("exit", (code) => {
if (code === 0) {
successCb();
return;
}
if (index < passwords.length - 1) {
logger.info(
`Failed to extract file: ${filePath} with password: ${password}. Trying next password...`
);
tryPassword(index + 1);
} else {
logger.info(`Failed to extract file: ${filePath}`);
errorCb();
}
});
};
tryPassword();
}
}

View File

@@ -16,13 +16,6 @@ export const getGameAchievementData = async (
if (cachedAchievements && useCachedData) if (cachedAchievements && useCachedData)
return cachedAchievements.achievements; return cachedAchievements.achievements;
if (
cachedAchievements &&
Date.now() < (cachedAchievements.cacheExpiresTimestamp ?? 0)
) {
return cachedAchievements.achievements;
}
const language = await db const language = await db
.get<string, string>(levelKeys.language, { .get<string, string>(levelKeys.language, {
valueEncoding: "utf-8", valueEncoding: "utf-8",
@@ -38,7 +31,6 @@ export const getGameAchievementData = async (
await gameAchievementsSublevel.put(levelKeys.game(shop, objectId), { await gameAchievementsSublevel.put(levelKeys.game(shop, objectId), {
unlockedAchievements: cachedAchievements?.unlockedAchievements ?? [], unlockedAchievements: cachedAchievements?.unlockedAchievements ?? [],
achievements, achievements,
cacheExpiresTimestamp: Date.now() + 1000 * 60 * 30, // 30 minutes
}); });
return achievements; return achievements;

View File

@@ -2,7 +2,6 @@ import type {
Game, Game,
GameShop, GameShop,
UnlockedAchievement, UnlockedAchievement,
UpdatedUnlockedAchievements,
UserPreferences, UserPreferences,
} from "@types"; } from "@types";
import { WindowManager } from "../window-manager"; import { WindowManager } from "../window-manager";
@@ -27,7 +26,6 @@ const saveAchievementsOnLocal = async (
await gameAchievementsSublevel.put(levelKey, { await gameAchievementsSublevel.put(levelKey, {
achievements: gameAchievement?.achievements ?? [], achievements: gameAchievement?.achievements ?? [],
unlockedAchievements: unlockedAchievements, unlockedAchievements: unlockedAchievements,
cacheExpiresTimestamp: gameAchievement?.cacheExpiresTimestamp,
}); });
if (!sendUpdateEvent) return; if (!sendUpdateEvent) return;
@@ -116,7 +114,7 @@ export const mergeAchievements = async (
} }
if (game.remoteId) { if (game.remoteId) {
await HydraApi.put<UpdatedUnlockedAchievements | undefined>( await HydraApi.put(
"/profile/games/achievements", "/profile/games/achievements",
{ {
id: game.remoteId, id: game.remoteId,
@@ -125,19 +123,10 @@ export const mergeAchievements = async (
{ needsSubscription: !newAchievements.length } { needsSubscription: !newAchievements.length }
) )
.then((response) => { .then((response) => {
if (response) {
return saveAchievementsOnLocal(
response.objectId,
response.shop,
response.achievements,
publishNotification
);
}
return saveAchievementsOnLocal( return saveAchievementsOnLocal(
game.objectId, response.objectId,
game.shop, response.shop,
mergedLocalAchievements, response.achievements,
publishNotification publishNotification
); );
}) })

View File

@@ -2,6 +2,8 @@ import path from "node:path";
import cp from "node:child_process"; import cp from "node:child_process";
import { app } from "electron"; import { app } from "electron";
export const startAria2 = () => {};
export class Aria2 { export class Aria2 {
private static process: cp.ChildProcess | null = null; private static process: cp.ChildProcess | null = null;

View File

@@ -1,111 +0,0 @@
import { levelKeys, gamesSublevel, db } from "@main/level";
import { app } from "electron";
import path from "node:path";
import * as tar from "tar";
import crypto from "node:crypto";
import fs from "node:fs";
import os from "node:os";
import type { GameShop, User } from "@types";
import { backupsPath } from "@main/constants";
import { HydraApi } from "./hydra-api";
import { normalizePath } from "@main/helpers";
import { logger } from "./logger";
import { WindowManager } from "./window-manager";
import axios from "axios";
import { Ludusavi } from "./ludusavi";
import { SubscriptionRequiredError } from "@shared";
export class CloudSync {
private static async bundleBackup(
shop: GameShop,
objectId: string,
winePrefix: string | null
) {
const backupPath = path.join(backupsPath, `${shop}-${objectId}`);
// Remove existing backup
if (fs.existsSync(backupPath)) {
fs.rmSync(backupPath, { recursive: true });
}
await Ludusavi.backupGame(shop, objectId, backupPath, winePrefix);
const tarLocation = path.join(backupsPath, `${crypto.randomUUID()}.tar`);
await tar.create(
{
gzip: false,
file: tarLocation,
cwd: backupPath,
},
["."]
);
return tarLocation;
}
public static async uploadSaveGame(
objectId: string,
shop: GameShop,
downloadOptionTitle: string | null,
label?: string
) {
const hasActiveSubscription = await db
.get<string, User>(levelKeys.user, { valueEncoding: "json" })
.then((user) => {
const expiresAt = new Date(user?.subscription?.expiresAt ?? 0);
return expiresAt > new Date();
});
if (!hasActiveSubscription) {
throw new SubscriptionRequiredError();
}
const game = await gamesSublevel.get(levelKeys.game(shop, objectId));
const bundleLocation = await this.bundleBackup(
shop,
objectId,
game?.winePrefixPath ?? null
);
const stat = await fs.promises.stat(bundleLocation);
const { uploadUrl } = await HydraApi.post<{
id: string;
uploadUrl: string;
}>("/profile/games/artifacts", {
artifactLengthInBytes: stat.size,
shop,
objectId,
hostname: os.hostname(),
homeDir: normalizePath(app.getPath("home")),
downloadOptionTitle,
platform: os.platform(),
label,
});
const fileBuffer = await fs.promises.readFile(bundleLocation);
await axios.put(uploadUrl, fileBuffer, {
headers: {
"Content-Type": "application/tar",
},
onUploadProgress: (progressEvent) => {
logger.log(progressEvent);
},
});
WindowManager.mainWindow?.webContents.send(
`on-upload-complete-${objectId}-${shop}`,
true
);
fs.rm(bundleLocation, (err) => {
if (err) {
logger.error("Failed to remove tar file", err);
throw err;
}
});
}
}

View File

@@ -1,109 +0,0 @@
import { commonRedistPath } from "@main/constants";
import axios from "axios";
import fs from "node:fs";
import cp from "node:child_process";
import path from "node:path";
import { logger } from "./logger";
import { app } from "electron";
import { WindowManager } from "./window-manager";
export class CommonRedistManager {
private static readonly redistributables = [
"dotNetFx40_Full_setup.exe",
"dxwebsetup.exe",
"oalinst.exe",
"install.bat",
"vcredist_2015-2019_x64.exe",
"vcredist_2015-2019_x86.exe",
"vcredist_x64.exe",
"vcredist_x86.exe",
"xnafx40_redist.msi",
];
private static readonly installationTimeout = 1000 * 60 * 5; // 5 minutes
private static readonly installationLog = path.join(
app.getPath("temp"),
"common_redist_install.log"
);
public static async installCommonRedist() {
const abortController = new AbortController();
const timeout = setTimeout(() => {
abortController.abort();
logger.error("Installation timed out");
WindowManager.mainWindow?.webContents.send("common-redist-progress", {
log: "Installation timed out",
complete: false,
});
}, this.installationTimeout);
const installationCompleteMessage = "Installation complete";
if (!fs.existsSync(this.installationLog)) {
await fs.promises.writeFile(this.installationLog, "");
}
fs.watch(this.installationLog, { signal: abortController.signal }, () => {
fs.readFile(this.installationLog, "utf-8", (err, data) => {
if (err) return logger.error("Error reading log file:", err);
const tail = data.split("\n").at(-2)?.trim();
if (tail?.includes(installationCompleteMessage)) {
clearTimeout(timeout);
if (!abortController.signal.aborted) {
abortController.abort();
}
}
WindowManager.mainWindow?.webContents.send("common-redist-progress", {
log: tail,
complete: tail?.includes(installationCompleteMessage),
});
});
});
cp.exec(
path.join(commonRedistPath, "install.bat"),
{
windowsHide: true,
},
(error) => {
if (error) {
logger.error("Failed to run install.bat", error);
}
}
);
}
public static async canInstallCommonRedist() {
return this.redistributables.every((redist) => {
const filePath = path.join(commonRedistPath, redist);
return fs.existsSync(filePath);
});
}
public static async downloadCommonRedist() {
if (!fs.existsSync(commonRedistPath)) {
await fs.promises.mkdir(commonRedistPath, { recursive: true });
}
for (const redist of this.redistributables) {
const filePath = path.join(commonRedistPath, redist);
if (fs.existsSync(filePath)) {
continue;
}
const response = await axios.get(
`https://github.com/hydralauncher/hydra-common-redist/raw/refs/heads/main/${redist}`,
{
responseType: "arraybuffer",
}
);
await fs.promises.writeFile(filePath, response.data);
}
}
}

View File

@@ -1,14 +1,8 @@
import { Downloader, DownloadError, FILE_EXTENSIONS_TO_EXTRACT } from "@shared"; import { Downloader, DownloadError } from "@shared";
import { WindowManager } from "../window-manager"; import { WindowManager } from "../window-manager";
import { publishDownloadCompleteNotification } from "../notifications"; import { publishDownloadCompleteNotification } from "../notifications";
import type { Download, DownloadProgress, UserPreferences } from "@types"; import type { Download, DownloadProgress, UserPreferences } from "@types";
import { import { GofileApi, QiwiApi, DatanodesApi, MediafireApi } from "../hosters";
GofileApi,
QiwiApi,
DatanodesApi,
MediafireApi,
PixelDrainApi,
} from "../hosters";
import { PythonRPC } from "../python-rpc"; import { PythonRPC } from "../python-rpc";
import { import {
LibtorrentPayload, LibtorrentPayload,
@@ -22,8 +16,6 @@ import { logger } from "../logger";
import { db, downloadsSublevel, gamesSublevel, levelKeys } from "@main/level"; import { db, downloadsSublevel, gamesSublevel, levelKeys } from "@main/level";
import { sortBy } from "lodash-es"; import { sortBy } from "lodash-es";
import { TorBoxClient } from "./torbox"; import { TorBoxClient } from "./torbox";
import { GameFilesManager } from "../game-files-manager";
import { HydraDebridClient } from "./hydra-debrid";
export class DownloadManager { export class DownloadManager {
private static downloadingGameId: string | null = null; private static downloadingGameId: string | null = null;
@@ -138,8 +130,6 @@ export class DownloadManager {
); );
} }
const shouldExtract = download.automaticallyExtract;
if (progress === 1 && download) { if (progress === 1 && download) {
publishDownloadCompleteNotification(game); publishDownloadCompleteNotification(game);
@@ -147,48 +137,23 @@ export class DownloadManager {
userPreferences?.seedAfterDownloadComplete && userPreferences?.seedAfterDownloadComplete &&
download.downloader === Downloader.Torrent download.downloader === Downloader.Torrent
) { ) {
await downloadsSublevel.put(gameId, { downloadsSublevel.put(gameId, {
...download, ...download,
status: "seeding", status: "seeding",
shouldSeed: true, shouldSeed: true,
queued: false, queued: false,
extracting: shouldExtract,
}); });
} else { } else {
await downloadsSublevel.put(gameId, { downloadsSublevel.put(gameId, {
...download, ...download,
status: "complete", status: "complete",
shouldSeed: false, shouldSeed: false,
queued: false, queued: false,
extracting: shouldExtract,
}); });
this.cancelDownload(gameId); this.cancelDownload(gameId);
} }
if (shouldExtract) {
const gameFilesManager = new GameFilesManager(
game.shop,
game.objectId
);
if (
FILE_EXTENSIONS_TO_EXTRACT.some((ext) =>
download.folderName?.endsWith(ext)
)
) {
gameFilesManager.extractDownloadedFile();
} else {
gameFilesManager
.extractFilesInDirectory(
path.join(download.downloadPath, download.folderName!)
)
.then(() => {
gameFilesManager.setExtractionComplete();
});
}
}
const downloads = await downloadsSublevel const downloads = await downloadsSublevel
.values() .values()
.all() .all()
@@ -314,18 +279,15 @@ export class DownloadManager {
url: downloadLink, url: downloadLink,
save_path: download.downloadPath, save_path: download.downloadPath,
header: `Cookie: accountToken=${token}`, header: `Cookie: accountToken=${token}`,
allow_multiple_connections: true,
connections_limit: 8,
}; };
} }
case Downloader.PixelDrain: { case Downloader.PixelDrain: {
const id = download.uri.split("/").pop(); const id = download.uri.split("/").pop();
const downloadUrl = await PixelDrainApi.getDownloadUrl(id!);
return { return {
action: "start", action: "start",
game_id: downloadId, game_id: downloadId,
url: downloadUrl, url: `https://cdn.pd5-gamedriveorg.workers.dev/api/file/${id}`,
save_path: download.downloadPath, save_path: download.downloadPath,
}; };
} }
@@ -367,14 +329,13 @@ export class DownloadManager {
case Downloader.RealDebrid: { case Downloader.RealDebrid: {
const downloadUrl = await RealDebridClient.getDownloadUrl(download.uri); const downloadUrl = await RealDebridClient.getDownloadUrl(download.uri);
if (!downloadUrl) throw new Error(DownloadError.NotCachedOnRealDebrid); if (!downloadUrl) throw new Error(DownloadError.NotCachedInRealDebrid);
return { return {
action: "start", action: "start",
game_id: downloadId, game_id: downloadId,
url: downloadUrl, url: downloadUrl,
save_path: download.downloadPath, save_path: download.downloadPath,
allow_multiple_connections: true,
}; };
} }
case Downloader.TorBox: { case Downloader.TorBox: {
@@ -387,22 +348,6 @@ export class DownloadManager {
url, url,
save_path: download.downloadPath, save_path: download.downloadPath,
out: name, out: name,
allow_multiple_connections: true,
};
}
case Downloader.Hydra: {
const downloadUrl = await HydraDebridClient.getDownloadUrl(
download.uri
);
if (!downloadUrl) throw new Error(DownloadError.NotCachedOnHydra);
return {
action: "start",
game_id: downloadId,
url: downloadUrl,
save_path: download.downloadPath,
allow_multiple_connections: true,
}; };
} }
} }

View File

@@ -1,27 +0,0 @@
import { HydraApi } from "../hydra-api";
export class HydraDebridClient {
public static getAvailableMagnets(
magnets: string[]
): Promise<Record<string, boolean>> {
return HydraApi.put(
"/debrid/check-availability",
{
magnets,
},
{ needsAuth: false }
);
}
public static async getDownloadUrl(magnet: string) {
try {
const response = await HydraApi.post("/debrid/request-file", {
magnet,
});
return response.downloadUrl;
} catch (error) {
return null;
}
}
}

View File

@@ -6,7 +6,6 @@ import type {
TorBoxAddTorrentRequest, TorBoxAddTorrentRequest,
TorBoxRequestLinkRequest, TorBoxRequestLinkRequest,
} from "@types"; } from "@types";
import { appVersion } from "@main/constants";
export class TorBoxClient { export class TorBoxClient {
private static instance: AxiosInstance; private static instance: AxiosInstance;
@@ -19,7 +18,6 @@ export class TorBoxClient {
baseURL: this.baseURL, baseURL: this.baseURL,
headers: { headers: {
Authorization: `Bearer ${apiToken}`, Authorization: `Bearer ${apiToken}`,
"User-Agent": `Hydra/${appVersion}`,
}, },
}); });
} }

View File

@@ -1,158 +0,0 @@
import path from "node:path";
import fs from "node:fs";
import type { GameShop } from "@types";
import { downloadsSublevel, gamesSublevel, levelKeys } from "@main/level";
import { FILE_EXTENSIONS_TO_EXTRACT } from "@shared";
import { SevenZip } from "./7zip";
import { WindowManager } from "./window-manager";
import { publishExtractionCompleteNotification } from "./notifications";
import { logger } from "./logger";
export class GameFilesManager {
constructor(
private readonly shop: GameShop,
private readonly objectId: string
) {}
private async clearExtractionState() {
const gameKey = levelKeys.game(this.shop, this.objectId);
const download = await downloadsSublevel.get(gameKey);
await downloadsSublevel.put(gameKey, {
...download!,
extracting: false,
});
WindowManager.mainWindow?.webContents.send(
"on-extraction-complete",
this.shop,
this.objectId
);
}
async extractFilesInDirectory(directoryPath: string) {
if (!fs.existsSync(directoryPath)) return;
const files = await fs.promises.readdir(directoryPath);
const compressedFiles = files.filter((file) =>
FILE_EXTENSIONS_TO_EXTRACT.some((ext) => file.endsWith(ext))
);
const filesToExtract = compressedFiles.filter(
(file) => /part1\.rar$/i.test(file) || !/part\d+\.rar$/i.test(file)
);
await Promise.all(
filesToExtract.map((file) => {
return new Promise((resolve, reject) => {
SevenZip.extractFile(
{
filePath: path.join(directoryPath, file),
cwd: directoryPath,
passwords: ["online-fix.me", "steamrip.com"],
},
() => {
resolve(true);
},
() => {
reject(new Error(`Failed to extract file: ${file}`));
this.clearExtractionState();
}
);
});
})
);
compressedFiles.forEach((file) => {
const extractionPath = path.join(directoryPath, file);
if (fs.existsSync(extractionPath)) {
fs.unlink(extractionPath, (err) => {
if (err) {
logger.error(`Failed to delete file: ${file}`, err);
this.clearExtractionState();
}
});
}
});
}
async setExtractionComplete(publishNotification = true) {
const gameKey = levelKeys.game(this.shop, this.objectId);
const [download, game] = await Promise.all([
downloadsSublevel.get(gameKey),
gamesSublevel.get(gameKey),
]);
await downloadsSublevel.put(gameKey, {
...download!,
extracting: false,
});
WindowManager.mainWindow?.webContents.send(
"on-extraction-complete",
this.shop,
this.objectId
);
if (publishNotification) {
publishExtractionCompleteNotification(game!);
}
}
async extractDownloadedFile() {
const gameKey = levelKeys.game(this.shop, this.objectId);
const [download, game] = await Promise.all([
downloadsSublevel.get(gameKey),
gamesSublevel.get(gameKey),
]);
if (!download || !game) return false;
const filePath = path.join(download.downloadPath, download.folderName!);
const extractionPath = path.join(
download.downloadPath,
path.parse(download.folderName!).name
);
SevenZip.extractFile(
{
filePath,
outputPath: extractionPath,
passwords: ["online-fix.me", "steamrip.com"],
},
async () => {
await this.extractFilesInDirectory(extractionPath);
if (fs.existsSync(extractionPath) && fs.existsSync(filePath)) {
fs.unlink(filePath, (err) => {
if (err) {
logger.error(
`Failed to delete file: ${download.folderName}`,
err
);
this.clearExtractionState();
}
});
}
await downloadsSublevel.put(gameKey, {
...download!,
folderName: path.parse(download.folderName!).name,
});
this.setExtractionComplete();
},
() => {
this.clearExtractionState();
}
);
return true;
}
}

View File

@@ -1,71 +1,47 @@
import axios, { AxiosResponse } from "axios"; import axios, { AxiosResponse } from "axios";
import { wrapper } from "axios-cookiejar-support";
import { CookieJar } from "tough-cookie";
export class DatanodesApi { export class DatanodesApi {
private static readonly jar = new CookieJar(); private static readonly session = axios.create({});
private static readonly session = wrapper(
axios.create({
jar: DatanodesApi.jar,
withCredentials: true,
})
);
public static async getDownloadUrl(downloadUrl: string): Promise<string> { public static async getDownloadUrl(downloadUrl: string): Promise<string> {
try { const parsedUrl = new URL(downloadUrl);
const parsedUrl = new URL(downloadUrl); const pathSegments = parsedUrl.pathname.split("/");
const pathSegments = parsedUrl.pathname.split("/").filter(Boolean);
const fileCode = pathSegments[0];
await this.jar.setCookie("lang=english;", "https://datanodes.to"); const fileCode = decodeURIComponent(pathSegments[1]);
const fileName = decodeURIComponent(pathSegments[pathSegments.length - 1]);
const payload = new URLSearchParams({ const payload = new URLSearchParams({
op: "download2", op: "download2",
id: fileCode, id: fileCode,
method_free: "Free Download >>", rand: "",
dl: "1", referer: "https://datanodes.to/download",
}); method_free: "Free Download >>",
method_premium: "",
adblock_detected: "",
});
const response: AxiosResponse = await this.session.post( const response: AxiosResponse = await this.session.post(
"https://datanodes.to/download", "https://datanodes.to/download",
payload, payload,
{ {
headers: { headers: {
"User-Agent": "Content-Type": "application/x-www-form-urlencoded",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0", Cookie: `lang=english; file_name=${fileName}; file_code=${fileCode};`,
Referer: "https://datanodes.to/download", Host: "datanodes.to",
Origin: "https://datanodes.to", Origin: "https://datanodes.to",
"Content-Type": "application/x-www-form-urlencoded", Referer: "https://datanodes.to/download",
}, "User-Agent":
maxRedirects: 0, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
validateStatus: (status: number) => status === 302 || status < 400, },
} maxRedirects: 0,
); validateStatus: (status: number) => status === 302 || status < 400,
if (response.status === 302) {
return response.headers["location"];
} }
);
if (typeof response.data === "object" && response.data.url) { if (response.status === 302) {
return decodeURIComponent(response.data.url); return response.headers["location"];
}
const htmlContent = String(response.data);
if (!htmlContent) {
throw new Error("Empty response received");
}
const downloadLinkRegex = /href=["'](https:\/\/[^"']+)["']/;
const downloadLinkMatch = downloadLinkRegex.exec(htmlContent);
if (downloadLinkMatch) {
return downloadLinkMatch[1];
}
throw new Error("Failed to get the download link");
} catch (error) {
console.error("Error fetching download URL:", error);
throw error;
} }
return "";
} }
} }

View File

@@ -2,4 +2,3 @@ export * from "./gofile";
export * from "./qiwi"; export * from "./qiwi";
export * from "./datanodes"; export * from "./datanodes";
export * from "./mediafire"; export * from "./mediafire";
export * from "./pixeldrain";

View File

@@ -1,42 +0,0 @@
import axios from "axios";
export class PixelDrainApi {
private static readonly browserHeaders = {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
Accept:
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
DNT: "1",
Connection: "keep-alive",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
};
public static async getDownloadUrl(fileId: string): Promise<string> {
try {
const response = await axios.get(`https://pd.cybar.xyz/${fileId}`, {
headers: this.browserHeaders,
maxRedirects: 0,
validateStatus: (status) =>
status === 301 || status === 302 || status === 200,
});
if (
response.headers.location ||
response.status === 301 ||
response.status === 302
) {
return response.headers.location;
}
throw new Error(`No redirect URL found (status: ${response.status})`);
} catch (error) {
console.error("Error fetching PixelDrain URL:", error);
throw error;
}
}
}

View File

@@ -8,6 +8,7 @@ import { UserNotLoggedInError, SubscriptionRequiredError } from "@shared";
import { omit } from "lodash-es"; import { omit } from "lodash-es";
import { appVersion } from "@main/constants"; import { appVersion } from "@main/constants";
import { getUserData } from "./user/get-user-data"; import { getUserData } from "./user/get-user-data";
import { isFuture, isToday } from "date-fns";
import { db } from "@main/level"; import { db } from "@main/level";
import { levelKeys } from "@main/level/sublevels"; import { levelKeys } from "@main/level/sublevels";
import type { Auth, User } from "@types"; import type { Auth, User } from "@types";
@@ -46,8 +47,8 @@ export class HydraApi {
} }
private static hasActiveSubscription() { private static hasActiveSubscription() {
const expiresAt = new Date(this.userAuth.subscription?.expiresAt ?? 0); const expiresAt = this.userAuth.subscription?.expiresAt;
return expiresAt > new Date(); return expiresAt && (isFuture(expiresAt) || isToday(expiresAt));
} }
static async handleExternalAuth(uri: string) { static async handleExternalAuth(uri: string) {

View File

@@ -7,8 +7,3 @@ export * from "./process-watcher";
export * from "./main-loop"; export * from "./main-loop";
export * from "./hydra-api"; export * from "./hydra-api";
export * from "./ludusavi"; export * from "./ludusavi";
export * from "./cloud-sync";
export * from "./7zip";
export * from "./game-files-manager";
export * from "./common-redist-manager";
export * from "./aria2";

View File

@@ -3,21 +3,18 @@ import { DownloadManager } from "./download";
import { watchProcesses } from "./process-watcher"; import { watchProcesses } from "./process-watcher";
import { AchievementWatcherManager } from "./achievements/achievement-watcher-manager"; import { AchievementWatcherManager } from "./achievements/achievement-watcher-manager";
import { UpdateManager } from "./update-manager"; import { UpdateManager } from "./update-manager";
import { watchFriendRequests } from "@main/events/profile/sync-friend-requests";
import { MAIN_LOOP_INTERVAL } from "@main/constants";
export const startMainLoop = async () => { export const startMainLoop = async () => {
// eslint-disable-next-line no-constant-condition // eslint-disable-next-line no-constant-condition
while (true) { while (true) {
await Promise.allSettled([ await Promise.allSettled([
watchProcesses(), watchProcesses(),
watchFriendRequests(),
DownloadManager.watchDownloads(), DownloadManager.watchDownloads(),
AchievementWatcherManager.watchAchievements(), AchievementWatcherManager.watchAchievements(),
DownloadManager.getSeedStatus(), DownloadManager.getSeedStatus(),
UpdateManager.checkForUpdatePeriodically(), UpdateManager.checkForUpdatePeriodically(),
]); ]);
await sleep(MAIN_LOOP_INTERVAL); await sleep(1500);
} }
}; };

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