mirror of
https://github.com/an-anime-team/sleepy-launcher.git
synced 2025-02-17 02:09:46 +03:00
commit
c2208070ef
52 changed files with 889 additions and 265 deletions
26
.vscode/launch.json
vendored
Normal file
26
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug",
|
||||||
|
"cargo": {
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"--bin=anime-game-launcher",
|
||||||
|
"--package=anime-game-launcher"
|
||||||
|
],
|
||||||
|
"filter": {
|
||||||
|
"name": "anime-game-launcher",
|
||||||
|
"kind": "bin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
24
CHANGELOG.md
24
CHANGELOG.md
|
@ -11,6 +11,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Added rules approving dialog to the first run window
|
||||||
|
- Added game settings section
|
||||||
|
- Added game sessions manager
|
||||||
|
- Added `LAUNCHER_FOLDER` variable support.
|
||||||
|
Using this you can specify root path where the launcher stores `config.json` and other files
|
||||||
|
- Added patch repository mirror
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Improved launcher logo rendering quality
|
||||||
|
- Reworked entry rows in the settings
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed wine tools running using proton builds
|
||||||
|
- Fixed sandboxed game running (sounds are broken for now)
|
||||||
|
|
||||||
|
## [3.5.2] - 17.04.2023
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
- Added arguments and symlinks editor to sandbox settings
|
- Added arguments and symlinks editor to sandbox settings
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -203,7 +224,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
[unreleased]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.5.1...next
|
[unreleased]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.5.2...next
|
||||||
|
[3.5.2]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.5.1...3.5.2
|
||||||
[3.5.1]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.5.0...3.5.1
|
[3.5.1]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.5.0...3.5.1
|
||||||
[3.5.0]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.4.1...3.5.0
|
[3.5.0]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.4.1...3.5.0
|
||||||
[3.4.1]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.4.0...3.4.1
|
[3.4.1]: https://github.com/an-anime-team/an-anime-game-launcher/compare/3.4.0...3.4.1
|
||||||
|
|
18
Cargo.lock
generated
18
Cargo.lock
generated
|
@ -40,8 +40,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anime-game-core"
|
name = "anime-game-core"
|
||||||
version = "1.7.1"
|
version = "1.8.0"
|
||||||
source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.7.1#8978728ce5d94aec5c6aecfe470e45fc43d5b522"
|
source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.8.0#dbb9008bcdd6a7b8026567ff35417671a77c740e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bzip2",
|
"bzip2",
|
||||||
|
@ -65,7 +65,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anime-game-launcher"
|
name = "anime-game-launcher"
|
||||||
version = "3.5.2"
|
version = "3.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anime-launcher-sdk",
|
"anime-launcher-sdk",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
@ -87,8 +87,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anime-launcher-sdk"
|
name = "anime-launcher-sdk"
|
||||||
version = "1.0.6"
|
version = "1.2.1"
|
||||||
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.0.6#2a8272c1afdd006925c150ac480a82be645f4b52"
|
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.2.1#f7bddd1d2fde4dcc7d04bda9e4d9160a5bc88218"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anime-game-core",
|
"anime-game-core",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
@ -2065,9 +2065,9 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "relm4"
|
name = "relm4"
|
||||||
version = "0.6.0-alpha.2"
|
version = "0.6.0-beta.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7acc5e3ddd682eeb0ca33da36b821fc907017c6d7758b09ce280247b0b0ea8cd"
|
checksum = "f169f698ce2e487eed2306898fcf262224a287d0e81480db4190e74cfec412cf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"flume",
|
"flume",
|
||||||
|
@ -2083,9 +2083,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "relm4-macros"
|
name = "relm4-macros"
|
||||||
version = "0.6.0-alpha.2"
|
version = "0.6.0-beta.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c8525ce12dcd7d2a9e9070d84b8b885600eccd0a143df6712ce34a87d001a8b7"
|
checksum = "7fa06febb3685960e7c1c44e21e44a3829325940b31d1e91391a43c32020c201"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "anime-game-launcher"
|
name = "anime-game-launcher"
|
||||||
version = "3.5.2"
|
version = "3.6.0"
|
||||||
description = "Anime Game launcher"
|
description = "Anime Game launcher"
|
||||||
authors = ["Nikita Podvirnyy <suimin.tu.mu.ga.mi@gmail.com>"]
|
authors = ["Nikita Podvirnyy <suimin.tu.mu.ga.mi@gmail.com>"]
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
|
@ -17,13 +17,13 @@ glib-build-tools = "0.17"
|
||||||
|
|
||||||
[dependencies.anime-launcher-sdk]
|
[dependencies.anime-launcher-sdk]
|
||||||
git = "https://github.com/an-anime-team/anime-launcher-sdk"
|
git = "https://github.com/an-anime-team/anime-launcher-sdk"
|
||||||
tag = "1.0.6"
|
tag = "1.2.1"
|
||||||
features = ["all", "genshin"]
|
features = ["all", "genshin"]
|
||||||
|
|
||||||
# path = "../anime-launcher-sdk" # ! for dev purposes only
|
# path = "../anime-launcher-sdk" # ! for dev purposes only
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
relm4 = { version = "0.6.0-alpha.2", features = ["macros", "libadwaita"] }
|
relm4 = { version = "0.6.0-beta.1", features = ["macros", "libadwaita"] }
|
||||||
gtk = { package = "gtk4", version = "0.6", features = ["v4_8"] }
|
gtk = { package = "gtk4", version = "0.6", features = ["v4_8"] }
|
||||||
adw = { package = "libadwaita", version = "0.3", features = ["v1_2"] }
|
adw = { package = "libadwaita", version = "0.3", features = ["v1_2"] }
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,8 @@ instead of the actual name of the game, to avoid search engine parsing.
|
||||||
|
|
||||||
To see the installation guides, please visit the wiki page [here](https://github.com/an-anime-team/an-anime-game-launcher/wiki/Installation)
|
To see the installation guides, please visit the wiki page [here](https://github.com/an-anime-team/an-anime-game-launcher/wiki/Installation)
|
||||||
|
|
||||||
|
Lutris integration described [here](https://github.com/an-anime-team/an-anime-game-launcher/wiki/Installation#-lutris)
|
||||||
|
|
||||||
## Chinese version support
|
## Chinese version support
|
||||||
|
|
||||||
This should be automatically enabled if you're using zh_cn (Chinese) as your system language. If you're not using it - you can change the game edition in the launcher settings
|
This should be automatically enabled if you're using zh_cn (Chinese) as your system language. If you're not using it - you can change the game edition in the launcher settings
|
||||||
|
|
|
@ -19,5 +19,5 @@ ru-ru = Русский
|
||||||
de-de = Deutsch
|
de-de = Deutsch
|
||||||
es-es = Español
|
es-es = Español
|
||||||
fr-fr = Français
|
fr-fr = Français
|
||||||
tr-tr = Türk
|
tr-tr = Türkçe
|
||||||
zh-cn = 简体中文
|
zh-cn = 简体中文
|
||||||
|
|
|
@ -6,7 +6,7 @@ debug-file-opening-error = Debug-Datei konnte nicht geöffnet werden
|
||||||
wish-url-search-failed = Kein Wünsche URL gefunden
|
wish-url-search-failed = Kein Wünsche URL gefunden
|
||||||
wish-url-opening-error = Wünsche URL konnte nicht geöffnet werden
|
wish-url-opening-error = Wünsche URL konnte nicht geöffnet werden
|
||||||
|
|
||||||
wine-run-error = Failed to run {$executable} executable using wine
|
wine-run-error = Ausführung von {$executable} mit wine fehlgeschlagen
|
||||||
|
|
||||||
game-launching-failed = Spiel konnte nicht gestartet werden
|
game-launching-failed = Spiel konnte nicht gestartet werden
|
||||||
failed-get-selected-wine = Die ausgewählte Wine version konnte nicht abgerufen werden.
|
failed-get-selected-wine = Die ausgewählte Wine version konnte nicht abgerufen werden.
|
||||||
|
@ -44,4 +44,12 @@ game-patching-error = Spiel konnte nicht gepatcht werden
|
||||||
|
|
||||||
# Sandbox
|
# Sandbox
|
||||||
|
|
||||||
documentation-url-open-failed = Failed to open documentation URL
|
documentation-url-open-failed = Dokumentations-URL kann nicht geöffnet werden
|
||||||
|
|
||||||
|
# Game
|
||||||
|
|
||||||
|
game-session-add-failed = Spielsitzung konnte nicht hinzugefügt werden
|
||||||
|
game-session-update-failed = Spielsitzung konnte nicht aktualisiert werden
|
||||||
|
game-session-remove-failed = Spielsitzung konnte nicht entfernt werden
|
||||||
|
game-session-set-current-failed = Aktuelle Spielsitzung konnte nicht eingestellt werden
|
||||||
|
game-session-apply-failed = Spielsitzung konnte nicht angewendet werden
|
||||||
|
|
|
@ -21,8 +21,13 @@ tos-violation-warning-message =
|
||||||
|
|
||||||
Sollte dies der Fall sein, würde Ihr Konto gegen die TOS verstoßen, {company-name}/{company-alter-name} sind frei zu tun, was sie wollen. Inklusive Ban.
|
Sollte dies der Fall sein, würde Ihr Konto gegen die TOS verstoßen, {company-name}/{company-alter-name} sind frei zu tun, was sie wollen. Inklusive Ban.
|
||||||
|
|
||||||
Wenn Sie sich des Risikos bewusst sind, das mit dem Versuch, das Spiel inoffiziell zu spielen, verbunden ist, drücken Sie auf OK und lassen Sie uns die Welt von Teyvat erforschen!
|
Wenn Sie sich über das Risiko bewusst sind das mit dem versuchen des Spiels spielen in inoffizieller Weise verbunden ist dann drücken Sie OK um fortzufahren.
|
||||||
|
|
||||||
|
tos-dialog-title = Sind Sie sicher, dass Sie verstehen, was wir sagen?
|
||||||
|
tos-dialog-message =
|
||||||
|
1. Veröffentlichen Sie keine Informationen über dieses Projekt
|
||||||
|
2. Missbrauchen Sie es nicht durch die Verwendung von Mods
|
||||||
|
3. Stellen Sie Fragen nur in unserem Discord oder auf dem Matrix-Server
|
||||||
|
|
||||||
dependencies = Abhängigkeiten
|
dependencies = Abhängigkeiten
|
||||||
missing-dependencies-title = Sie vermissen einige Abhängigkeiten!
|
missing-dependencies-title = Sie vermissen einige Abhängigkeiten!
|
||||||
|
@ -36,14 +41,14 @@ show-all-folders-subtitle = Zusätzliche Pfadauswahl-Einstellungen anzeigen. Tu
|
||||||
runners-folder = Runners-Ordner
|
runners-folder = Runners-Ordner
|
||||||
dxvks-folder = DXVKs-Ordner
|
dxvks-folder = DXVKs-Ordner
|
||||||
wine-prefix-folder = Wine prefix-Ordner
|
wine-prefix-folder = Wine prefix-Ordner
|
||||||
global-game-installation-folder = Global game version installation folder
|
global-game-installation-folder = Installationsordner der globalen Spielversion
|
||||||
chinese-game-installation-folder = Chinese game version installation folder
|
chinese-game-installation-folder = Installationsordner der chinesischen Spielversion
|
||||||
fps-unlocker-folder = FPS Unlocker Ordner
|
fps-unlocker-folder = FPS Unlocker Ordner
|
||||||
components-index = Komponentenverzeichnis
|
components-index = Komponentenverzeichnis
|
||||||
patch-folder = Patch-Ordner
|
patch-folder = Patch-Ordner
|
||||||
temp-folder = Temp-Ordner
|
temp-folder = Temp-Ordner
|
||||||
|
|
||||||
migrate = Migrate
|
migrate = Migrieren
|
||||||
|
|
||||||
|
|
||||||
select-voice-packages = Sprachpakete auswählen
|
select-voice-packages = Sprachpakete auswählen
|
||||||
|
|
7
assets/locales/de/game.ftl
Normal file
7
assets/locales/de/game.ftl
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
game-sessions = Spielsitzungen
|
||||||
|
|
||||||
|
active-sessions = Aktive Sitzung
|
||||||
|
active-session-description = Derzeit ausgewählte Spielsitzung. Aktualisiert nach jedem Spielstart
|
||||||
|
|
||||||
|
update-session = Sitzung mit aktuellen Wine prefix Registrierungswerten aktualisieren
|
||||||
|
delete-session = Sitzung löschen
|
|
@ -7,22 +7,22 @@ update-background-description = Lädt das offizielle Hintergrundbild herunter f
|
||||||
launcher-language = Launcher Sprache
|
launcher-language = Launcher Sprache
|
||||||
launcher-language-description = Gilt nach Neustart
|
launcher-language-description = Gilt nach Neustart
|
||||||
|
|
||||||
game-edition = Game edition
|
game-edition = Spiel-Edition
|
||||||
global = Global
|
global = Global
|
||||||
china = China
|
china = China
|
||||||
|
|
||||||
game-environment = Game environment
|
game-environment = Spielumgebung
|
||||||
game-environment-description = Get specific features like additional payment methods
|
game-environment-description = Spezielle Funktionen wie zusätzliche Zahlungsmöglichkeiten
|
||||||
|
|
||||||
game-voiceovers = Spiel Sprachen
|
game-voiceovers = Spiel Sprachen
|
||||||
game-voiceovers-description = List of downloaded game voiceovers. You can select them in the game settings
|
game-voiceovers-description = Liste der heruntergeladenen Sprachausgabe für das Spiel. Sie können diese in den Spieleinstellungen auswählen
|
||||||
english = Englisch
|
english = Englisch
|
||||||
japanese = Japanisch
|
japanese = Japanisch
|
||||||
korean = Koreanisch
|
korean = Koreanisch
|
||||||
chinese = Chinesisch
|
chinese = Chinesisch
|
||||||
|
|
||||||
migrate-installation = Migrate installation
|
migrate-installation = Installation migrieren
|
||||||
migrate-installation-description = Open special window where you can change your game installation folder
|
migrate-installation-description = Öffnet ein spezielles Fenster, in dem Sie den Installationsordner Ihres Spiels ändern können
|
||||||
repair-game = Spiel Reparieren
|
repair-game = Spiel Reparieren
|
||||||
|
|
||||||
status = Status
|
status = Status
|
||||||
|
@ -64,11 +64,11 @@ wine-version = Wine version
|
||||||
wine-recommended-description = Nur empfohlene wine versionen anzeigen
|
wine-recommended-description = Nur empfohlene wine versionen anzeigen
|
||||||
|
|
||||||
wine-tools = Wine tools
|
wine-tools = Wine tools
|
||||||
command-line = Command line
|
command-line = Befehlszeile
|
||||||
registry-editor = Registry editor
|
registry-editor = Registrierungs-Editor
|
||||||
explorer = Explorer
|
explorer = Explorer
|
||||||
task-manager = Task manager
|
task-manager = Task manager
|
||||||
configuration = Configuration
|
configuration = Konfiguration
|
||||||
debugger = Debugger
|
debugger = Debugger
|
||||||
|
|
||||||
dxvk-version = DXVK version
|
dxvk-version = DXVK version
|
||||||
|
|
|
@ -22,6 +22,7 @@ continue = Weiter
|
||||||
exit = Beenden
|
exit = Beenden
|
||||||
check = Überprüfen
|
check = Überprüfen
|
||||||
restart = Neustarten
|
restart = Neustarten
|
||||||
|
agree = Einverstanden
|
||||||
|
|
||||||
|
|
||||||
loading-data = Laden Daten
|
loading-data = Laden Daten
|
||||||
|
@ -49,8 +50,8 @@ components-index-updated = Kompontentenverzeichnis würde aktualisiert
|
||||||
|
|
||||||
|
|
||||||
launch = Starten
|
launch = Starten
|
||||||
migrate-folders = Migrate folders
|
migrate-folders = Ordner migrieren
|
||||||
migrate-folders-tooltip = Update game folders structure
|
migrate-folders-tooltip = Spielordnerstruktur aktualisieren
|
||||||
apply-patch = Patch anwenden
|
apply-patch = Patch anwenden
|
||||||
download-wine = Wine Herunterladen
|
download-wine = Wine Herunterladen
|
||||||
create-prefix = Prefix erstellen
|
create-prefix = Prefix erstellen
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
sandbox = Sandbox
|
sandbox = Sandbox
|
||||||
sandbox-description = Run the game in isolated environment, preventing it from accessing your personal data
|
sandbox-description = Führen Sie das Spiel in einer isolierten Umgebung aus, damit es nicht auf Ihre persönlichen Daten zugreifen kann.
|
||||||
|
|
||||||
enable-sandboxing = Enable sandboxing
|
enable-sandboxing = Sandboxing aktivieren
|
||||||
enable-sandboxing-description = Run the game in read-only copy of your root filesystem
|
enable-sandboxing-description = Starten Sie das Spiel in einer schreibgeschützten Kopie Ihres Root-Dateisystems
|
||||||
|
|
||||||
hide-home-directory = Hide home directory
|
hide-home-directory = Home-Verzeichnis ausblenden
|
||||||
hide-home-directory-description = Isolate your /home, /var/home/$USER, and $HOME folders from the game
|
hide-home-directory-description = Isolieren Sie Ihre Ordner /home, /var/home/$USER und $HOME vom Spiel
|
||||||
|
|
||||||
hostname = Hostname
|
hostname = Hostname
|
||||||
additional-arguments = Additional arguments
|
additional-arguments = Zusätzliche Argumente
|
||||||
|
|
||||||
private-directories = Private directories
|
private-directories = Private Verzeichnisse
|
||||||
private-directories-description = These folders will be replaced by an empty virtual filesystem (tmpfs), and their original content will not be available to sandboxed game
|
private-directories-description = Diese Ordner werden durch ein leeres virtuelles Dateisystem (tmpfs) ersetzt, und ihr ursprünglicher Inhalt ist für das Spiel in der Sandbox nicht verfügbar.
|
||||||
|
|
||||||
path = Path
|
path = Pfad
|
||||||
|
|
||||||
shared-directories = Shared directories
|
shared-directories = Geteilte Verzeichnisse
|
||||||
shared-directories-description = These directories will be symlinked to directories in your host system
|
shared-directories-description = Diese Verzeichnisse werden mit Verzeichnissen in Ihrem Host-System verlinkt
|
||||||
|
|
||||||
original-path = Original path
|
original-path = Ursprünglicher Pfad
|
||||||
new-path = New path
|
new-path = Neuer Pfad
|
||||||
|
|
||||||
read-only = Read-only
|
read-only = Schreibgeschützt
|
||||||
read-only-description = Forbid game to write any data to this directory
|
read-only-description = Dem Spiel verbieten, Daten in dieses Verzeichnis zu schreiben
|
||||||
|
|
||||||
symlinks = Symlinks
|
symlinks = Symlinks
|
||||||
symlinks-description = Symlink original path to the new one inside of your sandbox
|
symlinks-description = Verknüpfen Sie den ursprünglichen Pfad mit dem neuen Pfad innerhalb Ihrer Sandbox
|
||||||
|
|
|
@ -45,3 +45,11 @@ game-patching-error = Failed to patch game
|
||||||
# Sandbox
|
# Sandbox
|
||||||
|
|
||||||
documentation-url-open-failed = Failed to open documentation URL
|
documentation-url-open-failed = Failed to open documentation URL
|
||||||
|
|
||||||
|
# Game
|
||||||
|
|
||||||
|
game-session-add-failed = Failed to add game session
|
||||||
|
game-session-update-failed = Failed to update game session
|
||||||
|
game-session-remove-failed = Failed to remove game session
|
||||||
|
game-session-set-current-failed = Failed to set current game session
|
||||||
|
game-session-apply-failed = Failed to apply game session
|
||||||
|
|
|
@ -21,7 +21,13 @@ tos-violation-warning-message =
|
||||||
|
|
||||||
If this happens, as your account would be disobeying TOS, {company-name}/{company-alter-name} are free to do what they want. Including banning.
|
If this happens, as your account would be disobeying TOS, {company-name}/{company-alter-name} are free to do what they want. Including banning.
|
||||||
|
|
||||||
If you understand the risk of trying to play the game in an unofficial capacity, press OK and let's go researching the world of Teyvat!
|
If you understand the risk of trying to play the game in an unofficial capacity, press OK to continue
|
||||||
|
|
||||||
|
tos-dialog-title = Are you sure you understand what we want to say?
|
||||||
|
tos-dialog-message =
|
||||||
|
1. Don't publish any information about this project
|
||||||
|
2. Don't abuse it by using some modded clients and so
|
||||||
|
3. Ask questions exceptionally in our discord or matrix server
|
||||||
|
|
||||||
|
|
||||||
dependencies = Dependencies
|
dependencies = Dependencies
|
||||||
|
|
7
assets/locales/en/game.ftl
Normal file
7
assets/locales/en/game.ftl
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
game-sessions = Game sessions
|
||||||
|
|
||||||
|
active-sessions = Active session
|
||||||
|
active-session-description = Currently selected game session. Updates after each game launch
|
||||||
|
|
||||||
|
update-session = Update session using current wine prefix registry values
|
||||||
|
delete-session = Delete session
|
|
@ -22,6 +22,7 @@ continue = Continue
|
||||||
exit = Exit
|
exit = Exit
|
||||||
check = Check
|
check = Check
|
||||||
restart = Restart
|
restart = Restart
|
||||||
|
agree = Agree
|
||||||
|
|
||||||
|
|
||||||
loading-data = Loading data
|
loading-data = Loading data
|
||||||
|
|
|
@ -45,3 +45,11 @@ game-patching-error = Fallo al parchear el juego
|
||||||
# Sandbox
|
# Sandbox
|
||||||
|
|
||||||
documentation-url-open-failed = Failed to open documentation URL
|
documentation-url-open-failed = Failed to open documentation URL
|
||||||
|
|
||||||
|
# Game
|
||||||
|
|
||||||
|
game-session-add-failed = Fallo al añadir sesión de juego
|
||||||
|
game-session-update-failed = Fallo al actualizar sesión de juego
|
||||||
|
game-session-remove-failed = Fallo al eliminar sesión de juego
|
||||||
|
game-session-set-current-failed = Fallo al establecer sesión de juego actual
|
||||||
|
game-session-apply-failed = Fallo al aplicar sesión de juego
|
||||||
|
|
|
@ -23,6 +23,11 @@ tos-violation-warning-message =
|
||||||
|
|
||||||
Si entiendes los riesgos de intentar jugar el juego de manera extraoficial, presiona OK y ¡exploremos el vasto mundo de Teyvat!
|
Si entiendes los riesgos de intentar jugar el juego de manera extraoficial, presiona OK y ¡exploremos el vasto mundo de Teyvat!
|
||||||
|
|
||||||
|
tos-dialog-title = ¿Estás seguro de entender lo que queremos decir?
|
||||||
|
tos-dialog-message =
|
||||||
|
1. No publiques información sobre este proyecto
|
||||||
|
2. No abuses de él usando clientes modificados o cosas similares
|
||||||
|
3. Haz preguntas exclusivamente en nuestro canal de Discord o de Matrix
|
||||||
|
|
||||||
dependencies = Dependencias
|
dependencies = Dependencias
|
||||||
missing-dependencies-title = ¡Te faltan algunas dependencias!
|
missing-dependencies-title = ¡Te faltan algunas dependencias!
|
||||||
|
|
7
assets/locales/es/game.ftl
Normal file
7
assets/locales/es/game.ftl
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
game-sessions = Sesiones de juego
|
||||||
|
|
||||||
|
active-sessions = Sesión activa
|
||||||
|
active-session-description = La sesión de juego actualmente seleccionada. Se actualiza cada vez que se lanza el juego.
|
||||||
|
|
||||||
|
update-session = Actualizar la sesión con los valores actuales del registro del prefijo de Wine
|
||||||
|
delete-session = Eliminar sesión
|
|
@ -22,6 +22,7 @@ continue = Continuar
|
||||||
exit = Salir
|
exit = Salir
|
||||||
check = Comprobar
|
check = Comprobar
|
||||||
restart = Reiniciar
|
restart = Reiniciar
|
||||||
|
agree = Aceptar
|
||||||
|
|
||||||
|
|
||||||
loading-data = Cargando datos
|
loading-data = Cargando datos
|
||||||
|
|
|
@ -8,7 +8,7 @@ hide-home-directory = Esconder el directorio home
|
||||||
hide-home-directory-description = Aisla las carpetas /home, /var/home/$USER, y $HOME del juego
|
hide-home-directory-description = Aisla las carpetas /home, /var/home/$USER, y $HOME del juego
|
||||||
|
|
||||||
hostname = Nombre del host
|
hostname = Nombre del host
|
||||||
additional-arguments = Additional arguments
|
additional-arguments = Argumentos adicionales
|
||||||
|
|
||||||
private-directories = Directorios privados
|
private-directories = Directorios privados
|
||||||
private-directories-description = Estas carpetas serán reemplazadas por un sistema de archivos virtual (tmpfs) vacío, y su contenido real no será accesible al juego aislado
|
private-directories-description = Estas carpetas serán reemplazadas por un sistema de archivos virtual (tmpfs) vacío, y su contenido real no será accesible al juego aislado
|
||||||
|
@ -24,5 +24,5 @@ new-path = Nueva ruta
|
||||||
read-only = Sólo lectura
|
read-only = Sólo lectura
|
||||||
read-only-description = Le prohibe al juego escribir datos en este directorio
|
read-only-description = Le prohibe al juego escribir datos en este directorio
|
||||||
|
|
||||||
symlinks = Symlinks
|
symlinks = Enlaces simbólicos
|
||||||
symlinks-description = Symlink original path to the new one inside of your sandbox
|
symlinks-description = Enlaza la ruta original a la nueva dentro de tu entorno aislado
|
||||||
|
|
|
@ -45,3 +45,11 @@ game-patching-error = Le patch du jeu a échoué
|
||||||
# Sandbox
|
# Sandbox
|
||||||
|
|
||||||
documentation-url-open-failed = Failed to open documentation URL
|
documentation-url-open-failed = Failed to open documentation URL
|
||||||
|
|
||||||
|
# Game
|
||||||
|
|
||||||
|
game-session-add-failed = Imposible d'ajouter la session de jeu
|
||||||
|
game-session-update-failed = Imposible de mettre à jour la session de jeu
|
||||||
|
game-session-remove-failed = Imposible de supprimer la session de jeu
|
||||||
|
game-session-set-current-failed = Imposible de sélectionner la session de jeu par défaut
|
||||||
|
game-session-apply-failed = Imposible d'appliquer la session de jeu
|
||||||
|
|
|
@ -23,6 +23,11 @@ tos-violation-warning-message =
|
||||||
|
|
||||||
Si vous comprenez ces risques, appuyez sur "Continuer" pour venir explorer le monde de Teyvat !
|
Si vous comprenez ces risques, appuyez sur "Continuer" pour venir explorer le monde de Teyvat !
|
||||||
|
|
||||||
|
tos-dialog-title = Are you sure you understand what we want to say?
|
||||||
|
tos-dialog-message =
|
||||||
|
1. Don't publish any information about this project
|
||||||
|
2. Don't abuse it by using some modded clients and so
|
||||||
|
3. Ask questions exceptionally in our discord or matrix server
|
||||||
|
|
||||||
dependencies = Dépendances
|
dependencies = Dépendances
|
||||||
missing-dependencies-title = Il vous manque des dépendances !
|
missing-dependencies-title = Il vous manque des dépendances !
|
||||||
|
|
7
assets/locales/fr/game.ftl
Normal file
7
assets/locales/fr/game.ftl
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
game-sessions = Sessions de jeu
|
||||||
|
|
||||||
|
active-sessions = Session active
|
||||||
|
active-session-description = Session actuellement sélectionnée en jeu. Mis à jour à chaque lancement du jeu
|
||||||
|
|
||||||
|
update-session = Mettre à jour la session depuis les valeurs du registre du préfixe wine
|
||||||
|
delete-session = Supprimer la session
|
|
@ -22,6 +22,7 @@ continue = Continuer
|
||||||
exit = Quitter
|
exit = Quitter
|
||||||
check = Vérifier
|
check = Vérifier
|
||||||
restart = Redémarer
|
restart = Redémarer
|
||||||
|
agree = Agree
|
||||||
|
|
||||||
|
|
||||||
loading-data = Chargement des données
|
loading-data = Chargement des données
|
||||||
|
|
|
@ -45,3 +45,11 @@ game-patching-error = Не удалось установить патч игры
|
||||||
# Sandbox
|
# Sandbox
|
||||||
|
|
||||||
documentation-url-open-failed = Не удалось открыть ссылку с документацией
|
documentation-url-open-failed = Не удалось открыть ссылку с документацией
|
||||||
|
|
||||||
|
# Game
|
||||||
|
|
||||||
|
game-session-add-failed = Не удалось добавить игровую сессию
|
||||||
|
game-session-update-failed = Не удалось обновить игровую сессию
|
||||||
|
game-session-remove-failed = Не удалось удалить игровую сессию
|
||||||
|
game-session-set-current-failed = Не удалось выбрать игровую сессию
|
||||||
|
game-session-apply-failed = Не удалось применить игровую сессию
|
||||||
|
|
|
@ -23,8 +23,13 @@ tos-violation-warning-message =
|
||||||
|
|
||||||
Если это произойдёт - поскольку ваша учетная запись будет нарушать правила, {company-name}/{company-alter-name} будут свободы делать то, что захотят, включая блокировку вашего аккаунта.
|
Если это произойдёт - поскольку ваша учетная запись будет нарушать правила, {company-name}/{company-alter-name} будут свободы делать то, что захотят, включая блокировку вашего аккаунта.
|
||||||
|
|
||||||
Если вы осознаёте риск использования неофициальных средств игры - нажмите "Продолжить" и отправляйтесь исследовать мир Тейвата!
|
Если вы осознаёте риск использования неофициальных средств игры - нажмите "Продолжить"
|
||||||
|
|
||||||
|
tos-dialog-title = Вы точно уверены что понимаете что мы хотим сказать?
|
||||||
|
tos-dialog-message =
|
||||||
|
1. Не публикуйте никакой информации о проекте
|
||||||
|
2. Не используйте его совместно с модифицированными клиентами и тому подобным
|
||||||
|
3. Задавайте вопросы исключительно на нашем discord или matrix сервере
|
||||||
|
|
||||||
dependencies = Зависимости
|
dependencies = Зависимости
|
||||||
missing-dependencies-title = У вас не установлены некоторые компоненты!
|
missing-dependencies-title = У вас не установлены некоторые компоненты!
|
||||||
|
|
7
assets/locales/ru/game.ftl
Normal file
7
assets/locales/ru/game.ftl
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
game-sessions = Игровые сессии
|
||||||
|
|
||||||
|
active-sessions = Активная сессия
|
||||||
|
active-session-description = Выбранная игровая сессия. Обновляется после каждого запуска игры
|
||||||
|
|
||||||
|
update-session = Обновить сессию используя значения реестра из префикса Wine
|
||||||
|
delete-session = Удалить сессию
|
|
@ -22,6 +22,7 @@ continue = Продолжить
|
||||||
exit = Выйти
|
exit = Выйти
|
||||||
check = Проверить
|
check = Проверить
|
||||||
restart = Перезапустить
|
restart = Перезапустить
|
||||||
|
agree = Подтвердить
|
||||||
|
|
||||||
|
|
||||||
loading-data = Загрузка данных
|
loading-data = Загрузка данных
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
wine = Wine
|
wine = Wine
|
||||||
|
|
||||||
synchronization = Senkronizasyon
|
synchronization = Senkronizasyon
|
||||||
wine-sync-description = içerde dönen Wine eventleri senkronize etmek için kullanılan teknoloji
|
wine-sync-description = Arkaplanda gerçekleşen Wine olaylarını senkronize etmek için kullanılan teknoloji
|
||||||
|
|
||||||
language = dil
|
language = Dil
|
||||||
wine-lang-description = Wine için kullanılan dil klavye sorunlarını çözmek için kullanılabilir
|
wine-lang-description = Wine için kullanılan dil, klavye sorunlarını çözmek için kullanılabilir
|
||||||
system = Sistem
|
system = Sistem
|
||||||
|
|
||||||
borderless-window = Köşesiz pencere
|
borderless-window = Köşesiz Pencere
|
||||||
virtual-desktop = Sanal Masaüstü
|
virtual-desktop = Sanal Masaüstü
|
||||||
|
|
||||||
game = Oyun
|
game = Oyun
|
||||||
|
@ -15,30 +15,30 @@ game = Oyun
|
||||||
hud = HUD
|
hud = HUD
|
||||||
|
|
||||||
fsr = FSR
|
fsr = FSR
|
||||||
fsr-description = Oyunu mönitör boyutunuza büyütür daha düşük bir çözünürlük seçmek için oyun içinde alt + enter tuşlarına basın
|
fsr-description = Oyunu monitör boyutunuza büyütür. Daha düşük bir çözünürlük seçmek için oyun içinde alt + enter tuşlarına basın
|
||||||
ultra-quality = Ultra kalite
|
ultra-quality = Ultra kalite
|
||||||
quality = Kalite
|
quality = Kalite
|
||||||
balanced = Dengeli
|
balanced = Dengeli
|
||||||
performance = Performans
|
performance = Performans
|
||||||
|
|
||||||
gamemode = Oyunmodu
|
gamemode = Oyun modu
|
||||||
gamemode-description = Oyunu diğer işlemlerden daha öne koyarak performansı arttırır
|
gamemode-description = Oyunun işlem önceliğini arttırarak performansı arttırır
|
||||||
|
|
||||||
gamescope = Gamescope
|
gamescope = Gamescope
|
||||||
gamescope-description = Gamescope Valve tarafından geliştirilmiş bir araçtır oyunları izole edilmiş bir Xwayland içinde açmanıza yarar
|
gamescope-description = Gamescope, oyunları izole edilmiş bir Xwayland içinde açmanıza yarayan Valve tarafından geliştirilmiş araçtır.
|
||||||
|
|
||||||
discord-rpc = Discord RPC
|
discord-rpc = Discord RPC
|
||||||
discord-rpc-description = Discord RPC Discorda şuanda oyun oynadığınızın bilgisini vermenize yarar bu sayede arkadaşlarınıza şuanda oyun oynadığınızı gösterebilirsiniz
|
discord-rpc-description = Discord RPC, Discord'a şu anda oyun oynadığınızı bildirmenizi sağlar. Bu sayede arkadaşlarınıza şu anda oyun oynadığınızı gösterebilirsiniz
|
||||||
title = Başlık
|
title = Başlık
|
||||||
description = Açıklama
|
description = Açıklama
|
||||||
|
|
||||||
fps-unlocker = FPS kilidi açıcı
|
fps-unlocker = FPS kilidi açıcı
|
||||||
|
|
||||||
enabled = Açık
|
enabled = Açık
|
||||||
fps-unlocker-description = kare renderlama limitasyonunu kaldırır fakat oyunun anti hile sistemi tarafından tespit edilebilir
|
fps-unlocker-description = Kare işleme sınırlamasını kaldırır, fakat oyunun anti-hile sistemi tarafından tespit edilebilir
|
||||||
|
|
||||||
power-saving = Güç tasarrufu
|
power-saving = Güç tasarrufu
|
||||||
power-saving-description = Alt tab attığınızda oyunun fps limitini 10 a çeker ve oyuna verilen işlem önceliğini azaltır
|
power-saving-description = Pencere değiştirdiğinizde oyunun kare sınırını 10'a indirir ve oyuna verilen işlem önceliğini azaltır
|
||||||
|
|
||||||
monitor = Monitör
|
monitor = Monitör
|
||||||
monitor-description = Oyunu çalıştırmak istediğiniz monitör sayısı
|
monitor-description = Oyunu çalıştırmak istediğiniz monitör sayısı
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
launcher-folder-opening-error = Failed to open launcher folder
|
launcher-folder-opening-error = İstemci dosyasını açma başarısız oldu
|
||||||
game-folder-opening-error = Oyun dosyasını açma başarısız oldu
|
game-folder-opening-error = Oyun dosyasını açma başarısız oldu
|
||||||
config-file-opening-error = Config dosyasını açma başarısız oldu
|
config-file-opening-error = Config dosyasını açma başarısız oldu
|
||||||
debug-file-opening-error = Debug dosyasını açma başarısız oldu
|
debug-file-opening-error = Debug dosyasını açma başarısız oldu
|
||||||
|
|
||||||
wish-url-search-failed = Dilekler urlsi bulunamadı
|
wish-url-search-failed = Dileklerin URL'si bulunamadı
|
||||||
wish-url-opening-error = Dilekler urlsi açılamadı
|
wish-url-opening-error = Dileklerin URL'si açılamadı
|
||||||
|
|
||||||
wine-run-error = Failed to run {$executable} executable using wine
|
wine-run-error = Wine kullanarak {$executable} programı çalıştırılamadı
|
||||||
|
|
||||||
game-launching-failed = Oyunu açma başarısız oldu
|
game-launching-failed = Oyunu açma başarısız oldu
|
||||||
failed-get-selected-wine = Seçilen Wine versiyonunu alma başarısız oldu
|
failed-get-selected-wine = Seçilen Wine versiyonunu alma başarısız oldu
|
||||||
|
@ -19,18 +19,18 @@ integrity-files-getting-error = Dosyaların bütünlüğü kontrol edilemedi
|
||||||
background-downloading-failed = Arkaplan fotoğrafını indirme başarısız oldu
|
background-downloading-failed = Arkaplan fotoğrafını indirme başarısız oldu
|
||||||
components-index-sync-failed = Bileşenler dizini senkronizasyonu başarısız oldu
|
components-index-sync-failed = Bileşenler dizini senkronizasyonu başarısız oldu
|
||||||
components-index-verify-failed = Bileşenler dizini doğrulanamadı
|
components-index-verify-failed = Bileşenler dizini doğrulanamadı
|
||||||
config-update-error = Configi kaydetme başarısız oldu
|
config-update-error = Config'i kaydetme başarısız oldu
|
||||||
wine-prefix-update-failed = Wine prefixini güncelleme başarısız oldu
|
wine-prefix-update-failed = Wine prefixini güncelleme başarısız oldu
|
||||||
dxvk-install-failed = DXVK indirilemedi
|
dxvk-install-failed = DXVK indirilemedi
|
||||||
voice-package-deletion-error = Ses dosyasını silme başarısız oldu
|
voice-package-deletion-error = Ses dosyasını silme başarısız oldu
|
||||||
|
|
||||||
game-diff-finding-error = Oyun diffini bulma başarısız oldu
|
game-diff-finding-error = Oyun diff'ini bulma başarısız oldu
|
||||||
patch-info-fetching-error = Yama bilgilerini toplama başarısız oldu
|
patch-info-fetching-error = Yama bilgilerini toplama başarısız oldu
|
||||||
launcher-state-updating-error = İstemci durumunu güncelleme başarısız oldu
|
launcher-state-updating-error = İstemci durumunu güncelleme başarısız oldu
|
||||||
|
|
||||||
package-not-available = Paket mevcut değil: {$package}
|
package-not-available = Paket mevcut değil: {$package}
|
||||||
wine-download-error = Wine indirme başarısız oldu
|
wine-download-error = Wine indirme başarısız oldu
|
||||||
wine-unpack-errror = Wine dosyadan çıkarmak başarısız oldu
|
wine-unpack-errror = Wine dosyadan çıkarma başarısız oldu
|
||||||
wine-install-failed = Wine kurma başarısız oldu
|
wine-install-failed = Wine kurma başarısız oldu
|
||||||
dxvk-download-error = DXVK indirilemedi
|
dxvk-download-error = DXVK indirilemedi
|
||||||
dxvk-unpack-error = DXVK paketten çıkarılamadı
|
dxvk-unpack-error = DXVK paketten çıkarılamadı
|
||||||
|
@ -44,4 +44,12 @@ game-patching-error = Yamayı uygulamada sorun çıktı
|
||||||
|
|
||||||
# Sandbox
|
# Sandbox
|
||||||
|
|
||||||
documentation-url-open-failed = Failed to open documentation URL
|
documentation-url-open-failed = Belgelemenin URL'si açılamadı
|
||||||
|
|
||||||
|
# Game
|
||||||
|
|
||||||
|
game-session-add-failed = Oyun oturumu eklenemedi
|
||||||
|
game-session-update-failed = Oyun oturumu güncellenemedi
|
||||||
|
game-session-remove-failed = Oyun oturumu kaldırılamadı
|
||||||
|
game-session-set-current-failed = Oyun oturumu seçilemedi
|
||||||
|
game-session-apply-failed = Oyun oturumu uygulanamadı
|
||||||
|
|
|
@ -1,31 +1,36 @@
|
||||||
welcome = Merhaba
|
welcome = Merhaba
|
||||||
|
|
||||||
welcome-page-message =
|
welcome-page-message =
|
||||||
Merhaba bir anime oyunu istemcisine hoş geldiniz
|
Merhaba, bir anime oyunu istemcisine hoş geldiniz
|
||||||
|
|
||||||
Oyunu çalıştırmadan önce bazı şeyler hazırlamamız ve varsayılan bileşenleri indirmemiz gerekiyor.
|
Oyunu çalıştırmadan önce bazı şeyleri hazırlamamız ve varsayılan bileşenleri indirmemiz gerekiyor.
|
||||||
|
|
||||||
|
|
||||||
tos-violation-warning = Kullanım şartlarının ihlali uyarısı
|
tos-violation-warning = Kullanım şartlarının ihlali uyarısı
|
||||||
|
|
||||||
tos-violation-warning-message =
|
tos-violation-warning-message =
|
||||||
Bu başlatıcı, resmi olmayan bir araçtır ve hiçbir şekilde {company-name} veya {company-alter-name} ile ilgili değildir.
|
Bu başlatıcı, resmi olmayan bir araçtır ve hiçbir şekilde {company-name} veya {company-alter-name} ile ilgili değildir.
|
||||||
|
|
||||||
Bu araç, Linux'ta {game-name} oynamayı kolaylaştırmak için tasarlanmıştır ve yalnızca oyunu daha az güçlükle yüklemek ve çalıştırmak amacıyla oluşturulmuştur.
|
Bu araç, Linux'ta {game-name} oynamayı kolaylaştırmak için tasarlanmıştır ve yalnızca oyunu daha az güçlükle yüklemek ve çalıştırmak amacıyla oluşturulmuştur.
|
||||||
|
|
||||||
Bunu, mevcut bileşenleri kullanarak ve deneyimi kullanıcı için basit hale getirerek yapar.
|
Bunu, mevcut bileşenleri kullanarak ve deneyimi kullanıcı için basit hale getirerek yapar.
|
||||||
|
|
||||||
Ancak burada kullanılan bazı bileşenler, {game-name} için {company-name} Hizmet Şartlarını ihlal ediyor olabilir.
|
Ancak burada kullanılan bazı bileşenler, {game-name} için {company-name} Hizmet Şartlarını ihlal ediyor olabilir.
|
||||||
|
|
||||||
Bu başlatıcıyı kullanıyorsanız, {game-name} hesabınız {company-name}/{company-alter-name} tarafından TOS uyumlu değil olarak tanımlanacaktır.
|
Bu başlatıcıyı kullanıyorsanız, {game-name} hesabınız {company-name}/{company-alter-name} tarafından TOS uyumlu değil olarak tanımlanacaktır.
|
||||||
|
|
||||||
Böyle bir durumda, hesabınız Hizmet Koşullarına uymayacağından, {company-name}/{company-alter-name} istediğini yapmakta özgürdür. Banlamak dahil.
|
Böyle bir durumda, hesabınız Hizmet Koşullarına uymayacağından, {company-name}/{company-alter-name} istediğini yapmakta özgürdür. Banlamak dahil.
|
||||||
|
|
||||||
Oyunu gayri resmi bir sıfatla oynamaya çalışmanın riskini anlıyorsanız, Tamam'a basın ve Haydi Teyvat dünyasını araştırmaya başlayalım!
|
Eğer oyunu illegal yollarla oynamanın riskini anlıyorsanız, Tamam'a tıklayın
|
||||||
|
|
||||||
|
tos-dialog-title = Ne demek istediğimizi anlayabildiniz mi?
|
||||||
|
tos-dialog-message =
|
||||||
|
1. Bu proje hakkında herhangi bir bilgi paylaşmayın.
|
||||||
|
2. Modlanmış istemciler vb. ile suistimal etmeyin.
|
||||||
|
3. Sorularınızı sadece Discord veya Matrix sunucumuzda sorun.
|
||||||
|
|
||||||
dependencies = Bağlılıklar
|
dependencies = Bağımlılıklar
|
||||||
missing-dependencies-title = Bazı bağlılıklar bulunamadı!
|
missing-dependencies-title = Bazı bağımlılıklar bulunamadı!
|
||||||
missing-dependencies-message = Kurulum işlemine devam etmeden önce bazı paketleri sisteminize kurmalısınız.
|
missing-dependencies-message = Kurulum işlemine devam etmeden önce bazı paketleri sisteminize kurmalısınız.
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,24 +39,24 @@ choose-default-paths = Varsayılan yolları seç
|
||||||
show-all-folders = Ne yaptığımı biliyorum
|
show-all-folders = Ne yaptığımı biliyorum
|
||||||
show-all-folders-subtitle = Ek yol seçimi ayarlarını göster. Dediğimi yap...
|
show-all-folders-subtitle = Ek yol seçimi ayarlarını göster. Dediğimi yap...
|
||||||
runners-folder = Başlatıcılar(Runnerlar) klasörü
|
runners-folder = Başlatıcılar(Runnerlar) klasörü
|
||||||
dxvks-folder = DXVKnın klasörü
|
dxvks-folder = DXVK'nin klasörü
|
||||||
wine-prefix-folder = Wine prefixnin klasörü
|
wine-prefix-folder = Wine prefix'inin klasörü
|
||||||
global-game-installation-folder = Global game version installation folder
|
global-game-installation-folder = Evrensel oyun sürümünü yükleme klasörü
|
||||||
chinese-game-installation-folder = Chinese game version installation folder
|
chinese-game-installation-folder = Oyun'un Çin sürümünü yükleme klasörü
|
||||||
fps-unlocker-folder = FPS Unlocker folder
|
fps-unlocker-folder = FPS Unlocker klasörü
|
||||||
components-index = Bileşenlerin dizini
|
components-index = Bileşenlerin dizini
|
||||||
patch-folder = Yama klasörü
|
patch-folder = Yama klasörü
|
||||||
temp-folder = "Geçici" klasörü
|
temp-folder = "Geçici" klasörü
|
||||||
|
|
||||||
migrate = Migrate
|
migrate = Aktarma
|
||||||
|
|
||||||
|
|
||||||
select-voice-packages = Ses paketlerini seç
|
select-voice-packages = Ses paketlerini seç
|
||||||
|
|
||||||
|
|
||||||
download-components = Bileşenleri indir
|
download-components = Bileşenleri indir
|
||||||
download-dxvk = DXVKyı İndir
|
download-dxvk = DXVK'yi İndir
|
||||||
apply-dxvk = DXVKyı uygula
|
apply-dxvk = DXVK'yi uygula
|
||||||
|
|
||||||
|
|
||||||
finish = Bitir
|
finish = Bitir
|
||||||
|
|
7
assets/locales/tr/game.ftl
Normal file
7
assets/locales/tr/game.ftl
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
game-sessions = Oyun oturumları
|
||||||
|
|
||||||
|
active-sessions = Geçerli oturum
|
||||||
|
active-session-description = Şu anda geçerli oyun oturumu. Oyunu her açtığınızda güncellenir
|
||||||
|
|
||||||
|
update-session = Oturumu, geçerli wine prefix'inin girdi değerleriyle güncelleyin
|
||||||
|
delete-session = Oturumu kaldır
|
|
@ -10,4 +10,4 @@ nis-description = DLSS teknolojisine düşük maliyetli bir alternatif olarak Nv
|
||||||
|
|
||||||
other-settings = Diğer ayarlar
|
other-settings = Diğer ayarlar
|
||||||
framerate-limit = Kare hızı limiti
|
framerate-limit = Kare hızı limiti
|
||||||
unfocused-framerate-limit = Odakta değilken ki Kare hızı limiti
|
unfocused-framerate-limit = Odakta değilken kare hızı limiti
|
||||||
|
|
|
@ -5,43 +5,43 @@ update-background = Arkaplan imajını güncelle
|
||||||
update-background-description = İstemci için resmi arka plan resmini indirin. Bunun yerine özel resminizi kullanmak için devre dışı bırakabilirsiniz.
|
update-background-description = İstemci için resmi arka plan resmini indirin. Bunun yerine özel resminizi kullanmak için devre dışı bırakabilirsiniz.
|
||||||
|
|
||||||
launcher-language = İstemci dili
|
launcher-language = İstemci dili
|
||||||
launcher-language-description = Restart attıktan sonra uygulanır
|
launcher-language-description = Yeniden başlattıktan sonra uygulanır
|
||||||
|
|
||||||
game-edition = Game edition
|
game-edition = Oyun Sürümü
|
||||||
global = Global
|
global = Evrensel
|
||||||
china = China
|
china = Çin
|
||||||
|
|
||||||
game-environment = Game environment
|
game-environment = Oyun ortamı
|
||||||
game-environment-description = Get specific features like additional payment methods
|
game-environment-description = Ek ödeme yöntemleri gibi özelliklere erişin
|
||||||
|
|
||||||
game-voiceovers = Oyun içi sesler
|
game-voiceovers = Oyun içi sesler
|
||||||
game-voiceovers-description = List of downloaded game voiceovers. You can select them in the game settings
|
game-voiceovers-description = İndirilmiş oyun seslendirmeleri listesi. Oyun içi ayarlardan seçebilirsiniz
|
||||||
english = İngilizce
|
english = İngilizce
|
||||||
japanese = Japonca
|
japanese = Japonca
|
||||||
korean = Korece
|
korean = Korece
|
||||||
chinese = Çince
|
chinese = Çince
|
||||||
|
|
||||||
migrate-installation = Migrate installation
|
migrate-installation = Yüklemeyi aktar
|
||||||
migrate-installation-description = Open special window where you can change your game installation folder
|
migrate-installation-description = Oyun yükleme yerini değiştirebileceğiniz özel pencereyi açın
|
||||||
repair-game = Oyunu tamir et
|
repair-game = Oyunu tamir et
|
||||||
|
|
||||||
status = Durum
|
status = Durum
|
||||||
|
|
||||||
game-version = Oyun versiyonu
|
game-version = Oyun versiyonu
|
||||||
game-not-installed = inik değil
|
game-not-installed = Yüklü değil
|
||||||
|
|
||||||
game-predownload-available = Güncelleme önceden indirilebilir: {$old} -> {$new}
|
game-predownload-available = Güncelleme önceden indirilebilir: {$old} -> {$new}
|
||||||
game-update-available = Güncelleme mevcut: {$old} -> {$new}
|
game-update-available = Güncelleme mevcut: {$old} -> {$new}
|
||||||
game-outdated = Oyun çok eski bu yüzden güncellenemez. En son sürüm: {$latest}
|
game-outdated = Oyun çok eski, bu yüzden güncellenemez. En son sürüm: {$latest}
|
||||||
|
|
||||||
player-patch-version = Ana yama versiyonu
|
player-patch-version = Ana yama versiyonu
|
||||||
player-patch-version-description = Oyunu linuxda oynamanıza izin veren ana yama
|
player-patch-version-description = Oyunu Linux'ta oynamanıza izin veren ana yama
|
||||||
|
|
||||||
xlua-patch-version = Xlua yama versiyonu
|
xlua-patch-version = Xlua yama versiyonu
|
||||||
xlua-patch-version-description = Eski bilgisayarlarda performansı arttıran ve bir kaç sorunu düzelten ekstra yama
|
xlua-patch-version-description = Eski bilgisayarlarda performansı arttıran ve birkaç sorunu düzelten ekstra yama
|
||||||
|
|
||||||
patch-not-available = Mevcut değil
|
patch-not-available = Mevcut değil
|
||||||
patch-not-available-tooltip = Yama sunucularına erişelemiyor
|
patch-not-available-tooltip = Yama sunucularına erişilemiyor
|
||||||
|
|
||||||
patch-outdated = zamanı geçmiş ({$current})
|
patch-outdated = zamanı geçmiş ({$current})
|
||||||
patch-outdated-tooltip = Yamanın zamanı geçmiş: {$current} -> {$latest}
|
patch-outdated-tooltip = Yamanın zamanı geçmiş: {$current} -> {$latest}
|
||||||
|
@ -55,7 +55,7 @@ patch-not-applied-tooltip = Yama uygulanmamış
|
||||||
apply-xlua-patch = Xlua yamasını uygula
|
apply-xlua-patch = Xlua yamasını uygula
|
||||||
|
|
||||||
ask-superuser-permissions = Yönetici izinlerini sor
|
ask-superuser-permissions = Yönetici izinlerini sor
|
||||||
ask-superuser-permissions-description = İstemci yöneticini iznini hostunuzun dosyalarını güncellemek için otomatik olarak kullanıcaktır. Buna flatpak versiyonunda gerek yoktur
|
ask-superuser-permissions-description = İstemci yönetici iznini hostunuzun dosyalarını güncellemek için otomatik olarak kullanacaktır. Buna flatpak versiyonunda gerek yoktur
|
||||||
|
|
||||||
selected-version = Seçilmiş versiyon
|
selected-version = Seçilmiş versiyon
|
||||||
recommended-only = Sadece önerilenler
|
recommended-only = Sadece önerilenler
|
||||||
|
@ -63,14 +63,14 @@ recommended-only = Sadece önerilenler
|
||||||
wine-version = Wine versiyonu
|
wine-version = Wine versiyonu
|
||||||
wine-recommended-description = Sadece önerilen wine versiyonlarını göster
|
wine-recommended-description = Sadece önerilen wine versiyonlarını göster
|
||||||
|
|
||||||
wine-tools = Wine tools
|
wine-tools = Wine araçları
|
||||||
command-line = Command line
|
command-line = Komut istemi
|
||||||
registry-editor = Registry editor
|
registry-editor = Girdi düzenleyicisi
|
||||||
explorer = Explorer
|
explorer = Dosya gezgini
|
||||||
task-manager = Task manager
|
task-manager = Görev yöneticisi
|
||||||
configuration = Configuration
|
configuration = Konfigürasyon
|
||||||
debugger = Debugger
|
debugger = Debug aracı
|
||||||
|
|
||||||
dxvk-version = DXVK versiyonu
|
dxvk-version = DXVK versiyonu
|
||||||
dxvk-selection-disabled = DXVK özelliği Wine grup tercihleriniz yüzünden devre dışı
|
dxvk-selection-disabled = DXVK özelliği Wine grup tercihlerinizden dolayı devre dışı
|
||||||
dxvk-recommended-description = Sadece önerilen dxvk versiyonlarını göster
|
dxvk-recommended-description = Sadece önerilen dxvk versiyonlarını göster
|
||||||
|
|
|
@ -4,13 +4,13 @@ default = Varsayılan
|
||||||
details = Detaylar
|
details = Detaylar
|
||||||
|
|
||||||
width = Genişlik
|
width = Genişlik
|
||||||
height = Uzunlul
|
height = Uzunluk
|
||||||
|
|
||||||
# Menu items
|
# Menu items
|
||||||
|
|
||||||
launcher-folder = İstemci dosyası
|
launcher-folder = İstemci dosyası
|
||||||
game-folder = Oyun dosyası
|
game-folder = Oyun dosyası
|
||||||
config-file = Config dosyaso
|
config-file = Config dosyası
|
||||||
debug-file = Debug dosyası
|
debug-file = Debug dosyası
|
||||||
wish-url = Dilekleri aç
|
wish-url = Dilekleri aç
|
||||||
about = Hakkında
|
about = Hakkında
|
||||||
|
@ -21,17 +21,18 @@ save = Kaydet
|
||||||
continue = Devam et
|
continue = Devam et
|
||||||
exit = Çıkış yap
|
exit = Çıkış yap
|
||||||
check = Kontrol et
|
check = Kontrol et
|
||||||
restart = Tekrardan başlat
|
restart = Tekrardan başlat
|
||||||
|
agree = Onayla
|
||||||
|
|
||||||
|
|
||||||
loading-data = Bilgiler yükleniyor
|
loading-data = Bilgiler yükleniyor
|
||||||
downloading-background-picture = Arkaplan dosyasi indiriliyor
|
downloading-background-picture = Arkaplan dosyası indiriliyor
|
||||||
updating-components-index = Bileşenlerin dizini güncelleniyor
|
updating-components-index = Bileşenlerin dizini güncelleniyor
|
||||||
loading-game-version = Oyun sürümü yükleniyor
|
loading-game-version = Oyun sürümü yükleniyor
|
||||||
loading-patch-status = Yama durumu yükleniyor
|
loading-patch-status = Yama durumu yükleniyor
|
||||||
loading-launcher-state = İstemci durumu yükleniyor
|
loading-launcher-state = İstemci durumu yükleniyor
|
||||||
loading-launcher-state--game = Loading launcher state: oyun versiyonu doğrulanıyor
|
loading-launcher-state--game = Loading launcher state: oyun versiyonu doğrulanıyor
|
||||||
loading-launcher-state--voice = Loading launcher state: {$locale} dublaj doğrulanıyor
|
loading-launcher-state--voice = Loading launcher state: {$locale} seslendirme doğrulanıyor
|
||||||
loading-launcher-state--patch = Loading launcher state: indirilmiş yamanın durumu yükleniyor
|
loading-launcher-state--patch = Loading launcher state: indirilmiş yamanın durumu yükleniyor
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,17 +41,17 @@ downloading = İndiriliyor
|
||||||
unpacking = Paketten çıkartılıyor
|
unpacking = Paketten çıkartılıyor
|
||||||
verifying-files = Dosyalar Doğrulanıyor
|
verifying-files = Dosyalar Doğrulanıyor
|
||||||
repairing-files = Dosyalar tamir ediliyor
|
repairing-files = Dosyalar tamir ediliyor
|
||||||
migrating-folders = Migrating folders
|
migrating-folders = Dosyalar aktarılıyor
|
||||||
applying-hdiff = Applying hdiff patches
|
applying-hdiff = Hdiff yamaları uygulanıyor
|
||||||
removing-outdated = Removing outdated files
|
removing-outdated = Eskimiş dosyalar kaldırılıyor
|
||||||
|
|
||||||
|
|
||||||
components-index-updated = Components index was updated
|
components-index-updated = Bileşenlerin dizini güncellendi
|
||||||
|
|
||||||
|
|
||||||
launch = Çalıştır
|
launch = Çalıştır
|
||||||
migrate-folders = Migrate folders
|
migrate-folders = Dosyaları aktar
|
||||||
migrate-folders-tooltip = Update game folders structure
|
migrate-folders-tooltip = Oyun dosyaları yapısını güncelle
|
||||||
apply-patch = Yamayı uygula
|
apply-patch = Yamayı uygula
|
||||||
download-wine = Wine indir
|
download-wine = Wine indir
|
||||||
create-prefix = Prefix oluştur
|
create-prefix = Prefix oluştur
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
sandbox = Sandbox
|
sandbox = Sanallaştırma
|
||||||
sandbox-description = Run the game in isolated environment, preventing it from accessing your personal data
|
sandbox-description = Oyunu kişisel verilerinize erişemeyeceği, izole bir ortamda çalıştırın
|
||||||
|
|
||||||
enable-sandboxing = Enable sandboxing
|
enable-sandboxing = Sanallaştırmayı aktifleştir
|
||||||
enable-sandboxing-description = Run the game in read-only copy of your root filesystem
|
enable-sandboxing-description = Oyunu root dosya sisteminizin salt-okunur kopyasında çalıştırın
|
||||||
|
|
||||||
hide-home-directory = Hide home directory
|
hide-home-directory = Home dizinini gizle
|
||||||
hide-home-directory-description = Isolate your /home, /var/home/$USER, and $HOME folders from the game
|
hide-home-directory-description = /home, /var/home/$USER, ve $HOME klasörlerini oyundan gizle
|
||||||
|
|
||||||
hostname = Hostname
|
hostname = Host adı
|
||||||
additional-arguments = Additional arguments
|
additional-arguments = Ek argümanlar
|
||||||
|
|
||||||
private-directories = Private directories
|
private-directories = Özel dizinler
|
||||||
private-directories-description = These folders will be replaced by an empty virtual filesystem (tmpfs), and their original content will not be available to sandboxed game
|
private-directories-description = Bu klasörler boş bir sanal dosya sistemiyle değiştirilecektir (tmpfs), ve orijinal içeriklerine sanallaştırılmış oyun erişemeyecektir
|
||||||
|
|
||||||
path = Path
|
path = Yol
|
||||||
|
|
||||||
shared-directories = Shared directories
|
shared-directories = Paylaşılmış dizinler
|
||||||
shared-directories-description = These directories will be symlinked to directories in your host system
|
shared-directories-description = Bu dizinlerden host sisteminizin dizinlerine kısayol oluşturulacaktır
|
||||||
|
|
||||||
original-path = Original path
|
original-path = Orijinal yol
|
||||||
new-path = New path
|
new-path = Yeni yol
|
||||||
|
|
||||||
read-only = Read-only
|
read-only = Salt-okunur
|
||||||
read-only-description = Forbid game to write any data to this directory
|
read-only-description = Oyunun bu dizinde veri oluşturmasını yasakla
|
||||||
|
|
||||||
symlinks = Symlinks
|
symlinks = Kısayollar
|
||||||
symlinks-description = Symlink original path to the new one inside of your sandbox
|
symlinks-description = Orijinal yoldan sanal ortamın içindeki yenisine kısayol oluştur
|
||||||
|
|
|
@ -45,3 +45,11 @@ game-patching-error = 应用游戏补丁失败
|
||||||
# Sandbox
|
# Sandbox
|
||||||
|
|
||||||
documentation-url-open-failed = Failed to open documentation URL
|
documentation-url-open-failed = Failed to open documentation URL
|
||||||
|
|
||||||
|
# Game
|
||||||
|
|
||||||
|
game-session-add-failed = Failed to add game session
|
||||||
|
game-session-update-failed = Failed to update game session
|
||||||
|
game-session-remove-failed = Failed to remove game session
|
||||||
|
game-session-set-current-failed = Failed to set current game session
|
||||||
|
game-session-apply-failed = Failed to apply game session
|
||||||
|
|
|
@ -23,6 +23,11 @@ tos-violation-warning-message =
|
||||||
|
|
||||||
如果你了解并接受通过非官方许可方式玩这款游戏所带来的风险,请单击“确定”。让我们一直抢过提瓦特大陆吧!
|
如果你了解并接受通过非官方许可方式玩这款游戏所带来的风险,请单击“确定”。让我们一直抢过提瓦特大陆吧!
|
||||||
|
|
||||||
|
tos-dialog-title = Are you sure you understand what we want to say?
|
||||||
|
tos-dialog-message =
|
||||||
|
1. Don't publish any information about this project
|
||||||
|
2. Don't abuse it by using some modded clients and so
|
||||||
|
3. Ask questions exceptionally in our discord or matrix server
|
||||||
|
|
||||||
dependencies = 依赖
|
dependencies = 依赖
|
||||||
missing-dependencies-title = 你缺少某些依赖组件
|
missing-dependencies-title = 你缺少某些依赖组件
|
||||||
|
|
7
assets/locales/zh-cn/game.ftl
Normal file
7
assets/locales/zh-cn/game.ftl
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
game-sessions = Game sessions
|
||||||
|
|
||||||
|
active-sessions = Active session
|
||||||
|
active-session-description = Currently selected game session. Updates after each game launch
|
||||||
|
|
||||||
|
update-session = Update session using current wine prefix registry values
|
||||||
|
delete-session = Delete session
|
|
@ -22,6 +22,7 @@ continue = 继续
|
||||||
exit = 退出
|
exit = 退出
|
||||||
check = 检查
|
check = 检查
|
||||||
restart = 重启
|
restart = 重启
|
||||||
|
agree = Agree
|
||||||
|
|
||||||
|
|
||||||
loading-data = 正在加载数据
|
loading-data = 正在加载数据
|
||||||
|
|
|
@ -8,7 +8,7 @@ hide-home-directory = 隐藏家目录
|
||||||
hide-home-directory-description = 将 /home、 /var/home/$USER 和 $HOME 目录与游戏隔离
|
hide-home-directory-description = 将 /home、 /var/home/$USER 和 $HOME 目录与游戏隔离
|
||||||
|
|
||||||
hostname = 主机名
|
hostname = 主机名
|
||||||
additional-arguments = Additional arguments
|
additional-arguments = 额外参数
|
||||||
|
|
||||||
private-directories = 隐私目录
|
private-directories = 隐私目录
|
||||||
private-directories-description = 这些目录将会被空的虚拟文件系统(tmpfs)替代,其中的原始内容不可被沙盒中的游戏访问
|
private-directories-description = 这些目录将会被空的虚拟文件系统(tmpfs)替代,其中的原始内容不可被沙盒中的游戏访问
|
||||||
|
@ -24,5 +24,5 @@ new-path = 新路径
|
||||||
read-only = 只读
|
read-only = 只读
|
||||||
read-only-description = 禁止游戏向此目录写入任何数据
|
read-only-description = 禁止游戏向此目录写入任何数据
|
||||||
|
|
||||||
symlinks = Symlinks
|
symlinks = 软链接
|
||||||
symlinks-description = Symlink original path to the new one inside of your sandbox
|
symlinks-description = 软链接原始路径到沙盒里的新路径
|
||||||
|
|
132
fluentscan.py
Normal file → Executable file
132
fluentscan.py
Normal file → Executable file
|
@ -5,51 +5,118 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import glob
|
||||||
|
import re
|
||||||
|
|
||||||
path = "assets/locales/" + sys.argv[1] + "/"
|
valid_commands = ["diff", "unused", "missing"]
|
||||||
|
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print(f"Command format: ./fluentscan.py [command] [locale]\nAvailable commands: {valid_commands}")
|
||||||
|
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
if sys.argv[1] not in valid_commands:
|
||||||
|
print(f"Invalid command \"{sys.argv[1]}\". Available commands: {valid_commands}")
|
||||||
|
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
path = "assets/locales/" + sys.argv[2] + "/"
|
||||||
|
|
||||||
|
try:
|
||||||
|
open(path + "/main.ftl", "r").close()
|
||||||
|
|
||||||
|
except:
|
||||||
|
print(f"{path} does not exist")
|
||||||
|
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
all_entries = {}
|
||||||
|
|
||||||
|
def dict_compare(d1, d2):
|
||||||
|
d1_keys = set(d1.keys())
|
||||||
|
d2_keys = set(d2.keys())
|
||||||
|
|
||||||
|
shared_keys = d1_keys.intersection(d2_keys)
|
||||||
|
|
||||||
|
added = d1_keys - d2_keys
|
||||||
|
removed = d2_keys - d1_keys
|
||||||
|
|
||||||
|
same = set(o for o in shared_keys if d1[o] == d2[o])
|
||||||
|
|
||||||
|
return added, removed, same
|
||||||
|
|
||||||
|
def to_dict(text):
|
||||||
|
result={}
|
||||||
|
|
||||||
|
for i in text:
|
||||||
|
if " =" in i:
|
||||||
|
try:
|
||||||
|
result[i.split()[0]] = ' '.join(i.split()[2:])
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
elif i:
|
||||||
|
result[list(result.keys())[-1]] += i
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_line_num(text,pattern):
|
||||||
|
line = 1
|
||||||
|
|
||||||
|
for i in text.split("\n"):
|
||||||
|
if pattern in i:
|
||||||
|
return line
|
||||||
|
|
||||||
|
line += 1
|
||||||
|
|
||||||
for filename in os.listdir("assets/locales/en"):
|
for filename in os.listdir("assets/locales/en"):
|
||||||
with open(os.path.join("assets/locales/en", filename), 'r') as locale_file:
|
with open(os.path.join("assets/locales/en", filename), 'r') as locale_file:
|
||||||
created_locale = open(path + filename)
|
created_locale = open(path + filename)
|
||||||
|
|
||||||
def to_dict(text):
|
expected = to_dict(locale_file)
|
||||||
result={}
|
expected2 = to_dict(created_locale)
|
||||||
|
|
||||||
for i in text:
|
all_entries.update(expected)
|
||||||
if " = " in i:
|
|
||||||
try:
|
|
||||||
result[i.split()[0]] = ' '.join(i.split()[2:])
|
|
||||||
|
|
||||||
except:
|
added, removed, same = dict_compare(expected, expected2)
|
||||||
pass
|
|
||||||
|
|
||||||
elif i:
|
if sys.argv[1] == "unused" or sys.argv[1] == "missing":
|
||||||
result[list(result.keys())[-1]] += i
|
files = glob.glob("src/**/*.rs", recursive=True)
|
||||||
|
|
||||||
return result
|
used = []
|
||||||
|
vars = {}
|
||||||
|
|
||||||
def dict_compare(d1, d2):
|
for i in files:
|
||||||
d1_keys = set(d1.keys())
|
with open(i, "r") as script:
|
||||||
d2_keys = set(d2.keys())
|
text = script.read()
|
||||||
|
|
||||||
shared_keys = d1_keys.intersection(d2_keys)
|
if sys.argv[1] == "unused":
|
||||||
|
for j in expected:
|
||||||
|
if f"\"{j}\"" in text:
|
||||||
|
used.append(j)
|
||||||
|
|
||||||
added = d1_keys - d2_keys
|
elif sys.argv[1] == "missing":
|
||||||
removed = d2_keys - d1_keys
|
for j in text.split():
|
||||||
|
# TODO: ignore comments
|
||||||
|
if 'tr("' in j:
|
||||||
|
index = j.find('tr("')
|
||||||
|
|
||||||
modified = {o : (d1[o], d2[o]) for o in shared_keys if d1[o] != d2[o]}
|
var_name = re.sub('[^\\w-]+', '', j[index:].replace('tr("', '').replace("Some", ""))
|
||||||
|
|
||||||
same = set(o for o in shared_keys if d1[o] == d2[o])
|
# TODO: index multiple matches
|
||||||
|
vars[var_name] = [script.name, get_line_num(text,var_name)]
|
||||||
|
|
||||||
return added, removed, modified, same
|
if sys.argv[1] == "unused":
|
||||||
|
for i in expected:
|
||||||
|
if i not in used:
|
||||||
|
print(f"[{locale_file.name}]\n"
|
||||||
|
" [Unused]\n"
|
||||||
|
f" {i}")
|
||||||
|
|
||||||
expected=to_dict(locale_file)
|
continue
|
||||||
expected2=to_dict(created_locale)
|
|
||||||
|
|
||||||
# TODO: why modified is not used?
|
if (added or removed or same) and sys.argv[1] == "diff":
|
||||||
added, removed, modified, same = dict_compare(expected, expected2)
|
|
||||||
|
|
||||||
if added or removed or same:
|
|
||||||
print(f"[{created_locale.name[15:]}]")
|
print(f"[{created_locale.name[15:]}]")
|
||||||
|
|
||||||
if added:
|
if added:
|
||||||
|
@ -72,3 +139,14 @@ for filename in os.listdir("assets/locales/en"):
|
||||||
print(f" {i} = {expected[i]}")
|
print(f" {i} = {expected[i]}")
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
|
if sys.argv[1] == "missing":
|
||||||
|
added, removed, same = dict_compare(vars, all_entries)
|
||||||
|
|
||||||
|
if not added:
|
||||||
|
print("Nothing is missing")
|
||||||
|
|
||||||
|
for i in added:
|
||||||
|
print(f"[{vars[i][0]}, line {vars[i][1]}]\n"
|
||||||
|
" [Missing]\n"
|
||||||
|
f" {i}")
|
||||||
|
|
|
@ -51,10 +51,12 @@ impl SimpleComponent for AboutDialog {
|
||||||
]),
|
]),
|
||||||
|
|
||||||
add_credit_section: (Some("An Anime Team"), &[
|
add_credit_section: (Some("An Anime Team"), &[
|
||||||
|
"Nikita Podvirnyy https://github.com/krypt0nn",
|
||||||
"@Marie https://github.com/Mar0xy",
|
"@Marie https://github.com/Mar0xy",
|
||||||
"@lane https://github.com/laurinneff",
|
"@lane https://github.com/laurinneff",
|
||||||
"@jiro-too https://github.com/jiro-too",
|
"@jiro-too https://github.com/jiro-too",
|
||||||
"@cybik https://github.com/cybik"
|
"@cybik https://github.com/cybik",
|
||||||
|
"@mkrsym1 https://github.com/mkrsym1"
|
||||||
]),
|
]),
|
||||||
|
|
||||||
set_artists: &[
|
set_artists: &[
|
||||||
|
@ -66,7 +68,8 @@ impl SimpleComponent for AboutDialog {
|
||||||
"Deutsch — @Marie https://github.com/Mar0xy",
|
"Deutsch — @Marie https://github.com/Mar0xy",
|
||||||
"Español — Lautaro Garavano https://github.com/Rattlehead15",
|
"Español — Lautaro Garavano https://github.com/Rattlehead15",
|
||||||
"Français — @zeGolem https://github.com/zeGolem",
|
"Français — @zeGolem https://github.com/zeGolem",
|
||||||
"Türk — @Kaozix https://github.com/Kaozix1776",
|
"Türkçe — @Kaozix https://github.com/Kaozix1776",
|
||||||
|
"Türkçe — Kayra Nachfolger https://github.com/kayranachfolger",
|
||||||
"简体中文 — Caibin Chen https://github.com/tigersoldier"
|
"简体中文 — Caibin Chen https://github.com/tigersoldier"
|
||||||
].join("\n"),
|
].join("\n"),
|
||||||
|
|
||||||
|
@ -85,13 +88,25 @@ impl SimpleComponent for AboutDialog {
|
||||||
"<p>Added</p>",
|
"<p>Added</p>",
|
||||||
|
|
||||||
"<ul>",
|
"<ul>",
|
||||||
"<li>Added arguments and symlinks editor to sandbox settings</li>",
|
"<li>Added rules approving dialog to the first run window</li>",
|
||||||
|
"<li>Added game settings section</li>",
|
||||||
|
"<li>Added game sessions manager</li>",
|
||||||
|
"<li>Added `LAUNCHER_FOLDER` variable support</li>",
|
||||||
|
"<li>Added patch repository mirror</li>",
|
||||||
|
"</ul>",
|
||||||
|
|
||||||
|
"<p>Changed</p>",
|
||||||
|
|
||||||
|
"<ul>",
|
||||||
|
"<li>Improved launcher logo rendering quality</li>",
|
||||||
|
"<li>Reworked entry rows in the settings</li>",
|
||||||
"</ul>",
|
"</ul>",
|
||||||
|
|
||||||
"<p>Fixed</p>",
|
"<p>Fixed</p>",
|
||||||
|
|
||||||
"<ul>",
|
"<ul>",
|
||||||
"<li>Fixed game running issue if you have spaces in paths</li>",
|
"<li>Fixed wine tools running using proton builds</li>",
|
||||||
|
"<li>Fixed sandboxed game running (sounds are broken for now)</li>",
|
||||||
"</ul>",
|
"</ul>",
|
||||||
].join("\n"),
|
].join("\n"),
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ use anime_launcher_sdk::is_available;
|
||||||
use crate::i18n::*;
|
use crate::i18n::*;
|
||||||
use super::main::FirstRunAppMsg;
|
use super::main::FirstRunAppMsg;
|
||||||
|
|
||||||
|
use super::main::MAIN_WINDOW;
|
||||||
|
|
||||||
pub struct TosWarningApp;
|
pub struct TosWarningApp;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -86,11 +88,34 @@ impl SimpleAsyncComponent for TosWarningApp {
|
||||||
match msg {
|
match msg {
|
||||||
#[allow(unused_must_use)]
|
#[allow(unused_must_use)]
|
||||||
TosWarningAppMsg::Continue => {
|
TosWarningAppMsg::Continue => {
|
||||||
if is_available("git") && is_available("xdelta3") {
|
let dialog = adw::MessageDialog::new(
|
||||||
sender.output(Self::Output::ScrollToDefaultPaths);
|
unsafe { MAIN_WINDOW.as_ref() },
|
||||||
} else {
|
Some(&tr("tos-dialog-title")),
|
||||||
sender.output(Self::Output::ScrollToDependencies);
|
Some(&tr("tos-dialog-message"))
|
||||||
}
|
);
|
||||||
|
|
||||||
|
dialog.add_responses(&[
|
||||||
|
("exit", &tr("exit")),
|
||||||
|
("continue", &tr("agree"))
|
||||||
|
]);
|
||||||
|
|
||||||
|
dialog.connect_response(None, move |_, response| {
|
||||||
|
match response {
|
||||||
|
"exit" => relm4::main_application().quit(),
|
||||||
|
|
||||||
|
"continue" => {
|
||||||
|
if is_available("git") && is_available("xdelta3") {
|
||||||
|
sender.output(Self::Output::ScrollToDefaultPaths);
|
||||||
|
} else {
|
||||||
|
sender.output(Self::Output::ScrollToDependencies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
TosWarningAppMsg::Exit => relm4::main_application().quit()
|
TosWarningAppMsg::Exit => relm4::main_application().quit()
|
||||||
|
|
|
@ -220,13 +220,15 @@ impl SimpleComponent for App {
|
||||||
set_visible: model.loading.is_none(),
|
set_visible: model.loading.is_none(),
|
||||||
|
|
||||||
add = &adw::PreferencesGroup {
|
add = &adw::PreferencesGroup {
|
||||||
|
set_margin_top: 48,
|
||||||
|
|
||||||
#[watch]
|
#[watch]
|
||||||
set_visible: model.style == LauncherStyle::Modern,
|
set_visible: model.style == LauncherStyle::Modern,
|
||||||
|
|
||||||
gtk::Image {
|
gtk::Picture {
|
||||||
set_resource: Some("/org/app/images/icon.png"),
|
set_resource: Some("/org/app/images/icon.png"),
|
||||||
set_vexpand: true,
|
set_vexpand: true,
|
||||||
set_margin_top: 48
|
set_content_fit: gtk::ContentFit::ScaleDown
|
||||||
},
|
},
|
||||||
|
|
||||||
gtk::Label {
|
gtk::Label {
|
||||||
|
@ -253,6 +255,8 @@ impl SimpleComponent for App {
|
||||||
set_visible: model.downloading,
|
set_visible: model.downloading,
|
||||||
|
|
||||||
set_vexpand: true,
|
set_vexpand: true,
|
||||||
|
set_margin_top: 48,
|
||||||
|
set_margin_bottom: 48,
|
||||||
|
|
||||||
add = model.progress_bar.widget(),
|
add = model.progress_bar.widget(),
|
||||||
},
|
},
|
||||||
|
@ -273,6 +277,12 @@ impl SimpleComponent for App {
|
||||||
#[watch]
|
#[watch]
|
||||||
set_visible: !model.downloading,
|
set_visible: !model.downloading,
|
||||||
|
|
||||||
|
#[watch]
|
||||||
|
set_margin_bottom: match model.style {
|
||||||
|
LauncherStyle::Modern => 48,
|
||||||
|
LauncherStyle::Classic => 0
|
||||||
|
},
|
||||||
|
|
||||||
set_vexpand: true,
|
set_vexpand: true,
|
||||||
|
|
||||||
gtk::Box {
|
gtk::Box {
|
||||||
|
@ -547,11 +557,11 @@ impl SimpleComponent for App {
|
||||||
.detach());
|
.detach());
|
||||||
}
|
}
|
||||||
|
|
||||||
let group = RelmActionGroup::<WindowActionGroup>::new();
|
let mut group = RelmActionGroup::<WindowActionGroup>::new();
|
||||||
|
|
||||||
// TODO: reduce code somehow
|
// TODO: reduce code somehow
|
||||||
|
|
||||||
group.add_action::<LauncherFolder>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
group.add_action::<LauncherFolder>(RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
||||||
if let Err(err) = open::that(LAUNCHER_FOLDER.as_path()) {
|
if let Err(err) = open::that(LAUNCHER_FOLDER.as_path()) {
|
||||||
sender.input(AppMsg::Toast {
|
sender.input(AppMsg::Toast {
|
||||||
title: tr("launcher-folder-opening-error"),
|
title: tr("launcher-folder-opening-error"),
|
||||||
|
@ -562,7 +572,7 @@ impl SimpleComponent for App {
|
||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
|
|
||||||
group.add_action::<GameFolder>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
group.add_action::<GameFolder>(RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
||||||
let path = match Config::get() {
|
let path = match Config::get() {
|
||||||
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
|
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
|
||||||
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
|
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
|
||||||
|
@ -578,7 +588,7 @@ impl SimpleComponent for App {
|
||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
|
|
||||||
group.add_action::<ConfigFile>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
group.add_action::<ConfigFile>(RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
||||||
if let Ok(file) = config_file() {
|
if let Ok(file) = config_file() {
|
||||||
if let Err(err) = open::that(file) {
|
if let Err(err) = open::that(file) {
|
||||||
sender.input(AppMsg::Toast {
|
sender.input(AppMsg::Toast {
|
||||||
|
@ -591,7 +601,7 @@ impl SimpleComponent for App {
|
||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
|
|
||||||
group.add_action::<DebugFile>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
group.add_action::<DebugFile>(RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
||||||
if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) {
|
if let Err(err) = open::that(crate::DEBUG_FILE.as_os_str()) {
|
||||||
sender.input(AppMsg::Toast {
|
sender.input(AppMsg::Toast {
|
||||||
title: tr("debug-file-opening-error"),
|
title: tr("debug-file-opening-error"),
|
||||||
|
@ -602,7 +612,7 @@ impl SimpleComponent for App {
|
||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
|
|
||||||
group.add_action::<WishUrl>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
group.add_action::<WishUrl>(RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
||||||
std::thread::spawn(clone!(@strong sender => move || {
|
std::thread::spawn(clone!(@strong sender => move || {
|
||||||
let config = Config::get().unwrap_or_else(|_| CONFIG.clone());
|
let config = Config::get().unwrap_or_else(|_| CONFIG.clone());
|
||||||
|
|
||||||
|
@ -662,7 +672,7 @@ impl SimpleComponent for App {
|
||||||
}));
|
}));
|
||||||
})));
|
})));
|
||||||
|
|
||||||
group.add_action::<About>(&RelmAction::new_stateless(move |_| {
|
group.add_action::<About>(RelmAction::new_stateless(move |_| {
|
||||||
about_dialog_broker.send(AboutDialogMsg::Show);
|
about_dialog_broker.send(AboutDialogMsg::Show);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -709,10 +719,8 @@ impl SimpleComponent for App {
|
||||||
description: if changes.is_empty() {
|
description: if changes.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let max_len = changes.iter().map(|line| line.len()).max().unwrap_or(80);
|
|
||||||
|
|
||||||
Some(changes.into_iter()
|
Some(changes.into_iter()
|
||||||
.map(|line| format!("- {line}{}", " ".repeat(max_len - line.len())))
|
.map(|line| format!("- {line}"))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n"))
|
.join("\n"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,10 @@ struct Variable {
|
||||||
#[relm4::factory(async)]
|
#[relm4::factory(async)]
|
||||||
impl AsyncFactoryComponent for Variable {
|
impl AsyncFactoryComponent for Variable {
|
||||||
type Init = (String, String);
|
type Init = (String, String);
|
||||||
type Input = EnvironmentMsg;
|
type Input = EnvironmentAppMsg;
|
||||||
type Output = EnvironmentMsg;
|
type Output = EnvironmentAppMsg;
|
||||||
type CommandOutput = ();
|
type CommandOutput = ();
|
||||||
type ParentInput = EnvironmentMsg;
|
type ParentInput = EnvironmentAppMsg;
|
||||||
type ParentWidget = adw::PreferencesGroup;
|
type ParentWidget = adw::PreferencesGroup;
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
|
@ -33,16 +33,12 @@ impl AsyncFactoryComponent for Variable {
|
||||||
set_valign: gtk::Align::Center,
|
set_valign: gtk::Align::Center,
|
||||||
|
|
||||||
connect_clicked[sender, index] => move |_| {
|
connect_clicked[sender, index] => move |_| {
|
||||||
sender.input(EnvironmentMsg::Remove(index.clone()));
|
sender.output(EnvironmentAppMsg::Remove(index.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn output_to_parent_input(output: Self::Output) -> Option<Self::ParentInput> {
|
|
||||||
Some(output)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn init_model(
|
async fn init_model(
|
||||||
init: Self::Init,
|
init: Self::Init,
|
||||||
_index: &DynamicIndex,
|
_index: &DynamicIndex,
|
||||||
|
@ -54,8 +50,8 @@ impl AsyncFactoryComponent for Variable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update(&mut self, msg: Self::Input, sender: AsyncFactorySender<Self>) {
|
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
|
||||||
sender.output(msg);
|
Some(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +63,7 @@ pub struct EnvironmentApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum EnvironmentMsg {
|
pub enum EnvironmentAppMsg {
|
||||||
Add,
|
Add,
|
||||||
Remove(DynamicIndex)
|
Remove(DynamicIndex)
|
||||||
}
|
}
|
||||||
|
@ -75,7 +71,7 @@ pub enum EnvironmentMsg {
|
||||||
#[relm4::component(async, pub)]
|
#[relm4::component(async, pub)]
|
||||||
impl SimpleAsyncComponent for EnvironmentApp {
|
impl SimpleAsyncComponent for EnvironmentApp {
|
||||||
type Init = ();
|
type Init = ();
|
||||||
type Input = EnvironmentMsg;
|
type Input = EnvironmentAppMsg;
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
|
@ -110,6 +106,20 @@ impl SimpleAsyncComponent for EnvironmentApp {
|
||||||
add = &adw::PreferencesGroup {
|
add = &adw::PreferencesGroup {
|
||||||
set_title: &tr("new-variable"),
|
set_title: &tr("new-variable"),
|
||||||
|
|
||||||
|
#[wrap(Some)]
|
||||||
|
set_header_suffix = >k::Button {
|
||||||
|
add_css_class: "flat",
|
||||||
|
|
||||||
|
set_valign: gtk::Align::Center,
|
||||||
|
|
||||||
|
adw::ButtonContent {
|
||||||
|
set_icon_name: "list-add-symbolic",
|
||||||
|
set_label: &tr("add")
|
||||||
|
},
|
||||||
|
|
||||||
|
connect_clicked => EnvironmentAppMsg::Add
|
||||||
|
},
|
||||||
|
|
||||||
#[local_ref]
|
#[local_ref]
|
||||||
name_entry -> adw::EntryRow {
|
name_entry -> adw::EntryRow {
|
||||||
set_title: &tr("name")
|
set_title: &tr("name")
|
||||||
|
@ -118,16 +128,6 @@ impl SimpleAsyncComponent for EnvironmentApp {
|
||||||
#[local_ref]
|
#[local_ref]
|
||||||
value_entry -> adw::EntryRow {
|
value_entry -> adw::EntryRow {
|
||||||
set_title: &tr("value")
|
set_title: &tr("value")
|
||||||
},
|
|
||||||
|
|
||||||
gtk::Button {
|
|
||||||
set_label: &tr("add"),
|
|
||||||
add_css_class: "pill",
|
|
||||||
|
|
||||||
set_margin_top: 8,
|
|
||||||
set_halign: gtk::Align::Start,
|
|
||||||
|
|
||||||
connect_clicked => EnvironmentMsg::Add
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -166,12 +166,12 @@ impl SimpleAsyncComponent for EnvironmentApp {
|
||||||
|
|
||||||
async fn update(&mut self, msg: Self::Input, _sender: AsyncComponentSender<Self>) {
|
async fn update(&mut self, msg: Self::Input, _sender: AsyncComponentSender<Self>) {
|
||||||
match msg {
|
match msg {
|
||||||
EnvironmentMsg::Add => {
|
EnvironmentAppMsg::Add => {
|
||||||
if let Ok(mut config) = Config::get() {
|
let name = self.name_entry.text().trim().to_string();
|
||||||
let name = self.name_entry.text().trim().to_string();
|
let value = self.value_entry.text().trim().to_string();
|
||||||
let value = self.value_entry.text().trim().to_string();
|
|
||||||
|
|
||||||
if !name.is_empty() && !value.is_empty() {
|
if !name.is_empty() && !value.is_empty() {
|
||||||
|
if let Ok(mut config) = Config::get() {
|
||||||
self.name_entry.set_text("");
|
self.name_entry.set_text("");
|
||||||
self.value_entry.set_text("");
|
self.value_entry.set_text("");
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ impl SimpleAsyncComponent for EnvironmentApp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EnvironmentMsg::Remove(index) => {
|
EnvironmentAppMsg::Remove(index) => {
|
||||||
if let Ok(mut config) = Config::get() {
|
if let Ok(mut config) = Config::get() {
|
||||||
if let Some(var) = self.variables.guard().get(index.current_index()) {
|
if let Some(var) = self.variables.guard().get(index.current_index()) {
|
||||||
config.game.environment.remove(&var.key);
|
config.game.environment.remove(&var.key);
|
||||||
|
|
285
src/ui/preferences/game.rs
Normal file
285
src/ui/preferences/game.rs
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
use relm4::prelude::*;
|
||||||
|
use relm4::component::*;
|
||||||
|
use relm4::factory::*;
|
||||||
|
|
||||||
|
use adw::prelude::*;
|
||||||
|
|
||||||
|
use anime_launcher_sdk::sessions::SessionsExt;
|
||||||
|
use anime_launcher_sdk::genshin::sessions::Sessions;
|
||||||
|
|
||||||
|
use super::main::PreferencesAppMsg;
|
||||||
|
|
||||||
|
use crate::i18n::tr;
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct GameSession {
|
||||||
|
name: String,
|
||||||
|
description: Option<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[relm4::factory(async)]
|
||||||
|
impl AsyncFactoryComponent for GameSession {
|
||||||
|
type Init = GameSession;
|
||||||
|
type Input = GameAppMsg;
|
||||||
|
type Output = GameAppMsg;
|
||||||
|
type CommandOutput = ();
|
||||||
|
type ParentInput = GameAppMsg;
|
||||||
|
type ParentWidget = adw::PreferencesGroup;
|
||||||
|
|
||||||
|
view! {
|
||||||
|
root = adw::ActionRow {
|
||||||
|
set_title: &self.name,
|
||||||
|
|
||||||
|
set_subtitle: match &self.description {
|
||||||
|
Some(description) => description.as_str(),
|
||||||
|
None => ""
|
||||||
|
},
|
||||||
|
|
||||||
|
add_suffix = >k::Button {
|
||||||
|
set_icon_name: "view-refresh-symbolic-symbolic",
|
||||||
|
add_css_class: "flat",
|
||||||
|
|
||||||
|
set_tooltip_text: Some(&tr("update-session")),
|
||||||
|
|
||||||
|
set_valign: gtk::Align::Center,
|
||||||
|
|
||||||
|
connect_clicked[sender, index] => move |_| {
|
||||||
|
sender.output(GameAppMsg::UpdateSession(index.clone()));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
add_suffix = >k::Button {
|
||||||
|
set_icon_name: "user-trash-symbolic",
|
||||||
|
add_css_class: "flat",
|
||||||
|
|
||||||
|
set_tooltip_text: Some(&tr("delete-session")),
|
||||||
|
|
||||||
|
set_valign: gtk::Align::Center,
|
||||||
|
|
||||||
|
connect_clicked[sender, index] => move |_| {
|
||||||
|
sender.output(GameAppMsg::RemoveSession(index.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn init_model(
|
||||||
|
init: Self::Init,
|
||||||
|
_index: &DynamicIndex,
|
||||||
|
_sender: AsyncFactorySender<Self>,
|
||||||
|
) -> Self {
|
||||||
|
init
|
||||||
|
}
|
||||||
|
|
||||||
|
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
|
||||||
|
Some(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GameApp {
|
||||||
|
sessions: AsyncFactoryVecDeque<GameSession>,
|
||||||
|
|
||||||
|
sessions_names: Vec<String>,
|
||||||
|
|
||||||
|
sessions_combo: adw::ComboRow,
|
||||||
|
session_name_entry: adw::EntryRow
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum GameAppMsg {
|
||||||
|
AddSession,
|
||||||
|
UpdateSession(DynamicIndex),
|
||||||
|
RemoveSession(DynamicIndex),
|
||||||
|
SetCurrent(u32),
|
||||||
|
UpdateCombo
|
||||||
|
}
|
||||||
|
|
||||||
|
#[relm4::component(async, pub)]
|
||||||
|
impl SimpleAsyncComponent for GameApp {
|
||||||
|
type Init = ();
|
||||||
|
type Input = GameAppMsg;
|
||||||
|
type Output = PreferencesAppMsg;
|
||||||
|
|
||||||
|
view! {
|
||||||
|
adw::PreferencesPage {
|
||||||
|
set_title: &tr("game"),
|
||||||
|
set_icon_name: Some("applications-games-symbolic"),
|
||||||
|
|
||||||
|
add = &adw::PreferencesGroup {
|
||||||
|
set_title: &tr("game-sessions"),
|
||||||
|
|
||||||
|
#[local_ref]
|
||||||
|
sessions_combo -> adw::ComboRow {
|
||||||
|
set_title: &tr("active-sessions"),
|
||||||
|
set_subtitle: &tr("active-session-description"),
|
||||||
|
|
||||||
|
connect_selected_notify[sender] => move |row| sender.input(GameAppMsg::SetCurrent(row.selected()))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
add = &adw::PreferencesGroup {
|
||||||
|
#[local_ref]
|
||||||
|
session_name_entry -> adw::EntryRow {
|
||||||
|
set_title: &tr("name"),
|
||||||
|
|
||||||
|
add_suffix = >k::Button {
|
||||||
|
set_icon_name: "list-add-symbolic",
|
||||||
|
add_css_class: "flat",
|
||||||
|
|
||||||
|
set_valign: gtk::Align::Center,
|
||||||
|
|
||||||
|
connect_clicked => GameAppMsg::AddSession
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
#[local_ref]
|
||||||
|
add = sessions -> adw::PreferencesGroup {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn init(
|
||||||
|
_init: Self::Init,
|
||||||
|
root: Self::Root,
|
||||||
|
sender: AsyncComponentSender<Self>,
|
||||||
|
) -> AsyncComponentParts<Self> {
|
||||||
|
tracing::info!("Initializing game settings");
|
||||||
|
|
||||||
|
let mut model = Self {
|
||||||
|
sessions: AsyncFactoryVecDeque::new(adw::PreferencesGroup::new(), sender.input_sender()),
|
||||||
|
|
||||||
|
sessions_names: Vec::new(),
|
||||||
|
|
||||||
|
sessions_combo: adw::ComboRow::new(),
|
||||||
|
session_name_entry: adw::EntryRow::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
for (name, _) in Sessions::list().unwrap_or_default() {
|
||||||
|
model.sessions.guard().push_back(GameSession {
|
||||||
|
name: name.clone(),
|
||||||
|
description: None
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let sessions = model.sessions.widget();
|
||||||
|
|
||||||
|
let sessions_combo = &model.sessions_combo;
|
||||||
|
let session_name_entry = &model.session_name_entry;
|
||||||
|
|
||||||
|
let widgets = view_output!();
|
||||||
|
|
||||||
|
sender.input(GameAppMsg::UpdateCombo);
|
||||||
|
|
||||||
|
AsyncComponentParts { model, widgets }
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update(&mut self, msg: Self::Input, sender: AsyncComponentSender<Self>) {
|
||||||
|
match msg {
|
||||||
|
GameAppMsg::AddSession => {
|
||||||
|
let name = self.session_name_entry.text().trim().to_string();
|
||||||
|
|
||||||
|
if !name.is_empty() {
|
||||||
|
if let Ok(config) = Config::get() {
|
||||||
|
self.session_name_entry.set_text("");
|
||||||
|
|
||||||
|
match Sessions::update(name.clone(), config.get_wine_prefix_path()) {
|
||||||
|
Ok(()) => {
|
||||||
|
self.sessions.guard().push_back(GameSession {
|
||||||
|
name,
|
||||||
|
description: None
|
||||||
|
});
|
||||||
|
|
||||||
|
sender.input(GameAppMsg::UpdateCombo);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_must_use)]
|
||||||
|
Err(err) => {
|
||||||
|
sender.output(PreferencesAppMsg::Toast {
|
||||||
|
title: tr("game-session-add-failed"),
|
||||||
|
description: Some(err.to_string())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameAppMsg::UpdateSession(index) => {
|
||||||
|
if let Some(session) = self.sessions.guard().get(index.current_index()) {
|
||||||
|
if let Ok(config) = Config::get() {
|
||||||
|
#[allow(unused_must_use)]
|
||||||
|
if let Err(err) = Sessions::update(session.name.clone(), config.get_wine_prefix_path()) {
|
||||||
|
sender.output(PreferencesAppMsg::Toast {
|
||||||
|
title: tr("game-session-update-failed"),
|
||||||
|
description: Some(err.to_string())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameAppMsg::RemoveSession(index) => {
|
||||||
|
if let Some(session) = self.sessions.guard().get(index.current_index()) {
|
||||||
|
match Sessions::remove(&session.name) {
|
||||||
|
Ok(()) => sender.input(GameAppMsg::UpdateCombo),
|
||||||
|
|
||||||
|
#[allow(unused_must_use)]
|
||||||
|
Err(err) => {
|
||||||
|
sender.output(PreferencesAppMsg::Toast {
|
||||||
|
title: tr("game-session-remove-failed"),
|
||||||
|
description: Some(err.to_string())
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.sessions.guard().remove(index.current_index());
|
||||||
|
}
|
||||||
|
|
||||||
|
GameAppMsg::SetCurrent(id) => {
|
||||||
|
if let Some(name) = self.sessions_names.get(id as usize) {
|
||||||
|
if let Ok(config) = Config::get() {
|
||||||
|
#[allow(unused_must_use)]
|
||||||
|
if let Err(err) = Sessions::set_current(name.to_owned()) {
|
||||||
|
sender.output(PreferencesAppMsg::Toast {
|
||||||
|
title: tr("game-session-set-current-failed"),
|
||||||
|
description: Some(err.to_string())
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prevent session applying
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_must_use)]
|
||||||
|
if let Err(err) = Sessions::apply(name.to_owned(), config.get_wine_prefix_path()) {
|
||||||
|
sender.output(PreferencesAppMsg::Toast {
|
||||||
|
title: tr("game-session-apply-failed"),
|
||||||
|
description: Some(err.to_string())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameAppMsg::UpdateCombo => {
|
||||||
|
let sessions = Sessions::get_sessions().unwrap_or_default();
|
||||||
|
|
||||||
|
self.sessions_names = sessions.sessions.into_keys().collect::<Vec<String>>();
|
||||||
|
|
||||||
|
let mut selected = 0;
|
||||||
|
|
||||||
|
for (i, name) in self.sessions_names.iter().enumerate() {
|
||||||
|
if sessions.current.as_ref() == Some(name) {
|
||||||
|
selected = i as u32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.sessions_combo.set_model(Some(>k::StringList::new(&self.sessions_names.iter().map(|name: &String| name.as_str()).collect::<Vec<&str>>())));
|
||||||
|
self.sessions_combo.set_selected(selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -84,10 +84,6 @@ impl AsyncFactoryComponent for VoicePackageComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn output_to_parent_input(output: Self::Output) -> Option<Self::ParentInput> {
|
|
||||||
Some(output)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn init_model(
|
async fn init_model(
|
||||||
init: Self::Init,
|
init: Self::Init,
|
||||||
_index: &DynamicIndex,
|
_index: &DynamicIndex,
|
||||||
|
@ -105,6 +101,10 @@ impl AsyncFactoryComponent for VoicePackageComponent {
|
||||||
|
|
||||||
sender.output(msg);
|
sender.output(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
|
||||||
|
Some(output)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GeneralApp {
|
pub struct GeneralApp {
|
||||||
|
@ -1035,7 +1035,8 @@ impl SimpleAsyncComponent for GeneralApp {
|
||||||
let config = Config::get().unwrap_or_else(|_| CONFIG.clone());
|
let config = Config::get().unwrap_or_else(|_| CONFIG.clone());
|
||||||
|
|
||||||
if let Ok(Some(wine)) = config.get_selected_wine() {
|
if let Ok(Some(wine)) = config.get_selected_wine() {
|
||||||
let result = wine.to_wine(config.components.path, Some(config.game.wine.builds.join(&wine.name)))
|
let result = wine
|
||||||
|
.to_wine(config.components.path, Some(config.game.wine.builds.join(&wine.name)))
|
||||||
.with_prefix(config.game.wine.prefix)
|
.with_prefix(config.game.wine.prefix)
|
||||||
.with_loader(WineLoader::Current)
|
.with_loader(WineLoader::Current)
|
||||||
.with_arch(WineArch::Win64)
|
.with_arch(WineArch::Win64)
|
||||||
|
|
|
@ -15,6 +15,7 @@ use crate::i18n::tr;
|
||||||
|
|
||||||
use super::general::*;
|
use super::general::*;
|
||||||
use super::enhancements::*;
|
use super::enhancements::*;
|
||||||
|
use super::game::*;
|
||||||
use super::sandbox::*;
|
use super::sandbox::*;
|
||||||
use super::environment::*;
|
use super::environment::*;
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ pub static mut PREFERENCES_WINDOW: Option<adw::PreferencesWindow> = None;
|
||||||
pub struct PreferencesApp {
|
pub struct PreferencesApp {
|
||||||
general: AsyncController<GeneralApp>,
|
general: AsyncController<GeneralApp>,
|
||||||
enhancements: AsyncController<EnhancementsApp>,
|
enhancements: AsyncController<EnhancementsApp>,
|
||||||
|
game: AsyncController<GameApp>,
|
||||||
sandbox: AsyncController<SandboxApp>,
|
sandbox: AsyncController<SandboxApp>,
|
||||||
environment: AsyncController<EnvironmentApp>
|
environment: AsyncController<EnvironmentApp>
|
||||||
}
|
}
|
||||||
|
@ -69,6 +71,7 @@ impl SimpleAsyncComponent for PreferencesApp {
|
||||||
|
|
||||||
add = model.general.widget(),
|
add = model.general.widget(),
|
||||||
add = model.enhancements.widget(),
|
add = model.enhancements.widget(),
|
||||||
|
add = model.game.widget(),
|
||||||
add = model.sandbox.widget(),
|
add = model.sandbox.widget(),
|
||||||
add = model.environment.widget(),
|
add = model.environment.widget(),
|
||||||
|
|
||||||
|
@ -101,6 +104,10 @@ impl SimpleAsyncComponent for PreferencesApp {
|
||||||
.launch(())
|
.launch(())
|
||||||
.detach(),
|
.detach(),
|
||||||
|
|
||||||
|
game: GameApp::builder()
|
||||||
|
.launch(())
|
||||||
|
.detach(),
|
||||||
|
|
||||||
sandbox: SandboxApp::builder()
|
sandbox: SandboxApp::builder()
|
||||||
.launch(())
|
.launch(())
|
||||||
.forward(sender.input_sender(), std::convert::identity),
|
.forward(sender.input_sender(), std::convert::identity),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
pub mod main;
|
pub mod main;
|
||||||
pub mod general;
|
pub mod general;
|
||||||
pub mod enhancements;
|
pub mod enhancements;
|
||||||
|
pub mod game;
|
||||||
pub mod sandbox;
|
pub mod sandbox;
|
||||||
pub mod environment;
|
pub mod environment;
|
||||||
pub mod gamescope;
|
pub mod gamescope;
|
||||||
|
|
|
@ -7,6 +7,7 @@ use adw::prelude::*;
|
||||||
use anime_launcher_sdk::is_available;
|
use anime_launcher_sdk::is_available;
|
||||||
|
|
||||||
use super::main::PreferencesAppMsg;
|
use super::main::PreferencesAppMsg;
|
||||||
|
|
||||||
use crate::i18n::tr;
|
use crate::i18n::tr;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
|
@ -41,16 +42,12 @@ macro_rules! impl_directory {
|
||||||
set_valign: gtk::Align::Center,
|
set_valign: gtk::Align::Center,
|
||||||
|
|
||||||
connect_clicked[sender, index] => move |_| {
|
connect_clicked[sender, index] => move |_| {
|
||||||
sender.input($msg(index.clone()));
|
sender.output($msg(index.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn output_to_parent_input(output: Self::Output) -> Option<Self::ParentInput> {
|
|
||||||
Some(output)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn init_model(
|
async fn init_model(
|
||||||
init: Self::Init,
|
init: Self::Init,
|
||||||
_index: &DynamicIndex,
|
_index: &DynamicIndex,
|
||||||
|
@ -62,8 +59,8 @@ macro_rules! impl_directory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update(&mut self, msg: Self::Input, sender: AsyncFactorySender<Self>) {
|
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
|
||||||
sender.output(msg);
|
Some(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,8 +194,10 @@ impl SimpleAsyncComponent for SandboxApp {
|
||||||
},
|
},
|
||||||
|
|
||||||
add_suffix = >k::Button {
|
add_suffix = >k::Button {
|
||||||
set_valign: gtk::Align::Center,
|
|
||||||
set_icon_name: "dialog-information-symbolic",
|
set_icon_name: "dialog-information-symbolic",
|
||||||
|
add_css_class: "flat",
|
||||||
|
|
||||||
|
set_valign: gtk::Align::Center,
|
||||||
|
|
||||||
connect_clicked[sender] => move |_| {
|
connect_clicked[sender] => move |_| {
|
||||||
if let Err(err) = open::that("https://man.archlinux.org/man/bwrap.1") {
|
if let Err(err) = open::that("https://man.archlinux.org/man/bwrap.1") {
|
||||||
|
@ -218,17 +217,16 @@ impl SimpleAsyncComponent for SandboxApp {
|
||||||
|
|
||||||
#[local_ref]
|
#[local_ref]
|
||||||
private_path_entry -> adw::EntryRow {
|
private_path_entry -> adw::EntryRow {
|
||||||
set_title: &tr("path")
|
set_title: &tr("path"),
|
||||||
},
|
|
||||||
|
|
||||||
gtk::Button {
|
add_suffix = >k::Button {
|
||||||
set_label: &tr("add"),
|
set_icon_name: "list-add-symbolic",
|
||||||
add_css_class: "pill",
|
add_css_class: "flat",
|
||||||
|
|
||||||
set_margin_top: 8,
|
set_valign: gtk::Align::Center,
|
||||||
set_halign: gtk::Align::Start,
|
|
||||||
|
connect_clicked => SandboxAppMsg::AddPrivate
|
||||||
connect_clicked => SandboxAppMsg::AddPrivate
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -239,6 +237,20 @@ impl SimpleAsyncComponent for SandboxApp {
|
||||||
set_title: &tr("shared-directories"),
|
set_title: &tr("shared-directories"),
|
||||||
set_description: Some(&tr("shared-directories-description")),
|
set_description: Some(&tr("shared-directories-description")),
|
||||||
|
|
||||||
|
#[wrap(Some)]
|
||||||
|
set_header_suffix = >k::Button {
|
||||||
|
add_css_class: "flat",
|
||||||
|
|
||||||
|
set_valign: gtk::Align::Center,
|
||||||
|
|
||||||
|
adw::ButtonContent {
|
||||||
|
set_icon_name: "list-add-symbolic",
|
||||||
|
set_label: &tr("add")
|
||||||
|
},
|
||||||
|
|
||||||
|
connect_clicked => SandboxAppMsg::AddShared
|
||||||
|
},
|
||||||
|
|
||||||
#[local_ref]
|
#[local_ref]
|
||||||
shared_path_from_entry -> adw::EntryRow {
|
shared_path_from_entry -> adw::EntryRow {
|
||||||
set_title: &tr("original-path")
|
set_title: &tr("original-path")
|
||||||
|
@ -257,16 +269,6 @@ impl SimpleAsyncComponent for SandboxApp {
|
||||||
add_suffix = read_only_switch -> gtk::Switch {
|
add_suffix = read_only_switch -> gtk::Switch {
|
||||||
set_valign: gtk::Align::Center
|
set_valign: gtk::Align::Center
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
gtk::Button {
|
|
||||||
set_label: &tr("add"),
|
|
||||||
add_css_class: "pill",
|
|
||||||
|
|
||||||
set_margin_top: 8,
|
|
||||||
set_halign: gtk::Align::Start,
|
|
||||||
|
|
||||||
connect_clicked => SandboxAppMsg::AddShared
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -277,6 +279,20 @@ impl SimpleAsyncComponent for SandboxApp {
|
||||||
set_title: &tr("symlinks"),
|
set_title: &tr("symlinks"),
|
||||||
set_description: Some(&tr("symlinks-description")),
|
set_description: Some(&tr("symlinks-description")),
|
||||||
|
|
||||||
|
#[wrap(Some)]
|
||||||
|
set_header_suffix = >k::Button {
|
||||||
|
add_css_class: "flat",
|
||||||
|
|
||||||
|
set_valign: gtk::Align::Center,
|
||||||
|
|
||||||
|
adw::ButtonContent {
|
||||||
|
set_icon_name: "list-add-symbolic",
|
||||||
|
set_label: &tr("add")
|
||||||
|
},
|
||||||
|
|
||||||
|
connect_clicked => SandboxAppMsg::AddSymlink
|
||||||
|
},
|
||||||
|
|
||||||
#[local_ref]
|
#[local_ref]
|
||||||
symlink_path_from_entry -> adw::EntryRow {
|
symlink_path_from_entry -> adw::EntryRow {
|
||||||
set_title: &tr("original-path")
|
set_title: &tr("original-path")
|
||||||
|
@ -285,16 +301,6 @@ impl SimpleAsyncComponent for SandboxApp {
|
||||||
#[local_ref]
|
#[local_ref]
|
||||||
symlink_path_to_entry -> adw::EntryRow {
|
symlink_path_to_entry -> adw::EntryRow {
|
||||||
set_title: &tr("new-path")
|
set_title: &tr("new-path")
|
||||||
},
|
|
||||||
|
|
||||||
gtk::Button {
|
|
||||||
set_label: &tr("add"),
|
|
||||||
add_css_class: "pill",
|
|
||||||
|
|
||||||
set_margin_top: 8,
|
|
||||||
set_halign: gtk::Align::Start,
|
|
||||||
|
|
||||||
connect_clicked => SandboxAppMsg::AddSymlink
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue