Compare commits

...

122 Commits

Author SHA1 Message Date
Jonas Dellinger c5229c6a62 adjust some small store stylings (#471) 2023-05-30 16:35:42 -07:00
Marco Rodolfi c631d40aa3 Missed a toaster for the react tools 2023-05-30 19:32:41 +02:00
Jonas Dellinger d21b221575 quick fix: overwrite plugin list marginTop to be always 0 2023-05-29 18:40:17 +02:00
Jonas Dellinger 010feddf36 Add update all button to plugin list (#466) 2023-05-29 09:29:36 -07:00
WerWolvTranslationBot 5114bb5711 Translations update from Weblate (#467)
* Translated using Weblate (Italian)

Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/it/

* Translated using Weblate (German)

Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/de/

---------

Co-authored-by: Marco Rodolfi <marco.rodolfi@tuta.io>
Co-authored-by: Jonas Dellinger <jonas@dellinger.dev>
2023-05-28 14:57:14 +02:00
Marco Rodolfi 4e7001efd6 Merge remote-tracking branch 'weblate/main' 2023-05-28 13:48:22 +02:00
Weblate 0c9d90df10 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-28 13:46:51 +02:00
Weblate 09963ef4bb Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-28 13:46:14 +02:00
Weblate 2f24454b1e Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-28 13:46:14 +02:00
Weblate 177ed35522 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-28 13:46:14 +02:00
Weblate c5aeb018db Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-28 13:46:14 +02:00
Weblate 671120a517 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-28 13:46:14 +02:00
Weblate f306239b5f Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-28 13:46:11 +02:00
WerWolvTranslationBot 44859be657 Translations update from Weblate (#465)
* Update translation files

Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/

* Added translation using Weblate (German)

* Update translation files

Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/

* Update translation files

Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/

* Update translation files

Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/

* Update translation files

Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/

* Update translation files

Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/

* Update translation files

Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/

* Update translation files

Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/

---------

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: DarkSide1305 <darkside1305@web.de>
2023-05-28 11:06:03 +02:00
Weblate ee4c706529 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-27 18:03:47 +00:00
Weblate 5ca3015609 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-27 18:03:47 +00:00
Weblate 8b05fb6943 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-27 18:03:47 +00:00
Weblate e4ebbed477 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-27 18:03:47 +00:00
Weblate d13536955e Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-27 18:03:47 +00:00
Weblate 37462548b3 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-27 18:03:47 +00:00
Weblate 74d06aaca6 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-27 18:03:47 +00:00
DarkSide1305 1934d12aac Added translation using Weblate (German) 2023-05-27 18:03:47 +00:00
Weblate 70bd5adad3 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-27 18:03:47 +00:00
Marco Rodolfi f9d5c4ba2a Merge branch 'main' of github.com:SteamDeckHomebrew/decky-loader 2023-05-27 20:03:25 +02:00
Marco Rodolfi cc5e6ac24d Small code cleanup. 2023-05-27 20:02:47 +02:00
Party Wumpus d44ce0f74b Nouns don't have gender in english 2023-05-27 18:44:03 +01:00
Marco Rodolfi 687f7bf5db Simplified the translation error. 2023-05-27 19:23:15 +02:00
Marco Rodolfi 9cd219fab7 Simplified error message. 2023-05-27 14:26:25 +02:00
Marco Rodolfi 6e6f8caca8 Unified translation classes, fixed missing toaster translation and improved the error styling report. 2023-05-27 13:55:26 +02:00
Marco Rodolfi 3a83062438 Simplified inlining and cleaning up unused translations 2023-05-26 14:08:09 +02:00
Marco Rodolfi dfdad14ede Fix: actually force the cog icon to stay inline 2023-05-26 13:29:47 +02:00
Marco Rodolfi 852897c502 Fixed untranslated error message and added french suffix country code. 2023-05-26 12:14:40 +02:00
Marco Rodolfi 9e502f85fa Missed cleaning up new languages. 2023-05-25 19:45:18 +02:00
Marco Rodolfi 368a1044da Fixed file names for language strings. 2023-05-25 17:02:36 +02:00
Marco Rodolfi 578b8b3ee2 Merge remote-tracking branch 'weblate/main' 2023-05-25 16:58:59 +02:00
Marco Rodolfi ede1067bb3 [Hotfix] Wrong key name interpreted as plural (#459) 2023-05-20 15:07:59 -07:00
judgmentkazzy00 bec1c61366 Translated using Weblate (Spanish)
Currently translated at 50.0% (50 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/es/
2023-05-20 22:07:13 +00:00
david082321 5d2cc1c133 Translated using Weblate (Chinese (Traditional))
Currently translated at 99.0% (99 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/zh_Hant/
2023-05-20 22:07:13 +00:00
Sean ef97921e30 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/zh_Hans/
2023-05-20 22:07:13 +00:00
Marco Rodolfi 0009a53800 Translated using Weblate (Italian)
Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/it/
2023-05-20 22:07:13 +00:00
Marco Rodolfi 3eff60e8aa Translated using Weblate (English)
Currently translated at 99.0% (99 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/en/
2023-05-20 22:07:13 +00:00
marios cbfa548f98 Translated using Weblate (Greek)
Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/el/
2023-05-20 22:07:13 +00:00
EMERALD 3f2d54ddbd Translated using Weblate (Spanish)
Currently translated at 7.0% (7 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/es/
2023-05-20 22:07:13 +00:00
Adem Odza 0ecc9bf579 Translated using Weblate (Albanian)
Currently translated at 51.0% (51 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/sq/
2023-05-20 22:07:13 +00:00
Weblate 88b9984b0f Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate d6c025da1c Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 7ba864136f Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate d5dda39add Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 320f392ad3 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 47388b1083 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
marios c1edb9f2e9 Added translation using Weblate (Greek) 2023-05-20 22:07:13 +00:00
Weblate d184e1c4af Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 88a4c0c361 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate ff1f902c91 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate c1215072a9 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate ad3fc990f5 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate d3038efd45 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
EMERALD 92b953a22d Added translation using Weblate (Spanish) 2023-05-20 22:07:13 +00:00
Weblate 9accb676e6 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate ba9f12ffe7 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate a4f8f5fcf5 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 4400226c2d Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 6e6ef81e66 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate c4a4249440 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Adem Odza a4e02b8201 Added translation using Weblate (Albanian) 2023-05-20 22:07:13 +00:00
Weblate ea56b03b38 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Anonymous 3fe1d44515 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/zh_Hant/
2023-05-20 22:07:13 +00:00
Anonymous 3932c69ad6 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/zh_Hans/
2023-05-20 22:07:13 +00:00
Weblate 1b8fe4f82f Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Anonymous 67dc7e7893 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/zh_Hant/
2023-05-20 22:07:13 +00:00
Anonymous c14f7043bc Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/zh_Hans/
2023-05-20 22:07:13 +00:00
Anonymous 6d47a2111b Translated using Weblate (French)
Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/fr/
2023-05-20 22:07:13 +00:00
Anonymous aceeaeee07 Translated using Weblate (Italian)
Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/it/
2023-05-20 22:07:13 +00:00
AAGaming a77ad33ea0 Deleted translation using Weblate (Greek) 2023-05-20 22:07:13 +00:00
Marco Rodolfi e2691592ba Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/zh_Hant/
2023-05-20 22:07:13 +00:00
Marco Rodolfi 3d8629b803 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/zh_Hans/
2023-05-20 22:07:13 +00:00
elliotfontaine 4c5468ae97 Translated using Weblate (French)
Currently translated at 100.0% (100 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/fr/
2023-05-20 22:07:13 +00:00
Weblate 81cb3dd0ec Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate f94866f473 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate d4a4d2287a Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 4cfeb8ef3e Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 826e014456 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 9fb211316d Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate ba01ad6e13 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Marco Rodolfi d0b897ff7f Added translation using Weblate (Chinese (Traditional)) 2023-05-20 22:07:13 +00:00
Weblate dd3d313517 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 83faf6697b Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 7bc2187c8c Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 8a61ecc71a Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 579d52982a Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate d895b7c0ef Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate a3f6004fd9 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Marco Rodolfi 73c5a890ce Added translation using Weblate (Chinese (Simplified)) 2023-05-20 22:07:13 +00:00
elliotfontaine 0cb0fb7165 Translated using Weblate (French)
Currently translated at 4.0% (4 of 100 strings)

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/fr/
2023-05-20 22:07:13 +00:00
Weblate 5376478b2d Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate c74cfc51e7 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 6b10c87648 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 8ab0b34a2e Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate b5aeee505a Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate d7f343aac4 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
elliotfontaine 1eacdc4bce Added translation using Weblate (French) 2023-05-20 22:07:13 +00:00
Weblate a2e2335dd9 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 6882de6027 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate fccadefe47 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 70a4b26984 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 39206b782e Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
Weblate 3ca625d838 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Decky/Decky
Translate-URL: https://weblate.werwolv.net/projects/decky/decky/
2023-05-20 22:07:13 +00:00
marios 1042655eb9 Added translation using Weblate (Greek) 2023-05-20 22:07:13 +00:00
suchmememanyskill cad2babbca Add env var to not replace systemd service file (#462) 2023-05-20 15:07:09 -07:00
Party Wumpus dbd1ea9543 move pull request template 2023-05-18 18:45:15 +01:00
Party Wumpus 313f6db5fa Update and rename pull_request.md to pull_request_template.md 2023-05-18 18:43:59 +01:00
Party Wumpus 3b58001abe github pull requests don't do yml :( 2023-05-18 18:36:33 +01:00
Party Wumpus bf99bce579 Create new_feature.yml 2023-05-18 18:29:52 +01:00
Party Wumpus 9c02ccc537 Fix formatting of translation badge 2023-05-18 11:23:47 +01:00
AAGaming fedbfcb041 add Weblate badge
yeah the formatting is different I'll fix it later because GitHub mobile doesn't let me
2023-05-18 06:18:06 -04:00
Marco Rodolfi 3c52b33e18 [Hotfix] Windows lang fix (#457)
* Hotfix for i18n where the detector was overriding localStorage

* Please, pnpm, cooperate

* Small fix regarding the backend getting hammered when switching to not supported languages plus a small english typo

* Typo on translation variable

* Hotfix: Fix for missing locale data on windows
2023-05-18 03:03:19 -07:00
AAGaming d99f332523 Initial implementation of global DFL instance (#451) 2023-05-11 22:02:04 -04:00
Party Wumpus 0c83c9a2b5 Bump DFL to 3.20.7 (#449) 2023-05-10 22:12:27 +01:00
Marco Rodolfi 6b14f08d59 Hotfix: wrong variable name for English translation (#444) 2023-05-09 15:40:57 -07:00
Marco Rodolfi 089e6b086c Small fix: handle missing localization in backend plus a small typo in the english language (#443)
* Hotfix for i18n where the detector was overriding localStorage

* Please, pnpm, cooperate

* Small fix regarding the backend getting hammered when switching to not supported languages plus a small english typo
2023-05-04 16:46:00 +01:00
Marco Rodolfi 08d5c942a4 Hotfix for i18n where the detector was overriding localStorage (#439)
* Hotfix for i18n where the detector was overriding localStorage

* Please, pnpm, cooperate
2023-05-03 21:51:18 +01:00
Marco Rodolfi 35e7c80835 [Feature] Implement internazionalization for Decky Loader (#361)
* First iteration for internationalization of the loader

* First iteration for internationalization of the loader

* Cleanup node mess

* Cleanup node mess pt2

* Additional touches

* Latest decky changed merged into i18n and updated translation.

* Styling fixes

* Initial backend hosting implementation

* Added correct url path of the loopback server.

* Added correct url path of the loopback server.

* Some better namespaced text.

* Added whitelist for locales path.

* Refactor languages and fix hooks logic bugs.

* Small typo in language translation structure.

* Working backend, automatically swtich languages with steam and language fixes.

* Fix to languages

* Key fixes

* Additional language fixes.

* Additional json changes

* Final text revision and added a vscode tasks to automatically extract text from code.

* Typo in the middleware

* Remove unused imports

* Cleanup whitespaces.

* Import changes

* Revert "Import changes"

This reverts commit 8e8231950f.

* Update index.d.ts

* Clean up unused imports

* Delete pnpm-lock.yaml

* Update rollup.config.js

* Update PluginInstallModal.tsx

* Update index.tsx

* Update plugin-loader.tsx

* Update plugin-loader.tsx

* Revert "Delete pnpm-lock.yaml"

This reverts commit 3a39f36f21.

* Additional strings reworks.

* Fixes for issues coming from github merge.

* Fixes for master

* Styling fixes

* Styling pt2

* Missed a few strings in master,

* Styling fixes

* Additional master merge fixes.

* Final cleanup and adaptation to master.

* Final empty language cleanup and few string added

* Small changes to italian translation

* Disabled translation on a few components inside plugin-loader for missing react hooks.

* Fixed passing tag to translation.

* Disable debug output for reducing console spam.

* Return correct content type

* Small italian language change

* Added support for country code

* Fixed missing translation for uninstall popup.

* Fix class name shenanigans for  toast notification

* Update dependencies

* Fixed github workflow to include the new locales folder

* Update dependencies to latest version (unless it's React) and fixed the new small errors that cropped up

* Missed a file name change

* Updated dev dependencies to latest version

* Missed a few dev dependencies

* Revert "Update dependencies to latest version (unless it's React) and fixed the new small errors that cropped up"

Messed up merge with a different main branch

* Messed up deletion of rollup config.

* Fix broken pnpm lock file

* Missed a localized string during the merge

* Fixed a parameter mistake in the uninstall text parameter

* Fix pnpm random issues

* Small italian language tweaks

* Fix wrong parameter passed to the uninstall function call

* Another fix on a wrong function parameter

* Additional translation text on the store and branch selection channels

* Changed the default type passed to map to being able to index the two arrays.

* Reverted and reworked the last changes

* Distinguish events in UI for installing vs reinstalling plugins

* Additional fixes for reinstall prompt

* Revert the use of intevalPlural since the parser doesn't seem to support that.

* Missed a routing path in the backend

* Small bugfixes

* Small fixes

* Correctly adding the parameter to the request headers.

* Refactoring of the UI popup modal

* Fix pnpm shenanigans

* Final fixes for the install UI localization

* Clean up unnedeed backend code

* Small rework on text selection.

* Cleaned up parser configuration

* Removed extracttext dependency to pnpmsetup

* Merged translation and cleaned up parser

* Fixed JSON structure after manual merge.

* Added translation to the file picker

* Revert changes to PluginInstallModal

* Reworked the text modal for the final time

* Missed the proper linted text

* Missed the backend change

* Final branch cleanup

* Fixed small translation bleeding

Caused from the manual merge of _old.json files.

* fix extra space in browser.py

* fix extra newline in plugin-loader.tsx

* Cleanup i18next-parser.config.mjs

* Update plugin-loader.tsx

* Cleanup language files

* Better labeling of text

* Fixed language typos in BranchSelect

* Fixed language typos in StoreSelect

* Cleanup plugin-loader.tsx from unused imports

* Removed the path bypass since I'm using authentication from the frontend.

* Reimplemented this component as a functional component.

* Updated dependencies and lockfile

* Removed static route from main.py

Already handled in loader.py

* Small italian coherency fixes

* Fix small typography fixes on plugin name uninstall

* Fixed italian typo on removal popup

* Reenabled manual escaping value in i18next

* Set to fallback to the default language if the string in the JSON file is empty.

* Fixed pnpm wankery

* Added a missed italian text translation string

---------

Co-authored-by: AAGaming <aa@mail.catvibers.me>
2023-05-02 16:42:39 +01:00
43 changed files with 3829 additions and 570 deletions
+13
View File
@@ -0,0 +1,13 @@
Please tick as appropriate:
- [ ] I have tested this code on a steam deck or on a PC
- [ ] My changes generate no new errors/warnings
- [ ] This is a bugfix/hotfix
- [ ] This is a new feature
If you're wanting to update a translation or add a new one, please use the weblate page: https://weblate.werwolv.net/projects/decky/
# Description
This fixes issue: #
Please provide a clear and concise description of what the new feature is. If appropriate, include screenshots or videos.
+2 -2
View File
@@ -69,7 +69,7 @@ jobs:
run: pnpm run build
- name: Build Python Backend 🛠️
run: pyinstaller --noconfirm --onefile --name "PluginLoader" --add-data ./backend/static:/static --add-data ./backend/legacy:/legacy --add-data ./plugin:/plugin ./backend/*.py
run: pyinstaller --noconfirm --onefile --name "PluginLoader" --add-data ./backend/static:/static --add-data ./backend/locales:/locales --add-data ./backend/legacy:/legacy --add-data ./plugin:/plugin ./backend/*.py
- name: Upload package artifact ⬆️
if: ${{ !env.ACT }}
@@ -119,7 +119,7 @@ jobs:
run: pnpm run build
- name: Build Python Backend 🛠️
run: pyinstaller --noconfirm --onefile --name "PluginLoader" --add-data "./backend/static;/static" --add-data "./backend/legacy;/legacy" --add-data "./plugin;/plugin" ./backend/main.py
run: pyinstaller --noconfirm --onefile --name "PluginLoader" --add-data "./backend/static;/static" --add-data "./backend/locales;/locales" --add-data "./backend/legacy;/legacy" --add-data "./plugin;/plugin" ./backend/main.py
- name: Upload package artifact ⬆️
uses: actions/upload-artifact@v3
+8
View File
@@ -41,6 +41,14 @@
"command": "rsync -azp --rsh='ssh -p ${config:deckport} ${config:deckkey}' requirements.txt deck@${config:deckip}:${config:deckdir}/homebrew/dev/pluginloader/requirements.txt && ssh deck@${config:deckip} -p ${config:deckport} ${config:deckkey} 'python -m ensurepip && python -m pip install --upgrade pip && python -m pip install --upgrade setuptools && python -m pip install -r ${config:deckdir}/homebrew/dev/pluginloader/requirements.txt'",
"problemMatcher": []
},
{
"label": "extracttext",
"type": "shell",
"group": "none",
"detail": "Check for new strings in the frontend source code and extract it into the corresponding json language files",
"command": "cd frontend && ./node_modules/.bin/i18next --config ./i18next-parser.config.mjs",
"problemMatcher": []
},
// BUILD
{
"label": "pnpmsetup",
+1
View File
@@ -10,6 +10,7 @@
<a href="https://github.com/SteamDeckHomebrew/decky-loader/releases"><img src="https://img.shields.io/github/downloads/SteamDeckHomebrew/decky-loader/total" /></a>
<a href="https://github.com/SteamDeckHomebrew/decky-loader/stargazers"><img src="https://img.shields.io/github/stars/SteamDeckHomebrew/decky-loader" /></a>
<a href="https://github.com/SteamDeckHomebrew/decky-loader/commits/main"><img src="https://img.shields.io/github/last-commit/SteamDeckHomebrew/decky-loader.svg" /></a>
<a href="https://weblate.werwolv.net/engage/decky/"><img src="https://weblate.werwolv.net/widgets/decky/-/decky/svg-badge.svg" alt="Translation status" /></a>
<a href="https://github.com/SteamDeckHomebrew/decky-loader/blob/main/LICENSE"><img src="https://img.shields.io/github/license/SteamDeckHomebrew/decky-loader" /></a>
<a href="https://deckbrew.xyz/discord"><img src="https://img.shields.io/discord/960281551428522045?color=%235865F2&label=discord" /></a>
<br>
+22 -10
View File
@@ -49,7 +49,7 @@ class PluginBrowser:
logger.error(f"chown/chmod exited with a non-zero exit code")
return False
return True
async def _download_remote_binaries_for_plugin_with_name(self, pluginBasePath):
rv = False
try:
@@ -63,10 +63,8 @@ class PluginBrowser:
# create bin directory if needed.
chmod(pluginBasePath, 777)
if access(pluginBasePath, W_OK):
if not path.exists(pluginBinPath):
mkdir(pluginBinPath)
if not access(pluginBinPath, W_OK):
chmod(pluginBinPath, 777)
@@ -85,7 +83,7 @@ class PluginBrowser:
else:
rv = True
logger.debug(f"No Remote Binaries to Download")
except Exception as e:
rv = False
logger.debug(str(e))
@@ -174,7 +172,7 @@ class PluginBrowser:
if res_zip is None:
logger.fatal(f"Could not fetch {artifact}")
return
# If plugin is installed, uninstall it
if isInstalled:
try:
@@ -196,7 +194,7 @@ class PluginBrowser:
self.loader.plugins[name].stop()
self.loader.plugins.pop(name, None)
await sleep(1)
current_plugin_order = self.settings.getSetting("pluginOrder")
current_plugin_order.append(name)
self.settings.setSetting("pluginOrder", current_plugin_order)
@@ -209,16 +207,30 @@ class PluginBrowser:
if self.loader.watcher:
self.loader.watcher.disabled = False
async def request_plugin_install(self, artifact, name, version, hash):
async def request_plugin_install(self, artifact, name, version, hash, install_type):
request_id = str(time())
self.install_requests[request_id] = PluginInstallContext(artifact, name, version, hash)
tab = await get_gamepadui_tab()
await tab.open_websocket()
await tab.evaluate_js(f"DeckyPluginLoader.addPluginInstallPrompt('{name}', '{version}', '{request_id}', '{hash}')")
await tab.evaluate_js(f"DeckyPluginLoader.addPluginInstallPrompt('{name}', '{version}', '{request_id}', '{hash}', {install_type})")
async def request_multiple_plugin_installs(self, requests):
request_id = str(time())
self.install_requests[request_id] = [PluginInstallContext(req['artifact'], req['name'], req['version'], req['hash']) for req in requests]
js_requests_parameter = ','.join([
f"{{ name: '{req['name']}', version: '{req['version']}', hash: '{req['hash']}', install_type: {req['install_type']}}}" for req in requests
])
tab = await get_gamepadui_tab()
await tab.open_websocket()
await tab.evaluate_js(f"DeckyPluginLoader.addMultiplePluginsInstallPrompt('{request_id}', [{js_requests_parameter}])")
async def confirm_plugin_install(self, request_id):
request = self.install_requests.pop(request_id)
await self._install(request.artifact, request.name, request.version, request.hash)
requestOrRequests = self.install_requests.pop(request_id)
if isinstance(requestOrRequests, list):
[await self._install(req.artifact, req.name, req.version, req.hash) for req in requestOrRequests]
else:
await self._install(requestOrRequests.artifact, requestOrRequests.name, requestOrRequests.version, requestOrRequests.hash)
def cancel_plugin_install(self, request_id):
self.install_requests.pop(request_id)
+10
View File
@@ -77,6 +77,7 @@ class Loader:
server_instance.add_routes([
web.get("/frontend/{path:.*}", self.handle_frontend_assets),
web.get("/locales/{path:.*}", self.handle_frontend_locales),
web.get("/plugins", self.get_plugins),
web.get("/plugins/{plugin_name}/frontend_bundle", self.handle_frontend_bundle),
web.post("/plugins/{plugin_name}/methods/{method_name}", self.handle_plugin_method_call),
@@ -99,6 +100,15 @@ class Loader:
return web.FileResponse(file, headers={"Cache-Control": "no-cache"})
async def handle_frontend_locales(self, request):
req_lang = request.match_info["path"]
file = path.join(path.dirname(__file__), "locales", req_lang)
if exists(file):
return web.FileResponse(file, headers={"Cache-Control": "no-cache", "Content-Type": "application/json"})
else:
self.logger.info(f"Language {req_lang} not available, returning an empty dictionary")
return web.json_response(data={}, headers={"Cache-Control": "no-cache"})
async def get_plugins(self, request):
plugins = list(self.plugins.values())
return web.json_response([{"name": str(i) if not i.legacy else "$LEGACY_"+str(i), "version": i.version} for i in plugins])
+183
View File
@@ -0,0 +1,183 @@
{
"BranchSelect": {
"update_channel": {
"label": "Updatekanal",
"prerelease": "Vorabveröffentlichung",
"stable": "Standard",
"testing": "Test"
}
},
"Developer": {
"disabling": "Deaktiviere",
"enabling": "Aktiviere",
"5secreload": "Neu laden in 5 Sekunden"
},
"FilePickerIndex": {
"folder": {
"select": "Diesen Ordner verwenden"
}
},
"PluginCard": {
"plugin_install": "Installieren",
"plugin_no_desc": "Keine Beschreibung angegeben.",
"plugin_version_label": "Erweiterungs Version",
"plugin_full_access": "Diese Erweiterung hat uneingeschränkten Zugriff auf dein Steam Deck."
},
"PluginInstallModal": {
"install": {
"button_idle": "Installieren",
"button_processing": "Wird installiert",
"desc": "Bist du dir sicher, dass du {{artifact}}{{version}} installieren willst?",
"title": "Installiere {{artifact}}"
},
"reinstall": {
"button_idle": "Neu installieren",
"button_processing": "Wird neu installiert",
"desc": "Bist du dir sicher, dass du {{artifact}}{{version}} neu installieren willst?",
"title": "Neu installation {{artifact}}"
},
"update": {
"button_idle": "Aktualisieren",
"button_processing": "Wird aktualisiert",
"title": "Aktualisiere {{artifact}}",
"desc": "Bist du dir sicher, dass du {{artifact}}{{version}} aktualisieren willst?"
},
"no_hash": "Diese Erweiterung besitzt keine Prüfsumme, Installation auf eigene Gefahr."
},
"PluginListIndex": {
"no_plugin": "Keine Erweiterungen installiert!",
"plugin_actions": "Erweiterungs Aktionen",
"reinstall": "Neu installieren",
"reload": "Neu laden",
"uninstall": "Deinstallieren",
"update_to": "Aktualisieren zu {{name}}"
},
"PluginLoader": {
"decky_title": "Decky",
"decky_update_available": "Eine neue Version ({{tag_name}}) ist verfügbar!",
"error": "Fehler",
"plugin_load_error": {
"toast": "Fehler beim Laden von {{name}}",
"message": "Fehler beim Laden von {{name}}"
},
"plugin_uninstall": {
"button": "Deinstallieren",
"desc": "Bist du dir sicher, dass du {{name}} deinstallieren willst?",
"title": "Deinstalliere {{name}}"
},
"plugin_error_uninstall": "Das Laden von {{name}} hat einen Fehler verursacht. Dies bedeutet normalerweise, dass die Erweiterung ein Update für die neue Version von SteamUI benötigt. Prüfe in den Decky-Einstellungen im Bereich Erweiterungen, ob ein Update vorhanden ist.",
"plugin_update_one": "1 Erweiterung kann aktualisiert werden!",
"plugin_update_other": "{{count}} Erweiterungen können aktualisiert werden!"
},
"RemoteDebugging": {
"remote_cef": {
"label": "Remote CEF Debugging Zugriff",
"desc": "Erlaubt jedem aus dem Neztwerk unautorisierten Zugriff auf den CEF Debugger"
}
},
"SettingsDeveloperIndex": {
"header": "Sonstiges",
"react_devtools": {
"ip_label": "IP",
"label": "Aktiviere React DevTools",
"desc": "Erlaubt die Verbindung mit einem anderen Rechner, auf welchem React DevTools läuft. Eine Änderung startet Steam neu. Die IP Adresse muss vor Aktivierung ausgefüllt sein."
},
"third_party_plugins": {
"button_zip": "Durchsuchen",
"header": "Erweiterungen von Drittanbietern",
"label_desc": "URL",
"label_zip": "Installiere Erweiterung via ZIP Datei",
"button_install": "Installieren",
"label_url": "Installiere Erweiterung via URL"
},
"toast_zip": {
"body": "Installation fehlgeschlagen! Nur ZIP Datein werden unterstützt.",
"title": "Decky"
},
"valve_internal": {
"desc2": "Fasse in diesem Menü nichts an, es sei denn, du weißt was du tust.",
"label": "Aktiviere Valve-internes Menü",
"desc1": "Aktiviert das Valve-interne Entwickler Menü."
}
},
"SettingsGeneralIndex": {
"about": {
"decky_version": "Decky Version",
"header": "Über"
},
"beta": {
"header": "Beta Teilnahme"
},
"developer_mode": {
"desc": "Aktiviere Deckys Entwickleroptionen.",
"label": "Entwickleroptionen"
},
"other": {
"header": "Sonstiges"
},
"updates": {
"header": "Aktualisierungen"
}
},
"SettingsIndex": {
"developer_title": "Entwickler",
"general_title": "Allgemein",
"plugins_title": "Erweiterungen",
"navbar_settings": "Decky Einstellungen"
},
"Store": {
"store_contrib": {
"label": "Mitwirken",
"desc": "Wenn du Erweiterungen im Decky Store veröffentlichen willst, besuche die SteamDeckHomebrew/decky-plugin-template Repository auf GitHub. Informationen rund um Entwicklung und Veröffentlichung findest du in der README."
},
"store_filter": {
"label": "Filter",
"label_def": "Alle"
},
"store_search": {
"label": "Suche"
},
"store_sort": {
"label": "Sortierung",
"label_def": "Zuletzt aktualisiert"
},
"store_source": {
"desc": "Jeder Erweiterungs Quellcode ist in der SteamDeckHomebrew/decky-plugin-database Repository auf GitHub verfügbar.",
"label": "Quellcode"
},
"store_tabs": {
"about": "Über",
"alph_asce": "Alphabetisch (Z zu A)",
"alph_desc": "Alphabetisch (A zu Z)",
"title": "Durchstöbern"
},
"store_testing_cta": "Unterstütze das Decky Loader Team mit dem Testen von neuen Erweiterungen!"
},
"StoreSelect": {
"custom_store": {
"label": "Benutzerdefinierter Marktplatz",
"url_label": "URL"
},
"store_channel": {
"custom": "Benutzerdefiniert",
"default": "Standard",
"label": "Marktplatz Kanal",
"testing": "Test"
}
},
"Updater": {
"decky_updates": "Decky Aktualisierungen",
"patch_notes_desc": "Patchnotizen",
"updates": {
"check_button": "Auf Aktualisierungen prüfen",
"checking": "Wird überprüft",
"cur_version": "Aktualle Version: {{ver}}",
"install_button": "Aktualisierung installieren",
"label": "Aktualisierungen",
"lat_version": "{{ver}} ist die aktuellste",
"reloading": "Lade neu",
"updating": "Aktualisiere"
},
"no_patch_notes_desc": "Für diese Version gibt es keine Patchnotizen"
}
}
+180
View File
@@ -0,0 +1,180 @@
{
"SettingsDeveloperIndex": {
"react_devtools": {
"desc": "Επιτρέπει την σύνδεση με υπολογιστή που τρέχει React DevTools. Η αλλαγή αυτής της ρύθμισης θα προκαλέσει επαναφόρτωση του Steam. Ωρίστε την διεύθυνση IP πριν την ενεργοποιήσετε.",
"ip_label": "IP",
"label": "Ενεργοποίηση React DevTools"
},
"third_party_plugins": {
"button_install": "Εγκατάσταση",
"button_zip": "Περιήγηση",
"header": "Επεκτάσεις τρίτων",
"label_desc": "URL",
"label_url": "Εγκατάσταση επέκτασης απο URL",
"label_zip": "Εγκατάσταση επέκτασης από αρχείο ZIP"
},
"toast_zip": {
"title": "Decky",
"body": "Η εγκατάσταση απέτυχε. Μόνο αρχεία ZIP επιτρέπονται."
},
"valve_internal": {
"desc1": "Ενεργοποιεί το μενού προγραμματιστή της Valve.",
"desc2": "Μην αγγίξετε τίποτα σε αυτό το μενού εκτός και αν ξέρετε τι κάνει.",
"label": "Ενεργοποιήση εσωτερικού μενού Valve"
}
},
"BranchSelect": {
"update_channel": {
"prerelease": "Προ-κυκλοφορία",
"stable": "Σταθερό",
"label": "Κανάλι ενημερώσεων",
"testing": "Δοκιμαστικό"
}
},
"Developer": {
"5secreload": "Γίνεται επαναφόρτωση σε 5 δευτερόλεπτα",
"disabling": "Γίνεται απενεργοποίηση",
"enabling": "Γίνεται ενεργοποίηση"
},
"PluginCard": {
"plugin_no_desc": "Δεν υπάρχει περιγραφή.",
"plugin_full_access": "Αυτή η επέκταση έχει πλήρη πρόσβαση στο Steam Deck σας.",
"plugin_install": "Εγκατάσταση",
"plugin_version_label": "Έκδοση επέκτασης"
},
"PluginInstallModal": {
"install": {
"desc": "Σίγουρα θέλετε να εγκαταστήσετε το {{artifact}}{{version}};",
"button_idle": "Εγκατάσταση",
"button_processing": "Γίνεται εγκατάσταση",
"title": "Εγκατάσταση {{artifact}}"
},
"no_hash": "Αυτή η επέκταση δεν έχει υπογραφή, την εγκαθηστάτε με δικό σας ρίσκο.",
"reinstall": {
"button_idle": "Επανεγκατάσταση",
"button_processing": "Γίνεται επανεγκατάσταση",
"desc": "Σίγουρα θέλετε να επανεγκαταστήσετε το {{artifact}}{{version}};",
"title": "Επανεγκατάσταση {{artifact}}"
},
"update": {
"button_idle": "Ενημέρωση",
"desc": "Σίγουρα θέλετε να ενημερώσετε το {{artifact}} {{version}};",
"title": "Ενημέρωση {{artifact}}",
"button_processing": "Γίνεται ενημέρωση"
}
},
"PluginListIndex": {
"no_plugin": "Δεν υπάρχουν εγκατεστημένες επεκτάσεις!",
"plugin_actions": "Ενέργειες επεκτάσεων",
"reinstall": "Επανεγκατάσταση",
"reload": "Επαναφόρτωση",
"uninstall": "Απεγκατάσταση",
"update_to": "Ενημέρωση σε {{name}}"
},
"PluginLoader": {
"decky_title": "Decky",
"decky_update_available": "Ενημέρωση σε {{tag_name}} διαθέσιμη!",
"error": "Σφάλμα",
"plugin_error_uninstall": "Πηγαίντε στο <0></0> στο μενού του Decky για να απεγκαταστήσετε αυτή την επέκταση.",
"plugin_load_error": {
"message": "Σφάλμα στη φόρτωση της επέκτασης {{name}}",
"toast": "Σφάλμα φόρτωσης {{name}}"
},
"plugin_uninstall": {
"button": "Απεγκατάσταση",
"desc": "Σίγουρα θέλετε να απεγκαταστήσετε το {{name}};",
"title": "Απεγκατάσταση {{name}}"
}
},
"RemoteDebugging": {
"remote_cef": {
"label": "Να επιτρέπεται η απομακρυσμένη πρόσβαση στον CEF debugger",
"desc": "Να επιτρέπεται η ανεξέλεγκτη πρόσβαση στον CEF debugger σε οποιονδήποτε στο τοπικό δίκτυο"
}
},
"SettingsGeneralIndex": {
"about": {
"decky_version": "Έκδοση Decky",
"header": "Σχετικά"
},
"developer_mode": {
"desc": "Ενεργοποιεί το μενού προγραμματιστή του Decky.",
"label": "Λειτουργία προγραμματιστή"
},
"other": {
"header": "Άλλα"
},
"updates": {
"header": "Ενημερώσεις"
},
"beta": {
"header": "Συμμετοχή στη Beta"
}
},
"SettingsIndex": {
"plugins_title": "Επεκτάσεις",
"developer_title": "Προγραμματιστής",
"general_title": "Γενικά",
"navbar_settings": "Ρυθμίσεις Decky"
},
"Store": {
"store_contrib": {
"label": "Συνεισφέροντας",
"desc": "Αν θέλετε να συνεισφέρετε στο κατάστημα επεκτάσεων του Decky, τσεκάρετε το SteamDeckHomebrew/decky-plugin-template repository στο GitHub. Πληροφοριές σχετικά με τη δημιουργία και τη διανομή επεκτάσεων είναι διαθέσιμες στο README."
},
"store_filter": {
"label": "Φίλτρο",
"label_def": "Όλα"
},
"store_search": {
"label": "Αναζήτηση"
},
"store_sort": {
"label": "Ταξινόμηση",
"label_def": "Τελευταία ενημέρωση (Νεότερα)"
},
"store_source": {
"desc": "Ο πηγαίος κώδικας όλων των επεκτάσεων είναι διαθέσιμος στο SteamDeckHomebrew/decky-plugin-database repository στο GitHub.",
"label": "Πηγαίος κώδικας"
},
"store_tabs": {
"about": "Σχετικά",
"alph_asce": "Αλφαβητικά (Ζ σε Α)",
"alph_desc": "Αλφαβητικά (Α σε Ζ)",
"title": "Περιήγηση"
},
"store_testing_cta": "Παρακαλώ σκεφτείτε να τεστάρετε νέες επεκτάσεις για να βοηθήσετε την ομάδα του Decky Loader!"
},
"StoreSelect": {
"custom_store": {
"label": "Προσαρμοσμένο κατάστημα",
"url_label": "URL"
},
"store_channel": {
"custom": "Προσαρμοσμένο",
"default": "Προεπιλεγμένο",
"label": "Κανάλι καταστήματος",
"testing": "Δοκιμαστικό"
}
},
"Updater": {
"no_patch_notes_desc": "Κανένα ενημερωτικό σημείωμα για αυτή την έκδοση",
"patch_notes_desc": "Σημειώσεις ενημέρωσης",
"updates": {
"check_button": "Έλεγχος για ενημερώσεις",
"checking": "Γίνεται έλεγχος",
"cur_version": "Τρέχουσα έκδοση: {{ver}}",
"install_button": "Εγκατάσταση ενημέρωσης",
"label": "Ενημερώσεις",
"updating": "Γίνεται ενημέρωση",
"lat_version": "Ενημερωμένο: τρέχουσα έκδοση {{ver}}",
"reloading": "Γίνεται επαναφόρτωση"
},
"decky_updates": "Ενημερώσεις Decky"
},
"FilePickerIndex": {
"folder": {
"select": "Χρησιμοποιήστε αυτό το φάκελο"
}
}
}
+207
View File
@@ -0,0 +1,207 @@
{
"BranchSelect": {
"update_channel": {
"label": "Update Channel",
"prerelease": "Prerelease",
"stable": "Stable",
"testing": "Testing"
}
},
"Developer": {
"5secreload": "Reloading in 5 seconds",
"disabling": "Disabling React DevTools",
"enabling": "Enabling React DevTools"
},
"FilePickerIndex": {
"folder": {
"select": "Use this folder"
}
},
"PluginCard": {
"plugin_full_access": "This plugin has full access to your Steam Deck.",
"plugin_install": "Install",
"plugin_no_desc": "No description provided.",
"plugin_version_label": "Plugin Version"
},
"PluginInstallModal": {
"install": {
"button_idle": "Install",
"button_processing": "Installing",
"desc": "Are you sure you want to install {{artifact}} {{version}}?",
"title": "Install {{artifact}}"
},
"no_hash": "This plugin does not have a hash, you are installing it at your own risk.",
"reinstall": {
"button_idle": "Reinstall",
"button_processing": "Reinstalling",
"desc": "Are you sure you want to reinstall {{artifact}} {{version}}?",
"title": "Reinstall {{artifact}}"
},
"update": {
"button_idle": "Update",
"button_processing": "Updating",
"desc": "Are you sure you want to update {{artifact}} {{version}}?",
"title": "Update {{artifact}}"
}
},
"MultiplePluginsInstallModal": {
"title": {
"mixed_one": "Modify 1 plugin",
"mixed_other": "Modify {{count}} plugins",
"update_one": "Update 1 plugin",
"update_other": "Update {{count}} plugins",
"reinstall_one": "Reinstall 1 plugin",
"reinstall_other": "Reinstall {{count}} plugins",
"install_one": "Install 1 plugin",
"install_other": "Install {{count}} plugins"
},
"ok_button": {
"idle": "Confirm",
"loading": "Working"
},
"confirm": "Are you sure you want to make the following modifications?",
"description": {
"install": "Install {{name}} {{version}}",
"update": "Update {{name}} to {{version}}",
"reinstall": "Reinstall {{name}} {{version}}"
}
},
"PluginListIndex": {
"no_plugin": "No plugins installed!",
"plugin_actions": "Plugin Actions",
"reinstall": "Reinstall",
"reload": "Reload",
"uninstall": "Uninstall",
"update_to": "Update to {{name}}",
"update_all_one": "Update 1 plugin",
"update_all_other": "Update {{count}} plugins"
},
"PluginLoader": {
"decky_title": "Decky",
"decky_update_available": "Update to {{tag_name}} available!",
"error": "Error",
"plugin_error_uninstall": "Loading {{name}} caused an exception as shown above. This usually means that the plugin requires an update for the new version of SteamUI. Check if an update is present or evaluate its removal in the Decky settings, in the Plugins section.",
"plugin_load_error": {
"message": "Error loading plugin {{name}}",
"toast": "Error loading {{name}}"
},
"plugin_uninstall": {
"button": "Uninstall",
"desc": "Are you sure you want to uninstall {{name}}?",
"title": "Uninstall {{name}}"
},
"plugin_update_one": "Updates available for 1 plugin!",
"plugin_update_other": "Updates available for {{count}} plugins!"
},
"RemoteDebugging": {
"remote_cef": {
"desc": "Allow unauthenticated access to the CEF debugger to anyone in your network",
"label": "Allow Remote CEF Debugging"
}
},
"SettingsDeveloperIndex": {
"header": "Other",
"react_devtools": {
"desc": "Enables connection to a computer running React DevTools. Changing this setting will reload Steam. Set the IP address before enabling.",
"ip_label": "IP",
"label": "Enable React DevTools"
},
"third_party_plugins": {
"button_install": "Install",
"button_zip": "Browse",
"header": "Third-Party Plugins",
"label_desc": "URL",
"label_url": "Install Plugin from URL",
"label_zip": "Install Plugin from ZIP File"
},
"toast_zip": {
"body": "Installation failed! Only ZIP files are supported.",
"title": "Decky"
},
"valve_internal": {
"desc1": "Enables the Valve internal developer menu.",
"desc2": "Do not touch anything in this menu unless you know what it does.",
"label": "Enable Valve Internal"
}
},
"SettingsGeneralIndex": {
"about": {
"decky_version": "Decky Version",
"header": "About"
},
"beta": {
"header": "Beta participation"
},
"developer_mode": {
"desc": "Enables Decky's developer settings.",
"label": "Developer mode"
},
"other": {
"header": "Other"
},
"updates": {
"header": "Updates"
}
},
"SettingsIndex": {
"developer_title": "Developer",
"general_title": "General",
"navbar_settings": "Decky Settings",
"plugins_title": "Plugins"
},
"Store": {
"store_contrib": {
"desc": "If you would like to contribute to the Decky Plugin Store, check the SteamDeckHomebrew/decky-plugin-template repository on GitHub. Information on development and distribution is available in the README.",
"label": "Contributing"
},
"store_filter": {
"label": "Filter",
"label_def": "All"
},
"store_search": {
"label": "Search"
},
"store_sort": {
"label": "Sort",
"label_def": "Last Updated (Newest)"
},
"store_source": {
"desc": "All plugin source code is available on SteamDeckHomebrew/decky-plugin-database repository on GitHub.",
"label": "Source Code"
},
"store_tabs": {
"about": "About",
"alph_asce": "Alphabetical (Z to A)",
"alph_desc": "Alphabetical (A to Z)",
"title": "Browse"
},
"store_testing_cta": "Please consider testing new plugins to help the Decky Loader team!"
},
"StoreSelect": {
"custom_store": {
"label": "Custom Store",
"url_label": "URL"
},
"store_channel": {
"custom": "Custom",
"default": "Default",
"label": "Store Channel",
"testing": "Testing"
}
},
"Updater": {
"decky_updates": "Decky Updates",
"no_patch_notes_desc": "no patch notes for this version",
"patch_notes_desc": "Patch Notes",
"updates": {
"check_button": "Check For Updates",
"checking": "Checking",
"cur_version": "Current version: {{ver}}",
"install_button": "Install Update",
"label": "Updates",
"lat_version": "Up to date: running {{ver}}",
"reloading": "Reloading",
"updating": "Updating"
}
}
}
+113
View File
@@ -0,0 +1,113 @@
{
"SettingsDeveloperIndex": {
"third_party_plugins": {
"button_install": "Instalar",
"button_zip": "Navegar"
},
"valve_internal": {
"desc2": "No toque nada en este menú a menos que sepa lo que hace."
},
"toast_zip": {
"title": "Decky"
}
},
"PluginInstallModal": {
"install": {
"button_idle": "Instalar",
"button_processing": "Instalando"
},
"reinstall": {
"button_idle": "Reinstalar",
"button_processing": "Reinstalando"
},
"update": {
"button_processing": "Actualizando",
"button_idle": "Actualizar"
}
},
"Developer": {
"disabling": "Desactivando",
"enabling": "Activando",
"5secreload": "Recargando en 5 segundos"
},
"BranchSelect": {
"update_channel": {
"prerelease": "Prelanzamiento",
"stable": "Estable",
"label": "Canal de actualización"
}
},
"PluginCard": {
"plugin_full_access": "Este plugin tiene acceso completo a su Steam Deck.",
"plugin_install": "Instalar",
"plugin_version_label": "Versión de Plugin"
},
"FilePickerIndex": {
"folder": {
"select": "Usar esta carpeta"
}
},
"PluginListIndex": {
"uninstall": "Desinstalar",
"reinstall": "Reinstalar",
"reload": "Recargar",
"plugin_actions": "Acciónes de Plugin",
"no_plugin": "¡No hay plugins instalados!"
},
"PluginLoader": {
"error": "Error",
"plugin_uninstall": {
"button": "Desinstalar"
},
"decky_title": "Decky"
},
"RemoteDebugging": {
"remote_cef": {
"desc": "Permitir acceso no autenticado al CEF debugger a cualquier persona en su red"
}
},
"SettingsGeneralIndex": {
"updates": {
"header": "Actualizaciones"
},
"about": {
"header": "Información"
},
"developer_mode": {
"label": "Modo Desarrollador"
}
},
"SettingsIndex": {
"developer_title": "Desarrollador",
"general_title": "General",
"navbar_settings": "Ajustes de Decky",
"plugins_title": "Plugins"
},
"Store": {
"store_search": {
"label": "Buscar"
},
"store_sort": {
"label": "Ordenar"
},
"store_contrib": {
"desc": "Si desea contribuir a la Tienda de Decky Plugin, revise el repositorio SteamDeckHomebrew/decky-plugin-template en GitHub. Información acerca del desarrollo y distribución está disponible en al archivo README.",
"label": "Contribuyendo"
},
"store_tabs": {
"about": "Información",
"title": "Navegar"
},
"store_testing_cta": "¡Por favor considera probando plugins nuevos para ayudar al equipo de Decky Loader!"
},
"Updater": {
"updates": {
"reloading": "Recargando",
"updating": "Actualizando",
"checking": "Buscando",
"check_button": "Buscar Actualizaciones",
"install_button": "Instalar Actualización",
"label": "Actualizaciones"
}
}
}
+183
View File
@@ -0,0 +1,183 @@
{
"SettingsDeveloperIndex": {
"react_devtools": {
"desc": "Permet la connexion à un ordinateur exécutant React DevTools. Changer ce paramètre rechargera Steam. Définissez l'adresse IP avant l'activation.",
"ip_label": "IP",
"label": "Activer React DevTools"
},
"third_party_plugins": {
"button_install": "Installer",
"button_zip": "Parcourir",
"header": "Plugins tiers",
"label_desc": "URL",
"label_url": "Installer le plugin à partir d'un URL",
"label_zip": "Installer le plugin à partir d'un fichier ZIP"
},
"toast_zip": {
"body": "Échec de l'installation! Seuls les fichiers ZIP sont pris en charge.",
"title": "Decky"
},
"valve_internal": {
"desc1": "Active le menu développeur interne de Valve.",
"desc2": "Ne touchez à rien dans ce menu à moins que vous ne sachiez ce qu'il fait.",
"label": "Activer Valve Internal"
}
},
"BranchSelect": {
"update_channel": {
"prerelease": "Avant-première",
"label": "Canal de mise à jour",
"stable": "Stable",
"testing": "Test"
}
},
"StoreSelect": {
"store_channel": {
"label": "Canal du Plugin Store",
"testing": "Test",
"custom": "Personnalisé",
"default": "Par défaut"
},
"custom_store": {
"label": "Plugin Store personnalisé",
"url_label": "URL"
}
},
"Updater": {
"decky_updates": "Mises à jour de Decky",
"no_patch_notes_desc": "pas de notes de mise à jour pour cette version",
"patch_notes_desc": "Notes de mise à jour",
"updates": {
"check_button": "Chercher les mises à jour",
"checking": "Recherche",
"cur_version": "Version actuelle: {{ver}}",
"install_button": "Installer la mise à jour",
"label": "Mises à jour",
"lat_version": "À jour: version {{ver}}",
"reloading": "Rechargement",
"updating": "Mise à jour en cours"
}
},
"Developer": {
"5secreload": "Rechargement dans 5 secondes",
"disabling": "Désactivation",
"enabling": "Activation"
},
"FilePickerIndex": {
"folder": {
"select": "Utiliser ce dossier"
}
},
"PluginCard": {
"plugin_full_access": "Ce plugin a un accès complet à votre Steam Deck.",
"plugin_install": "Installer",
"plugin_no_desc": "Aucune description fournie.",
"plugin_version_label": "Version du plugin"
},
"PluginInstallModal": {
"install": {
"button_idle": "Installer",
"button_processing": "Installation en cours",
"title": "Installer {{artifact}}",
"desc": "Êtes-vous sûr de vouloir installer {{artifact}} {{version}}?"
},
"no_hash": "Ce plugin n'a pas de somme de contrôle, vous l'installez à vos risques et périls.",
"reinstall": {
"button_idle": "Réinstaller",
"button_processing": "Réinstallation en cours",
"desc": "Êtes-vous sûr de vouloir réinstaller {{artifact}} {{version}}?",
"title": "Réinstaller {{artifact}}"
},
"update": {
"button_idle": "Mettre à jour",
"button_processing": "Mise à jour",
"title": "Mettre à jour {{artifact}}",
"desc": "Êtes-vous sûr de vouloir mettre à jour {{artifact}} {{version}}?"
}
},
"PluginListIndex": {
"plugin_actions": "Plugin Actions",
"reinstall": "Réinstaller",
"reload": "Recharger",
"uninstall": "Désinstaller",
"update_to": "Mettre à jour vers {{name}}",
"no_plugin": "Aucun plugin installé !"
},
"PluginLoader": {
"decky_title": "Decky",
"error": "Erreur",
"plugin_error_uninstall": "Allez sur <0></0> dans le menu de Decky si vous voulez désinstaller ce plugin.",
"plugin_load_error": {
"message": "Erreur lors du chargement du plugin {{name}}",
"toast": "Erreur lors du chargement de {{name}}"
},
"decky_update_available": "Mise à jour vers {{tag_name}} disponible !",
"plugin_uninstall": {
"button": "Désinstaller",
"title": "Désinstaller {{name}}",
"desc": "Êtes-vous sûr.e de vouloir désinstaller {{name}} ?"
},
"plugin_update_one": "",
"plugin_update_many": "",
"plugin_update_other": ""
},
"RemoteDebugging": {
"remote_cef": {
"desc": "Autoriser l'accès non authentifié au débogueur CEF à toute personne de votre réseau",
"label": "Autoriser le débogage CEF à distance"
}
},
"SettingsGeneralIndex": {
"about": {
"decky_version": "Version de Decky",
"header": "À propos"
},
"beta": {
"header": "Participation à la Bêta"
},
"developer_mode": {
"desc": "Active les paramètres de développeur de Decky.",
"label": "Mode développeur"
},
"other": {
"header": "Autre"
},
"updates": {
"header": "Mises à jour"
}
},
"SettingsIndex": {
"developer_title": "Développeur",
"general_title": "Général",
"navbar_settings": "Paramètres de Decky",
"plugins_title": "Plugins"
},
"Store": {
"store_contrib": {
"desc": "Si vous souhaitez contribuer au Decky Plugin Store, consultez le dépôt SteamDeckHomebrew/decky-plugin-template sur GitHub. Des informations sur le développement et la distribution sont disponibles dans le fichier README.",
"label": "Contributions"
},
"store_filter": {
"label": "Filtrer",
"label_def": "Tous"
},
"store_search": {
"label": "Rechercher"
},
"store_sort": {
"label": "Trier",
"label_def": "Mises à jour (Plus récentes)"
},
"store_source": {
"desc": "Tout le code source des plugins est disponible sur le dépôt SteamDeckHomebrew/decky-plugin-database sur GitHub.",
"label": "Code Source"
},
"store_tabs": {
"about": "À propos",
"alph_asce": "Alphabétique (Z à A)",
"alph_desc": "Alphabétique (A à Z)",
"title": "Explorer"
},
"store_testing_cta": "Pensez à tester de nouveaux plugins pour aider l'équipe Decky Loader !"
}
}
+184
View File
@@ -0,0 +1,184 @@
{
"BranchSelect": {
"update_channel": {
"label": "Canale di aggiornamento",
"prerelease": "Prerilascio",
"stable": "Stabile",
"testing": "In prova"
}
},
"Developer": {
"5secreload": "Ricarico in 5 secondi",
"disabling": "Disabilito i tools di React",
"enabling": "Abilito i tools di React"
},
"FilePickerIndex": {
"folder": {
"select": "Usa questa cartella"
}
},
"PluginCard": {
"plugin_full_access": "Questo plugin ha accesso completo al tuo Steam Deck.",
"plugin_install": "Installa",
"plugin_no_desc": "Nessuna descrizione fornita.",
"plugin_version_label": "Versione Plugin"
},
"PluginInstallModal": {
"install": {
"button_idle": "Installa",
"button_processing": "Installando",
"desc": "Sei sicuro di voler installare {{artifact}} {{version}}?",
"title": "Installa {{artifact}}"
},
"no_hash": "Questo plugin non ha un hash associato, lo stai installando a tuo rischio e pericolo.",
"reinstall": {
"button_idle": "Reinstalla",
"button_processing": "Reinstallando",
"desc": "Sei sicuro di voler reinstallare {{artifact}} {{version}}?",
"title": "Reinstalla {{artifact}}"
},
"update": {
"button_idle": "Aggiorna",
"button_processing": "Aggiornando",
"desc": "Sei sicuro di voler aggiornare {{artifact}} {{version}}?",
"title": "Aggiorna {{artifact}}"
}
},
"PluginListIndex": {
"no_plugin": "Nessun plugin installato!",
"plugin_actions": "Operazioni sui plugins",
"reinstall": "Reinstalla",
"reload": "Ricarica",
"uninstall": "Rimuovi",
"update_to": "Aggiorna a {{name}}"
},
"PluginLoader": {
"decky_title": "Decky",
"decky_update_available": "Disponibile aggiornamento a {{tag_name}}!",
"error": "Errore",
"plugin_error_uninstall": "Il plugin {{name}} ha causato un'eccezione che è descritta sopra. Questo tipicamente significa che il plugin deve essere aggiornato per funzionare sulla nuova versione di SteamUI. Controlla se è disponibile un aggiornamento o valutane la rimozione andando nelle impostazioni di Decky nella sezione Plugins.",
"plugin_load_error": {
"message": "Errore caricando il plugin {{name}}",
"toast": "Errore caricando {{name}}"
},
"plugin_uninstall": {
"button": "Rimuovi",
"desc": "Sei sicuro di voler rimuovere {{name}}?",
"title": "Rimuovi {{name}}"
},
"plugin_update_one": "Aggiornamento disponibile per 1 plugin!",
"plugin_update_many": "Aggiornamenti disponibili per {{count}} plugins!",
"plugin_update_other": "Aggiornamenti disponibili per {{count}} plugins!"
},
"RemoteDebugging": {
"remote_cef": {
"desc": "Permetti l'accesso non autenticato al debugger di CEF da tutti gli indirizzi sulla tua rete locale",
"label": "Permetti il debug remoto di CEF"
}
},
"SettingsDeveloperIndex": {
"header": "Altro",
"react_devtools": {
"desc": "Abilita la connessione ad un computer che esegue i DevTools di React. Cambiando questa impostazione ricaricherà Steam. Imposta l'indirizzo IP prima di abilitarlo.",
"ip_label": "IP",
"label": "Abilita i DevTools di React"
},
"third_party_plugins": {
"button_install": "Installa",
"button_zip": "Seleziona",
"header": "Plugin di terze parti",
"label_desc": "URL",
"label_url": "Installa plugin da un'indirizzo web",
"label_zip": "Installa plugin da un file ZIP"
},
"toast_zip": {
"body": "Installazione non riuscita! Solo supportati solo file ZIP.",
"title": "Decky"
},
"valve_internal": {
"desc1": "Abilita il menu di sviluppo interno di Valve.",
"desc2": "Non toccare nulla in questo menu se non sai quello che fa.",
"label": "Abilita Menu Sviluppatore"
}
},
"SettingsGeneralIndex": {
"about": {
"decky_version": "Versione di Decky",
"header": "Riguardo a"
},
"beta": {
"header": "Partecipazione alla beta"
},
"developer_mode": {
"desc": "Abilità le impostazioni di sviluppo di Decky.",
"label": "Modalità sviluppatore"
},
"other": {
"header": "Altro"
},
"updates": {
"header": "Aggiornamenti"
}
},
"SettingsIndex": {
"developer_title": "Sviluppatore",
"general_title": "Generali",
"navbar_settings": "Impostazioni Decky",
"plugins_title": "Plugins"
},
"Store": {
"store_contrib": {
"desc": "Se desideri contribuire allo store di Decky, puoi trovare un template caricato su GitHub all'indirizzo SteamDeckHomebrew/decky-plugin-template. Informazioni riguardo sviluppo e distribuzione sono disponibili nel README.",
"label": "Contribuisci"
},
"store_filter": {
"label": "Filtra",
"label_def": "Tutto"
},
"store_search": {
"label": "Cerca"
},
"store_sort": {
"label": "Ordina",
"label_def": "Ultimo aggiornato (Più recente)"
},
"store_source": {
"desc": "Tutto il codice sorgente dei plugin è disponibile su GitHub all'indirizzo SteamDeckHomebrew/decky-plugin-database.",
"label": "Codice Sorgente"
},
"store_tabs": {
"about": "Riguardo a",
"alph_asce": "Alfabetico (Z a A)",
"alph_desc": "Alfabetico (A a Z)",
"title": "Sfoglia"
},
"store_testing_cta": "Valuta la possibilità di testare nuovi plugin per aiutare il team di Decky Loader!"
},
"StoreSelect": {
"custom_store": {
"label": "Negozio custom",
"url_label": "URL"
},
"store_channel": {
"custom": "Personalizzato",
"default": "Default",
"label": "Canale del negozio",
"testing": "In prova"
}
},
"Updater": {
"decky_updates": "Aggiornamento di Decky",
"no_patch_notes_desc": "nessuna patch notes per questa versione",
"patch_notes_desc": "Cambiamenti",
"updates": {
"check_button": "Cerca aggiornamenti",
"checking": "Controllando",
"cur_version": "Versione attuale: {{ver}}",
"install_button": "Installa aggiornamento",
"label": "Aggiornamenti",
"lat_version": "Aggiornato. Eseguendo {{ver}}",
"reloading": "Ricaricando",
"updating": "Aggiornando"
}
}
}
+115
View File
@@ -0,0 +1,115 @@
{
"SettingsDeveloperIndex": {
"react_devtools": {
"ip_label": "IP",
"label": "Aktivizo React DevTools"
},
"third_party_plugins": {
"button_zip": "Kërko",
"header": "Shtesa të Huaj",
"button_install": "Instalo",
"label_desc": "URL",
"label_url": "Instalo Shtes Nga URL",
"label_zip": "Instalo Shtes Nga ZIP"
},
"toast_zip": {
"title": "Decky"
}
},
"BranchSelect": {
"update_channel": {
"stable": "Fiksuar",
"label": "Kanali Përditësimet"
}
},
"FilePickerIndex": {
"folder": {
"select": "Përdore këtë folder"
}
},
"PluginCard": {
"plugin_install": "Instalo",
"plugin_version_label": "Versioni Shteses"
},
"PluginInstallModal": {
"install": {
"button_idle": "Instalo",
"button_processing": "Instalohet",
"desc": "Je i sigurt që don ta instalojsh {{artifact}} {{version}}?",
"title": "Instalo {{artifact}}"
},
"no_hash": "Ky shtesë nuk ka hash, ti e instalon me rrezikun tuaj.",
"reinstall": {
"button_idle": "Riinstalo",
"button_processing": "Riinstalohet",
"desc": "Je i sigurt a don ta riinstalojsh {{artifact}} {{version}}?",
"title": "Riinstalo {{artifact}}"
},
"update": {
"button_processing": "Përditësohet",
"desc": "Je i sigurt a don ta përditësojsh {{artifact}} {{version}}?",
"title": "Përditëso {{artifact}}"
}
},
"PluginLoader": {
"decky_title": "Decky",
"plugin_uninstall": {
"title": "Çinstalo {{name}}",
"button": "Çinstalo",
"desc": "Je i sigurt që don ta çinstalojsh {{name}}?"
},
"error": "Gabim",
"plugin_error_uninstall": "Ju lutem shko nga <0></0> në Decky menu nëse don ta çinstalojsh këtë shtese."
},
"PluginListIndex": {
"no_plugin": "Nuk ka shtesa të instaluar!",
"uninstall": "Çinstalo"
},
"SettingsGeneralIndex": {
"other": {
"header": "Të Tjera"
},
"about": {
"decky_version": "Versioni Decky"
},
"updates": {
"header": "Përmirësimet"
}
},
"SettingsIndex": {
"developer_title": "Zhvillues",
"general_title": "Gjeneral",
"navbar_settings": "Cilësimet Decky"
},
"Store": {
"store_sort": {
"label": "Rendit"
},
"store_tabs": {
"title": "Kërko"
},
"store_contrib": {
"label": "Kontributi"
},
"store_filter": {
"label": "Filtro",
"label_def": "Të Gjitha"
},
"store_search": {
"label": "Kërko"
},
"store_source": {
"label": "Kodin Burimor"
}
},
"StoreSelect": {
"store_channel": {
"label": "Kanali Dyqanit"
}
},
"Updater": {
"updates": {
"cur_version": "Versioni e tanishëme: {{ver}}"
}
}
}
+181
View File
@@ -0,0 +1,181 @@
{
"BranchSelect": {
"update_channel": {
"prerelease": "发布候选",
"stable": "稳定",
"testing": "测试",
"label": "更新通道"
}
},
"Developer": {
"5secreload": "5 秒钟后重新加载",
"disabling": "正在禁用",
"enabling": "正在启用"
},
"FilePickerIndex": {
"folder": {
"select": "使用这个文件夹"
}
},
"PluginCard": {
"plugin_install": "安装",
"plugin_no_desc": "无描述提供。",
"plugin_version_label": "插件版本",
"plugin_full_access": "此插件可以完全访问你的 Steam Deck"
},
"PluginInstallModal": {
"install": {
"button_idle": "安装",
"button_processing": "安装中",
"desc": "你确定要安装 {{artifact}} {{version}} 吗?",
"title": "安装 {{artifact}}"
},
"reinstall": {
"button_idle": "重新安装",
"button_processing": "正在重新安装",
"desc": "你确定要重新安装 {{artifact}} {{version}} 吗?",
"title": "重新安装 {{artifact}}"
},
"update": {
"button_idle": "更新",
"button_processing": "正在更新",
"desc": "你确定要更新 {{artifact}} {{version}} 吗?",
"title": "更新 {{artifact}}"
},
"no_hash": "此插件没有哈希校验值,你需要自行承担安装风险"
},
"PluginListIndex": {
"no_plugin": "没有安装插件!",
"plugin_actions": "插件操作",
"reinstall": "重新安装",
"reload": "重新加载",
"uninstall": "卸载",
"update_to": "更新 {{name}}"
},
"PluginLoader": {
"decky_title": "Decky",
"error": "错误",
"plugin_error_uninstall": "如果你想卸载插件请点击 Decky 菜单中的 <0></0> 图标",
"plugin_load_error": {
"message": "加载插件 {{name}} 错误",
"toast": "加载插件 {{name}} 发生了错误"
},
"plugin_uninstall": {
"button": "卸载",
"title": "卸载 {{name}}",
"desc": "你确定要卸载 {{name}} 吗?"
},
"decky_update_available": "新版本 {{tag_name}} 可用!",
"plugin_update_other": "{{count}} 个插件有更新!"
},
"RemoteDebugging": {
"remote_cef": {
"desc": "允许你网络中的任何人无需身份验证即可访问CEF调试器",
"label": "允许远程访问CEF调试"
}
},
"SettingsDeveloperIndex": {
"react_devtools": {
"ip_label": "IP",
"label": "启用 React DevTools",
"desc": "允许连接到运行着 React DevTools 的计算机,更改此设置将重新加载Steam,请在启用前设置IP地址"
},
"third_party_plugins": {
"button_install": "安装",
"button_zip": "浏览文件",
"header": "第三方插件",
"label_desc": "URL",
"label_url": "从 URL 安装插件",
"label_zip": "从 ZIP 压缩文件安装插件"
},
"toast_zip": {
"title": "Decky",
"body": "安装失败!只有 ZIP 格式的插件被支持"
},
"valve_internal": {
"desc1": "启用 Valve 内部开发者菜单",
"desc2": "除非你知道你在干什么,否则请不要修改此菜单中的任何内容",
"label": "启用 Valve 内部开发者"
}
},
"SettingsGeneralIndex": {
"about": {
"decky_version": "Decky 版本",
"header": "关于"
},
"beta": {
"header": "参与测试"
},
"developer_mode": {
"label": "开发者模式",
"desc": "启用 Decky 的开发者测试"
},
"other": {
"header": "其他"
},
"updates": {
"header": "更新"
}
},
"SettingsIndex": {
"developer_title": "开发者",
"general_title": "通用",
"navbar_settings": "Decky 设置",
"plugins_title": "插件"
},
"Store": {
"store_contrib": {
"label": "贡献",
"desc": "如果你想要提交你的插件到 Decky 插件商店,请访问 GitHub 上的 SteamDeckHomebrew/decky-plugin-template 存储库,关于开发和分发的相关信息,请查看 README 文件"
},
"store_filter": {
"label": "过滤器",
"label_def": "全部"
},
"store_search": {
"label": "搜索"
},
"store_sort": {
"label": "排序",
"label_def": "最后更新 (最新)"
},
"store_source": {
"label": "源代码",
"desc": "所有插件的源代码都可以在 GitHub 上的 SteamDeckHomebrew/decky-plugin-database 存储库中获得"
},
"store_tabs": {
"about": "关于",
"alph_asce": "字母排序 (Z 到 A)",
"alph_desc": "字母排序 (A 到 Z)",
"title": "浏览"
},
"store_testing_cta": "请考虑测试新插件以帮助 Decky Loader 团队!"
},
"StoreSelect": {
"store_channel": {
"default": "默认",
"label": "商店通道",
"testing": "测试",
"custom": "自定义"
},
"custom_store": {
"label": "自定义商店",
"url_label": "URL"
}
},
"Updater": {
"decky_updates": "Decky 更新",
"no_patch_notes_desc": "此版本没有补丁说明",
"patch_notes_desc": "补丁说明",
"updates": {
"check_button": "检查更新",
"checking": "检查中",
"cur_version": "当前版本: {{ver}}",
"install_button": "安装更新",
"label": "更新",
"lat_version": "已是最新版本: {{ver}} 运行中",
"reloading": "重新加载中",
"updating": "更新中"
}
}
}
+180
View File
@@ -0,0 +1,180 @@
{
"BranchSelect": {
"update_channel": {
"testing": "測試版",
"label": "更新頻道",
"prerelease": "預發佈",
"stable": "穩定版"
}
},
"Developer": {
"5secreload": "5 秒後重新載入",
"disabling": "正在停用",
"enabling": "正在啟用"
},
"FilePickerIndex": {
"folder": {
"select": "使用此資料夾"
}
},
"PluginCard": {
"plugin_install": "安裝",
"plugin_no_desc": "未提示描述。",
"plugin_version_label": "外掛程式版本",
"plugin_full_access": "此外掛程式擁有您的 Steam Deck 的完整存取權。"
},
"PluginInstallModal": {
"install": {
"button_idle": "安裝",
"button_processing": "正在安裝",
"title": "安裝 {{artifact}}",
"desc": "您確定要安裝 {{artifact}} {{version}} 嗎?"
},
"reinstall": {
"button_idle": "重新安裝",
"button_processing": "正在重新安裝",
"desc": "您確定要重新安裝 {{artifact}} {{version}} 嗎?",
"title": "重新安裝 {{artifact}}"
},
"update": {
"button_idle": "更新",
"button_processing": "正在更新",
"desc": "您確定要更新 {{artifact}} {{version}} 嗎?",
"title": "更新 {{artifact}}"
},
"no_hash": "此外掛程式沒有提供 hash 驗證,安裝可能有風險。"
},
"PluginListIndex": {
"no_plugin": "未安裝外掛程式!",
"plugin_actions": "外掛程式操作",
"uninstall": "解除安裝",
"update_to": "更新到 {{name}}",
"reinstall": "重新安裝",
"reload": "重新載入"
},
"PluginLoader": {
"decky_title": "Decky",
"error": "錯誤",
"plugin_error_uninstall": "如果您要解除安裝外掛程式,請在 Decky 選單,按下 <0></0>。",
"plugin_load_error": {
"message": "載入外掛程式 {{name}} 發生錯誤",
"toast": "{{name}} 載入出錯"
},
"plugin_uninstall": {
"button": "解除安裝",
"title": "解除安裝 {{name}}",
"desc": "您確定要解除安裝 {{name}} 嗎?"
},
"decky_update_available": "可更新至版本 {{tag_name}}"
},
"RemoteDebugging": {
"remote_cef": {
"desc": "允許您的網路中的任何人未經認證地存取 CEF 偵錯器",
"label": "允許 CEF 遠端偵錯"
}
},
"SettingsDeveloperIndex": {
"third_party_plugins": {
"button_zip": "開啟",
"label_desc": "網址",
"label_url": "從網址安裝外掛程式",
"label_zip": "從 ZIP 檔案安裝外掛程式",
"button_install": "安裝",
"header": "第三方外掛程式"
},
"toast_zip": {
"body": "安裝失敗!只支援 ZIP 檔案。",
"title": "Decky"
},
"valve_internal": {
"desc2": "除非您知道它的作用,否則不要碰這個選單中的任何東西。",
"desc1": "啟用 Valve 內建開發人員選單。",
"label": "啟用 Valve 內建"
},
"react_devtools": {
"desc": "啟用與執行 React DevTools 的電腦的連接。改變這個設定將重新載入 Steam。啟用前必須設定 IP 位址。",
"ip_label": "IP",
"label": "啟用 React DevTools"
}
},
"SettingsGeneralIndex": {
"about": {
"header": "關於",
"decky_version": "Decky 版本"
},
"beta": {
"header": "參與測試"
},
"developer_mode": {
"label": "開發人員模式",
"desc": "啟用 Decky 的開發人員模式。"
},
"other": {
"header": "其他"
},
"updates": {
"header": "更新"
}
},
"SettingsIndex": {
"developer_title": "開發人員",
"general_title": "一般",
"navbar_settings": "Decky 設定",
"plugins_title": "外掛程式"
},
"Store": {
"store_contrib": {
"label": "貢獻",
"desc": "如果您想為 Decky 外掛程式商店做貢獻,請查看 GitHub 上的 SteamDeckHomebrew/decky-plugin-template 儲存庫。README 中提供了有關開發和發佈的資訊。"
},
"store_filter": {
"label": "過濾",
"label_def": "全部"
},
"store_search": {
"label": "搜尋"
},
"store_sort": {
"label": "排序",
"label_def": "最後更新 (最新)"
},
"store_source": {
"label": "原始碼",
"desc": "所有外掛程式原始碼可以在 GitHub 的 SteamDeckHomebrew/decky-plugin-database 儲存庫查看。"
},
"store_tabs": {
"about": "關於",
"alph_asce": "依字母排序 (Z 到 A)",
"alph_desc": "依字母排序 (A 到 Z)",
"title": "瀏覽"
},
"store_testing_cta": "請考慮測試新的外掛程式來幫助 Decky Loader 團隊!"
},
"StoreSelect": {
"custom_store": {
"label": "自訂商店",
"url_label": "網址"
},
"store_channel": {
"custom": "自訂",
"default": "預設",
"label": "商店頻道",
"testing": "測試"
}
},
"Updater": {
"decky_updates": "Decky 更新",
"no_patch_notes_desc": "這個版本沒有更新日誌",
"patch_notes_desc": "更新日誌",
"updates": {
"checking": "正在檢查",
"install_button": "安裝更新",
"label": "更新",
"lat_version": "已是最新:執行 {{ver}}",
"reloading": "正在重新載入",
"check_button": "檢查更新",
"cur_version": "目前版本:{{ver}}",
"updating": "正在更新"
}
}
}
+4 -1
View File
@@ -32,7 +32,10 @@ def get_server_port() -> int:
return int(os.getenv("SERVER_PORT", "1337"))
def get_live_reload() -> bool:
os.getenv("LIVE_RELOAD", "1") == "1"
return os.getenv("LIVE_RELOAD", "1") == "1"
def get_keep_systemd_service() -> bool:
return os.getenv("KEEP_SYSTEMD_SERVICE", "0") == "1"
def get_log_level() -> int:
return {"CRITICAL": 50, "ERROR": 40, "WARNING": 30, "INFO": 20, "DEBUG": 10}[
+2 -2
View File
@@ -6,7 +6,7 @@ from ensurepip import version
from json.decoder import JSONDecodeError
from logging import getLogger
from os import getcwd, path, remove
from localplatform import chmod, service_restart, ON_LINUX
from localplatform import chmod, service_restart, ON_LINUX, get_keep_systemd_service
from aiohttp import ClientSession, web
@@ -159,7 +159,7 @@ class Updater:
tab = await get_gamepadui_tab()
await tab.open_websocket()
async with ClientSession() as web:
if ON_LINUX:
if ON_LINUX and not get_keep_systemd_service():
logger.debug("Downloading systemd service")
# download the relevant systemd service depending upon branch
async with web.request("GET", service_url, ssl=helpers.get_ssl_context(), allow_redirects=True) as res:
+10 -3
View File
@@ -19,6 +19,7 @@ class Utilities:
"ping": self.ping,
"http_request": self.http_request,
"install_plugin": self.install_plugin,
"install_plugins": self.install_plugins,
"cancel_plugin_install": self.cancel_plugin_install,
"confirm_plugin_install": self.confirm_plugin_install,
"uninstall_plugin": self.uninstall_plugin,
@@ -61,12 +62,18 @@ class Utilities:
res["success"] = False
return web.json_response(res)
async def install_plugin(self, artifact="", name="No name", version="dev", hash=False):
async def install_plugin(self, artifact="", name="No name", version="dev", hash=False, install_type=0):
return await self.context.plugin_browser.request_plugin_install(
artifact=artifact,
name=name,
version=version,
hash=hash
hash=hash,
install_type=install_type
)
async def install_plugins(self, requests):
return await self.context.plugin_browser.request_multiple_plugin_installs(
requests=requests
)
async def confirm_plugin_install(self, request_id):
@@ -265,7 +272,7 @@ class Utilities:
await close_old_tabs()
result = await tab.reload_and_evaluate(script)
self.logger.info(result)
except Exception:
self.logger.error("Failed to connect to React DevTools")
self.logger.error(format_exc())
+100
View File
@@ -0,0 +1,100 @@
export default {
contextSeparator: '_',
// Key separator used in your translation keys
createOldCatalogs: false,
// Save the \_old files
defaultNamespace: 'translation',
// Default namespace used in your i18next config
defaultValue: '',
// Default value to give to keys with no value
// You may also specify a function accepting the locale, namespace, key, and value as arguments
indentation: 2,
// Indentation of the catalog files
keepRemoved: true,
// Keep keys from the catalog that are no longer in code
keySeparator: '.',
// Key separator used in your translation keys
// If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance.
// see below for more details
lexers: {
mjs: ['JavascriptLexer'],
js: ['JavascriptLexer'], // if you're writing jsx inside .js files, change this to JsxLexer
ts: ['JavascriptLexer'],
jsx: ['JsxLexer'],
tsx: ['JsxLexer'],
default: ['JavascriptLexer'],
},
lineEnding: 'auto',
// Control the line ending. See options at https://github.com/ryanve/eol
locales: ['en-US', 'it-IT'],
// An array of the locales in your applications
namespaceSeparator: false,
// Namespace separator used in your translation keys
// If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance.
output: '../backend/locales/$LOCALE.json',
// Supports $LOCALE and $NAMESPACE injection
// Supports JSON (.json) and YAML (.yml) file formats
// Where to write the locale files relative to process.cwd()
pluralSeparator: '_',
// Plural separator used in your translation keys
// If you want to use plain english keys, separators such as `_` might conflict. You might want to set `pluralSeparator` to a different string that does not occur in your keys.
input: './src/**/*.{ts,tsx}',
// An array of globs that describe where to look for source files
// relative to the location of the configuration file
sort: true,
// Whether or not to sort the catalog. Can also be a [compareFunction](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#parameters)
verbose: false,
// Display info about the parsing including some stats
failOnWarnings: false,
// Exit with an exit code of 1 on warnings
failOnUpdate: false,
// Exit with an exit code of 1 when translations are updated (for CI purpose)
customValueTemplate: null,
// If you wish to customize the value output the value as an object, you can set your own format.
// ${defaultValue} is the default value you set in your translation function.
// Any other custom property will be automatically extracted.
//
// Example:
// {
// message: "${defaultValue}",
// description: "${maxLength}", // t('my-key', {maxLength: 150})
// }
resetDefaultValueLocale: null,
// The locale to compare with default values to determine whether a default value has been changed.
// If this is set and a default value differs from a translation in the specified locale, all entries
// for that key across locales are reset to the default value, and existing translations are moved to
// the `_old` file.
i18nextOptions: null,
// If you wish to customize options in internally used i18next instance, you can define an object with any
// configuration property supported by i18next (https://www.i18next.com/overview/configuration-options).
// { compatibilityJSON: 'v3' } can be used to generate v3 compatible plurals.
yamlOptions: null,
// If you wish to customize options for yaml output, you can define an object here.
// Configuration options are here (https://github.com/nodeca/js-yaml#dump-object---options-).
// Example:
// {
// lineWidth: -1,
// }
}
+8 -4
View File
@@ -22,9 +22,10 @@
"@types/react-router": "5.1.18",
"@types/webpack": "^5.28.1",
"husky": "^8.0.3",
"i18next-parser": "^7.9.0",
"import-sort-style-module": "^6.0.0",
"inquirer": "^8.2.5",
"prettier": "^2.8.7",
"prettier": "^2.8.8",
"prettier-plugin-import-sort": "^0.0.7",
"react": "16.14.0",
"react-dom": "16.14.0",
@@ -32,7 +33,7 @@
"rollup-plugin-delete": "^2.0.0",
"rollup-plugin-external-globals": "^0.6.1",
"rollup-plugin-polyfill-node": "^0.10.2",
"tslib": "^2.5.0",
"tslib": "^2.5.2",
"typescript": "^4.9.5"
},
"importSort": {
@@ -42,10 +43,13 @@
}
},
"dependencies": {
"decky-frontend-lib": "3.20.6",
"decky-frontend-lib": "3.20.7",
"i18next": "^22.5.0",
"i18next-http-backend": "^2.2.1",
"react-file-icon": "^1.3.0",
"react-i18next": "^12.3.1",
"react-icons": "^4.8.0",
"react-markdown": "^8.0.6",
"react-markdown": "^8.0.7",
"remark-gfm": "^3.0.1"
}
}
+1472 -271
View File
File diff suppressed because it is too large Load Diff
+5 -3
View File
@@ -11,11 +11,13 @@ import externalGlobals from 'rollup-plugin-external-globals';
const hiddenWarnings = ['THIS_IS_UNDEFINED', 'EVAL'];
export default defineConfig({
input: 'src/index.tsx',
input: 'src/index.ts',
plugins: [
del({ targets: '../backend/static/*', force: true }),
commonjs(),
nodeResolve(),
nodeResolve({
browser: true
}),
externalGlobals({
react: 'SP_REACT',
'react-dom': 'SP_REACTDOM',
@@ -44,4 +46,4 @@ export default defineConfig({
if (hiddenWarnings.some((warning) => message.code === warning)) return;
handleWarning(message);
},
});
});
@@ -0,0 +1,82 @@
import { ConfirmModal, Navigation, QuickAccessTab } from 'decky-frontend-lib';
import { FC, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { InstallType } from '../../plugin';
interface MultiplePluginsInstallModalProps {
requests: { name: string; version: string; hash: string; install_type: InstallType }[];
onOK(): void | Promise<void>;
onCancel(): void | Promise<void>;
closeModal?(): void;
}
// values are the JSON keys used in the translation file
const InstallTypeTranslationMapping = {
[InstallType.INSTALL]: 'install',
[InstallType.REINSTALL]: 'reinstall',
[InstallType.UPDATE]: 'update',
} as const satisfies Record<InstallType, string>;
type TitleTranslationMapping = 'mixed' | (typeof InstallTypeTranslationMapping)[InstallType];
const MultiplePluginsInstallModal: FC<MultiplePluginsInstallModalProps> = ({
requests,
onOK,
onCancel,
closeModal,
}) => {
const [loading, setLoading] = useState<boolean>(false);
const { t } = useTranslation();
// used as part of the title translation
// if we know all operations are of a specific type, we can show so in the title to make decision easier
const installTypeGrouped = useMemo((): TitleTranslationMapping => {
if (requests.every(({ install_type }) => install_type === InstallType.INSTALL)) return 'install';
if (requests.every(({ install_type }) => install_type === InstallType.REINSTALL)) return 'reinstall';
if (requests.every(({ install_type }) => install_type === InstallType.UPDATE)) return 'update';
return 'mixed';
}, [requests]);
return (
<ConfirmModal
bOKDisabled={loading}
closeModal={closeModal}
onOK={async () => {
setLoading(true);
await onOK();
setTimeout(() => Navigation.OpenQuickAccessMenu(QuickAccessTab.Decky), 250);
setTimeout(() => window.DeckyPluginLoader.checkPluginUpdates(), 1000);
}}
onCancel={async () => {
await onCancel();
}}
strTitle={<div>{t(`MultiplePluginsInstallModal.title.${installTypeGrouped}`, { count: requests.length })}</div>}
strOKButtonText={t(`MultiplePluginsInstallModal.ok_button.${loading ? 'loading' : 'idle'}`)}
>
<div>
{t('MultiplePluginsInstallModal.confirm')}
<ul style={{ listStyle: 'none', display: 'flex', flexDirection: 'column', gap: '4px' }}>
{requests.map(({ name, version, install_type, hash }, i) => {
const installTypeStr = InstallTypeTranslationMapping[install_type];
const description = t(`MultiplePluginsInstallModal.description.${installTypeStr}`, {
name,
version,
});
return (
<li key={i} style={{ display: 'flex', flexDirection: 'column' }}>
<div>{description}</div>
{hash === 'False' && (
<div style={{ color: 'red', paddingLeft: '10px' }}>{t('PluginInstallModal.no_hash')}</div>
)}
</li>
);
})}
</ul>
</div>
</ConfirmModal>
);
};
export default MultiplePluginsInstallModal;
@@ -1,18 +1,31 @@
import { ConfirmModal, Navigation, QuickAccessTab } from 'decky-frontend-lib';
import { FC, useState } from 'react';
import { useTranslation } from 'react-i18next';
import TranslationHelper, { TranslationClass } from '../../utils/TranslationHelper';
interface PluginInstallModalProps {
artifact: string;
version: string;
hash: string;
// reinstall: boolean;
installType: number;
onOK(): void;
onCancel(): void;
closeModal?(): void;
}
const PluginInstallModal: FC<PluginInstallModalProps> = ({ artifact, version, hash, onOK, onCancel, closeModal }) => {
const PluginInstallModal: FC<PluginInstallModalProps> = ({
artifact,
version,
hash,
installType,
onOK,
onCancel,
closeModal,
}) => {
const [loading, setLoading] = useState<boolean>(false);
const { t } = useTranslation();
return (
<ConfirmModal
bOKDisabled={loading}
@@ -26,14 +39,48 @@ const PluginInstallModal: FC<PluginInstallModalProps> = ({ artifact, version, ha
onCancel={async () => {
await onCancel();
}}
strTitle={`Install ${artifact}`}
strOKButtonText={loading ? 'Installing' : 'Install'}
strTitle={
<div>
<TranslationHelper
trans_class={TranslationClass.PLUGIN_INSTALL_MODAL}
trans_text="title"
i18n_args={{ artifact: artifact }}
install_type={installType}
/>
</div>
}
strOKButtonText={
loading ? (
<div>
<TranslationHelper
trans_class={TranslationClass.PLUGIN_INSTALL_MODAL}
trans_text="button_processing"
install_type={installType}
/>
</div>
) : (
<div>
<TranslationHelper
trans_class={TranslationClass.PLUGIN_INSTALL_MODAL}
trans_text="button_idle"
install_type={installType}
/>
</div>
)
}
>
Are you sure you want to install {artifact}
{version ? ` ${version}` : ''}?
{hash == 'False' && (
<span style={{ color: 'red' }}> This plugin does not have a hash, you are installing it at your own risk.</span>
)}
<div>
<TranslationHelper
trans_class={TranslationClass.PLUGIN_INSTALL_MODAL}
trans_text="desc"
i18n_args={{
artifact: artifact,
version: version,
}}
install_type={installType}
/>
</div>
{hash == 'False' && <span style={{ color: 'red' }}>{t('PluginInstallModal.no_hash')}</span>}
</ConfirmModal>
);
};
@@ -2,6 +2,7 @@ import { DialogButton, Focusable, SteamSpinner, TextField } from 'decky-frontend
import { useEffect } from 'react';
import { FunctionComponent, useState } from 'react';
import { FileIcon, defaultStyles } from 'react-file-icon';
import { useTranslation } from 'react-i18next';
import { FaArrowUp, FaFolder } from 'react-icons/fa';
import Logger from '../../../logger';
@@ -47,6 +48,7 @@ const FilePicker: FunctionComponent<FilePickerProps> = ({
onSubmit,
closeModal,
}) => {
const { t } = useTranslation();
if (startPath.endsWith('/')) startPath = startPath.substring(0, startPath.length - 1); // remove trailing path
const [path, setPath] = useState<string>(startPath);
const [listing, setListing] = useState<FileListing>({ files: [], realpath: path });
@@ -158,7 +160,7 @@ const FilePicker: FunctionComponent<FilePickerProps> = ({
closeModal?.();
}}
>
Use this folder
{t('FilePickerIndex.folder.select')}
</DialogButton>
)}
</div>
+5 -3
View File
@@ -1,5 +1,6 @@
import { SidebarNavigation } from 'decky-frontend-lib';
import { lazy } from 'react';
import { useTranslation } from 'react-i18next';
import { FaCode, FaPlug } from 'react-icons/fa';
import { useSetting } from '../../utils/hooks/useSetting';
@@ -12,22 +13,23 @@ const DeveloperSettings = lazy(() => import('./pages/developer'));
export default function SettingsPage() {
const [isDeveloper, setIsDeveloper] = useSetting<boolean>('developer.enabled', false);
const { t } = useTranslation();
const pages = [
{
title: 'Decky',
title: t('SettingsIndex.general_title'),
content: <GeneralSettings isDeveloper={isDeveloper} setIsDeveloper={setIsDeveloper} />,
route: '/decky/settings/general',
icon: <DeckyIcon />,
},
{
title: 'Plugins',
title: t('SettingsIndex.plugins_title'),
content: <PluginList />,
route: '/decky/settings/plugins',
icon: <FaPlug />,
},
{
title: 'Developer',
title: t('SettingsIndex.developer_title'),
content: (
<WithSuspense>
<DeveloperSettings />
@@ -8,6 +8,7 @@ import {
Toggle,
} from 'decky-frontend-lib';
import { useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { FaFileArchive, FaLink, FaReact, FaSteamSymbol } from 'react-icons/fa';
import { setShouldConnectToReactDevTools, setShowValveInternal } from '../../../../developer';
@@ -24,8 +25,10 @@ const installFromZip = () => {
installFromURL(url);
} else {
window.DeckyPluginLoader.toaster.toast({
//title: t('SettingsDeveloperIndex.toast_zip.title'),
title: 'Decky',
body: `Installation failed! Only ZIP files are supported.`,
//body: t('SettingsDeveloperIndex.toast_zip.body'),
body: 'Installation failed! Only ZIP files are supported.',
onClick: installFromZip,
});
}
@@ -38,33 +41,47 @@ export default function DeveloperSettings() {
const [reactDevtoolsIP, setReactDevtoolsIP] = useSetting<string>('developer.rdt.ip', '');
const [pluginURL, setPluginURL] = useState('');
const textRef = useRef<HTMLDivElement>(null);
const { t } = useTranslation();
return (
<DialogBody>
<DialogControlsSection>
<DialogControlsSectionHeader>Third-Party Plugins</DialogControlsSectionHeader>
<Field label="Install Plugin from ZIP File" icon={<FaFileArchive style={{ display: 'block' }} />}>
<DialogButton onClick={installFromZip}>Browse</DialogButton>
<DialogControlsSectionHeader>
{t('SettingsDeveloperIndex.third_party_plugins.header')}
</DialogControlsSectionHeader>
<Field
label={t('SettingsDeveloperIndex.third_party_plugins.label_zip')}
icon={<FaFileArchive style={{ display: 'block' }} />}
>
<DialogButton onClick={installFromZip}>
{t('SettingsDeveloperIndex.third_party_plugins.button_zip')}
</DialogButton>
</Field>
<Field
label="Install Plugin from URL"
description={<TextField label={'URL'} value={pluginURL} onChange={(e) => setPluginURL(e?.target.value)} />}
label={t('SettingsDeveloperIndex.third_party_plugins.label_url')}
description={
<TextField
label={t('SettingsDeveloperIndex.third_party_plugins.label_desc')}
value={pluginURL}
onChange={(e) => setPluginURL(e?.target.value)}
/>
}
icon={<FaLink style={{ display: 'block' }} />}
>
<DialogButton disabled={pluginURL.length == 0} onClick={() => installFromURL(pluginURL)}>
Install
{t('SettingsDeveloperIndex.third_party_plugins.button_install')}
</DialogButton>
</Field>
</DialogControlsSection>
<DialogControlsSection>
<DialogControlsSectionHeader>Other</DialogControlsSectionHeader>
<DialogControlsSectionHeader>{t('SettingsDeveloperIndex.header')}</DialogControlsSectionHeader>
<RemoteDebuggingSettings />
<Field
label="Enable Valve Internal"
label={t('SettingsDeveloperIndex.valve_internal.label')}
description={
<span style={{ whiteSpace: 'pre-line' }}>
Enables the Valve internal developer menu.{' '}
<span style={{ color: 'red' }}>Do not touch anything in this menu unless you know what it does.</span>
{t('SettingsDeveloperIndex.valve_internal.desc1')}{' '}
<span style={{ color: 'red' }}>{t('SettingsDeveloperIndex.valve_internal.desc2')}</span>
</span>
}
icon={<FaSteamSymbol style={{ display: 'block' }} />}
@@ -78,17 +95,18 @@ export default function DeveloperSettings() {
/>
</Field>
<Field
label="Enable React DevTools"
label={t('SettingsDeveloperIndex.react_devtools.label')}
description={
<>
<span style={{ whiteSpace: 'pre-line' }}>
Enables connection to a computer running React DevTools. Changing this setting will reload Steam. Set
the IP address before enabling.
</span>
<span style={{ whiteSpace: 'pre-line' }}>{t('SettingsDeveloperIndex.react_devtools.desc')}</span>
<br />
<br />
<div ref={textRef}>
<TextField label={'IP'} value={reactDevtoolsIP} onChange={(e) => setReactDevtoolsIP(e?.target.value)} />
<TextField
label={t('SettingsDeveloperIndex.react_devtools.ip_label')}
value={reactDevtoolsIP}
onChange={(e) => setReactDevtoolsIP(e?.target.value)}
/>
</div>
</>
}
@@ -1,5 +1,6 @@
import { Dropdown, Field } from 'decky-frontend-lib';
import { FunctionComponent } from 'react';
import { useTranslation } from 'react-i18next';
import Logger from '../../../../logger';
import { callUpdaterMethod } from '../../../../updater';
@@ -14,17 +15,23 @@ enum UpdateBranch {
}
const BranchSelect: FunctionComponent<{}> = () => {
const { t } = useTranslation();
const tBranches = [
t('BranchSelect.update_channel.stable'),
t('BranchSelect.update_channel.prerelease'),
t('BranchSelect.update_channel.testing'),
];
const [selectedBranch, setSelectedBranch] = useSetting<UpdateBranch>('branch', UpdateBranch.Prerelease);
return (
// Returns numerical values from 0 to 2 (with current branch setup as of 8/28/22)
// 0 being stable, 1 being pre-release and 2 being nightly
<Field label="Decky Update Channel" childrenContainerWidth={'fixed'}>
<Field label={t('BranchSelect.update_channel.label')} childrenContainerWidth={'fixed'}>
<Dropdown
rgOptions={Object.values(UpdateBranch)
.filter((branch) => typeof branch == 'string')
.map((branch) => ({
label: branch,
label: tBranches[UpdateBranch[branch]],
data: UpdateBranch[branch],
}))}
selectedOption={selectedBranch}
@@ -1,19 +1,17 @@
import { Field, Toggle } from 'decky-frontend-lib';
import { useTranslation } from 'react-i18next';
import { FaChrome } from 'react-icons/fa';
import { useSetting } from '../../../../utils/hooks/useSetting';
export default function RemoteDebuggingSettings() {
const [allowRemoteDebugging, setAllowRemoteDebugging] = useSetting<boolean>('cef_forward', false);
const { t } = useTranslation();
return (
<Field
label="Allow Remote CEF Debugging"
description={
<span style={{ whiteSpace: 'pre-line' }}>
Allows unauthenticated access to the CEF debugger to anyone in your network.
</span>
}
label={t('RemoteDebugging.remote_cef.label')}
description={<span style={{ whiteSpace: 'pre-line' }}>{t('RemoteDebugging.remote_cef.desc')}</span>}
icon={<FaChrome style={{ display: 'block' }} />}
>
<Toggle
@@ -1,5 +1,6 @@
import { Dropdown, Field, TextField } from 'decky-frontend-lib';
import { FunctionComponent } from 'react';
import { useTranslation } from 'react-i18next';
import { FaShapes } from 'react-icons/fa';
import Logger from '../../../../logger';
@@ -11,17 +12,23 @@ const logger = new Logger('StoreSelect');
const StoreSelect: FunctionComponent<{}> = () => {
const [selectedStore, setSelectedStore] = useSetting<Store>('store', Store.Default);
const [selectedStoreURL, setSelectedStoreURL] = useSetting<string | null>('store-url', null);
const { t } = useTranslation();
const tStores = [
t('StoreSelect.store_channel.default'),
t('StoreSelect.store_channel.testing'),
t('StoreSelect.store_channel.custom'),
];
// Returns numerical values from 0 to 2 (with current branch setup as of 8/28/22)
// 0 being Default, 1 being Testing and 2 being Custom
return (
<>
<Field label="Plugin Store Channel" childrenContainerWidth={'fixed'}>
<Field label={t('StoreSelect.store_channel.label')} childrenContainerWidth={'fixed'}>
<Dropdown
rgOptions={Object.values(Store)
.filter((store) => typeof store == 'string')
.map((store) => ({
label: store,
label: tStores[Store[store]],
data: Store[store],
}))}
selectedOption={selectedStore}
@@ -33,11 +40,11 @@ const StoreSelect: FunctionComponent<{}> = () => {
</Field>
{selectedStore == Store.Custom && (
<Field
label="Custom Store"
label={t('StoreSelect.custom_store.label')}
indentLevel={1}
description={
<TextField
label={'URL'}
label={t('StoreSelect.custom_store.url_label')}
value={selectedStoreURL || undefined}
onChange={(e) => setSelectedStoreURL(e?.target.value || null)}
/>
@@ -12,6 +12,7 @@ import {
import { useCallback } from 'react';
import { Suspense, lazy } from 'react';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { FaExclamation } from 'react-icons/fa';
import { VerInfo, callUpdaterMethod, finishUpdate } from '../../../../updater';
@@ -23,6 +24,7 @@ const MarkdownRenderer = lazy(() => import('../../../Markdown'));
function PatchNotesModal({ versionInfo, closeModal }: { versionInfo: VerInfo | null; closeModal?: () => {} }) {
const SP = findSP();
const { t } = useTranslation();
return (
<Focusable onCancelButton={closeModal}>
<FocusRing>
@@ -45,7 +47,7 @@ function PatchNotesModal({ versionInfo, closeModal }: { versionInfo: VerInfo | n
<MarkdownRenderer onDismiss={closeModal}>{versionInfo.all[id].body}</MarkdownRenderer>
</WithSuspense>
) : (
'no patch notes for this version'
t('Updater.no_patch_notes_desc')
)}
</div>
</Focusable>
@@ -58,7 +60,7 @@ function PatchNotesModal({ versionInfo, closeModal }: { versionInfo: VerInfo | n
initialColumn={0}
autoFocus={true}
fnGetColumnWidth={() => SP.innerWidth}
name="Decky Updates"
name={t('Updater.decky_updates') as string}
/>
</FocusRing>
</Focusable>
@@ -72,6 +74,8 @@ export default function UpdaterSettings() {
const [updateProgress, setUpdateProgress] = useState<number>(-1);
const [reloading, setReloading] = useState<boolean>(false);
const { t } = useTranslation();
useEffect(() => {
window.DeckyUpdater = {
updateProgress: (i) => {
@@ -93,14 +97,14 @@ export default function UpdaterSettings() {
return (
<>
<Field
onOptionsActionDescription={versionInfo?.all ? 'Patch Notes' : undefined}
onOptionsActionDescription={versionInfo?.all ? t('Updater.patch_notes_desc') : undefined}
onOptionsButton={versionInfo?.all ? showPatchNotes : undefined}
label="Decky Updates"
label={t('Updater.updates.label')}
description={
checkingForUpdates || versionInfo?.remote?.tag_name != versionInfo?.current || !versionInfo?.remote ? (
''
) : (
<span>Up to date: running {versionInfo?.current}</span>
<span>{t('Updater.updates.lat_version', { ver: versionInfo?.current })} </span>
)
}
icon={
@@ -129,10 +133,10 @@ export default function UpdaterSettings() {
}
>
{checkingForUpdates
? 'Checking'
? t('Updater.updates.checking')
: !versionInfo?.remote || versionInfo?.remote?.tag_name == versionInfo?.current
? 'Check For Updates'
: 'Install Update'}
? t('Updater.updates.check_button')
: t('Updater.updates.install_button')}
</DialogButton>
) : (
<ProgressBarWithInfo
@@ -140,7 +144,7 @@ export default function UpdaterSettings() {
bottomSeparator="none"
nProgress={updateProgress}
indeterminate={reloading}
sOperationText={reloading ? 'Reloading' : 'Updating'}
sOperationText={reloading ? t('Updater.updates.reloading') : t('Updater.updates.updating')}
/>
)}
</Field>
@@ -1,4 +1,5 @@
import { DialogBody, DialogControlsSection, DialogControlsSectionHeader, Field, Toggle } from 'decky-frontend-lib';
import { useTranslation } from 'react-i18next';
import { useDeckyState } from '../../../DeckyState';
import BranchSelect from './BranchSelect';
@@ -13,21 +14,22 @@ export default function GeneralSettings({
setIsDeveloper: (val: boolean) => void;
}) {
const { versionInfo } = useDeckyState();
const { t } = useTranslation();
return (
<DialogBody>
<DialogControlsSection>
<DialogControlsSectionHeader>Updates</DialogControlsSectionHeader>
<DialogControlsSectionHeader>{t('SettingsGeneralIndex.updates.header')}</DialogControlsSectionHeader>
<UpdaterSettings />
</DialogControlsSection>
<DialogControlsSection>
<DialogControlsSectionHeader>Beta Participation</DialogControlsSectionHeader>
<DialogControlsSectionHeader>{t('SettingsGeneralIndex.beta.header')}</DialogControlsSectionHeader>
<BranchSelect />
<StoreSelect />
</DialogControlsSection>
<DialogControlsSection>
<DialogControlsSectionHeader>Other</DialogControlsSectionHeader>
<Field label="Enable Developer Mode">
<DialogControlsSectionHeader>{t('SettingsGeneralIndex.other.header')}</DialogControlsSectionHeader>
<Field label={t('SettingsGeneralIndex.developer_mode.label')}>
<Toggle
value={isDeveloper}
onChange={(toggleValue) => {
@@ -37,8 +39,8 @@ export default function GeneralSettings({
</Field>
</DialogControlsSection>
<DialogControlsSection>
<DialogControlsSectionHeader>About</DialogControlsSectionHeader>
<Field label="Decky Version" focusable={true}>
<DialogControlsSectionHeader>{t('SettingsGeneralIndex.about.header')}</DialogControlsSectionHeader>
<Field label={t('SettingsGeneralIndex.about.decky_version')} focusable={true}>
<div style={{ color: 'var(--gpSystemLighterGrey)' }}>{versionInfo?.current}</div>
</Field>
</DialogControlsSection>
@@ -10,9 +10,16 @@ import {
showContextMenu,
} from 'decky-frontend-lib';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { FaDownload, FaEllipsisH, FaRecycle } from 'react-icons/fa';
import { StorePluginVersion, getPluginList, requestPluginInstall } from '../../../../store';
import { InstallType } from '../../../../plugin';
import {
StorePluginVersion,
getPluginList,
requestMultiplePluginInstalls,
requestPluginInstall,
} from '../../../../store';
import { useSetting } from '../../../../utils/hooks/useSetting';
import { useDeckyState } from '../../../DeckyState';
@@ -25,19 +32,33 @@ async function reinstallPlugin(pluginName: string, currentVersion?: string) {
const remotePlugin = serverData?.find((x) => x.name == pluginName);
if (remotePlugin && remotePlugin.versions?.length > 0) {
const currentVersionData = remotePlugin.versions.find((version) => version.name == currentVersion);
if (currentVersionData) requestPluginInstall(pluginName, currentVersionData);
if (currentVersionData) requestPluginInstall(pluginName, currentVersionData, InstallType.REINSTALL);
}
}
function PluginInteractables(props: { entry: ReorderableEntry<PluginData> }) {
const data = props.entry.data;
const { t } = useTranslation();
let pluginName = labelToName(props.entry.label, data?.version);
const showCtxMenu = (e: MouseEvent | GamepadEvent) => {
showContextMenu(
<Menu label="Plugin Actions">
<MenuItem onSelected={() => window.DeckyPluginLoader.importPlugin(pluginName, data?.version)}>Reload</MenuItem>
<MenuItem onSelected={() => window.DeckyPluginLoader.uninstallPlugin(pluginName)}>Uninstall</MenuItem>
<Menu label={t('PluginListIndex.plugin_actions')}>
<MenuItem onSelected={() => window.DeckyPluginLoader.importPlugin(pluginName, data?.version)}>
{t('PluginListIndex.reload')}
</MenuItem>
<MenuItem
onSelected={() =>
window.DeckyPluginLoader.uninstallPlugin(
pluginName,
t('PluginLoader.plugin_uninstall.title', { name: pluginName }),
t('PluginLoader.plugin_uninstall.button'),
t('PluginLoader.plugin_uninstall.desc', { name: pluginName }),
)
}
>
{t('PluginListIndex.uninstall')}
</MenuItem>
</Menu>,
e.currentTarget ?? window,
);
@@ -48,12 +69,12 @@ function PluginInteractables(props: { entry: ReorderableEntry<PluginData> }) {
{data?.update ? (
<DialogButton
style={{ height: '40px', minWidth: '60px', marginRight: '10px' }}
onClick={() => requestPluginInstall(pluginName, data?.update as StorePluginVersion)}
onOKButton={() => requestPluginInstall(pluginName, data?.update as StorePluginVersion)}
onClick={() => requestPluginInstall(pluginName, data?.update as StorePluginVersion, InstallType.UPDATE)}
onOKButton={() => requestPluginInstall(pluginName, data?.update as StorePluginVersion, InstallType.UPDATE)}
>
<div style={{ display: 'flex', flexDirection: 'row' }}>
Update to {data?.update?.name}
<FaDownload style={{ paddingLeft: '2rem' }} />
<div style={{ display: 'flex', minWidth: '180px', justifyContent: 'space-between', alignItems: 'center' }}>
{t('PluginListIndex.update_to', { name: data?.update?.name })}
<FaDownload style={{ paddingLeft: '1rem' }} />
</div>
</DialogButton>
) : (
@@ -62,14 +83,22 @@ function PluginInteractables(props: { entry: ReorderableEntry<PluginData> }) {
onClick={() => reinstallPlugin(pluginName, data?.version)}
onOKButton={() => reinstallPlugin(pluginName, data?.version)}
>
<div style={{ display: 'flex', flexDirection: 'row' }}>
Reinstall
<FaRecycle style={{ paddingLeft: '5.3rem' }} />
<div style={{ display: 'flex', minWidth: '180px', justifyContent: 'space-between', alignItems: 'center' }}>
{t('PluginListIndex.reinstall')}
<FaRecycle style={{ paddingLeft: '1rem' }} />
</div>
</DialogButton>
)}
<DialogButton
style={{ height: '40px', width: '40px', padding: '10px 12px', minWidth: '40px' }}
style={{
height: '40px',
width: '40px',
padding: '10px 12px',
minWidth: '40px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
}}
onClick={showCtxMenu}
onOKButton={showCtxMenu}
>
@@ -90,6 +119,7 @@ export default function PluginList() {
'pluginOrder',
plugins.map((plugin) => plugin.name),
);
const { t } = useTranslation();
useEffect(() => {
window.DeckyPluginLoader.checkPluginUpdates();
@@ -115,7 +145,7 @@ export default function PluginList() {
if (plugins.length === 0) {
return (
<div>
<p>No plugins installed</p>
<p>{t('PluginListIndex.no_plugin')}</p>
</div>
);
}
@@ -129,7 +159,31 @@ export default function PluginList() {
return (
<DialogBody>
<DialogControlsSection>
{updates && updates.size > 0 && (
<DialogButton
onClick={() =>
requestMultiplePluginInstalls(
[...updates.entries()].map(([plugin, selectedVer]) => ({
installType: InstallType.UPDATE,
plugin,
selectedVer,
})),
)
}
style={{
position: 'absolute',
top: '57px',
right: '2.8vw',
width: 'auto',
display: 'flex',
alignItems: 'center',
}}
>
{t('PluginListIndex.update_all', { count: updates.size })}
<FaDownload style={{ paddingLeft: '1rem' }} />
</DialogButton>
)}
<DialogControlsSection style={{ marginTop: 0 }}>
<ReorderableList<PluginData> entries={pluginEntries} onSave={onSave} interactables={PluginInteractables} />
</DialogControlsSection>
</DialogBody>
+82 -84
View File
@@ -6,8 +6,10 @@ import {
SingleDropdownOption,
SuspensefulImage,
} from 'decky-frontend-lib';
import { FC, useState } from 'react';
import { CSSProperties, FC, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { InstallType } from '../../plugin';
import { StorePlugin, StorePluginVersion, requestPluginInstall } from '../../store';
interface PluginCardProps {
@@ -16,7 +18,9 @@ interface PluginCardProps {
const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
const [selectedOption, setSelectedOption] = useState<number>(0);
const root: boolean = plugin.tags.some((tag) => tag === 'root');
const root = plugin.tags.some((tag) => tag === 'root');
const { t } = useTranslation();
return (
<div
@@ -26,7 +30,6 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
marginRight: '20px',
marginBottom: '20px',
display: 'flex',
alignItems: 'center',
}}
>
<div
@@ -55,107 +58,102 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
width: 'calc(100% - 320px)', // The calc is here so that the info section doesn't expand into the image
display: 'flex',
flexDirection: 'column',
height: '100%',
justifyContent: 'space-between',
marginLeft: '1em',
justifyContent: 'center',
gap: '10px',
}}
>
<span
className="deckyStoreCardTitle"
style={{
fontSize: '1.25em',
fontWeight: 'bold',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
width: '90%',
}}
>
{plugin.name}
</span>
<span
className="deckyStoreCardAuthor"
style={{
marginRight: 'auto',
fontSize: '1em',
}}
>
{plugin.author}
</span>
<span
className="deckyStoreCardDescription"
style={{
fontSize: '13px',
color: '#969696',
WebkitLineClamp: root ? '2' : '3',
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
display: '-webkit-box',
}}
>
{plugin.description ? (
plugin.description
) : (
<span>
<i style={{ color: '#666' }}>No description provided.</i>
</span>
)}
</span>
{root && (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<span
className="deckyStoreCardDescription deckyStoreCardDescriptionRoot"
className="deckyStoreCardTitle"
style={{
fontSize: '13px',
color: '#fee75c',
fontSize: '1.25em',
fontWeight: 'bold',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
width: '90%',
}}
>
<i>This plugin has full access to your Steam Deck.</i>{' '}
<a
className="deckyStoreCardDescriptionRootLink"
href="https://deckbrew.xyz/root"
target="_blank"
{plugin.name}
</span>
<span
className="deckyStoreCardAuthor"
style={{
marginRight: 'auto',
fontSize: '1em',
}}
>
{plugin.author}
</span>
<span
className="deckyStoreCardDescription"
style={{
fontSize: '13px',
color: '#969696',
WebkitLineClamp: root ? '2' : '3',
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
display: '-webkit-box',
}}
>
{plugin.description ? (
plugin.description
) : (
<span>
<i style={{ color: '#666' }}>{t('PluginCard.plugin_no_desc')}</i>
</span>
)}
</span>
{root && (
<div
className="deckyStoreCardDescription deckyStoreCardDescriptionRoot"
style={{
fontSize: '13px',
color: '#fee75c',
textDecoration: 'none',
marginTop: 'auto',
}}
>
deckbrew.xyz/root
</a>
</span>
)}
<div
className="deckyStoreCardButtonRow"
style={{
marginTop: '1em',
width: '100%',
overflow: 'hidden',
}}
>
<i>{t('PluginCard.plugin_full_access')}</i>{' '}
<a
className="deckyStoreCardDescriptionRootLink"
href="https://deckbrew.xyz/root"
target="_blank"
style={{
color: '#fee75c',
textDecoration: 'none',
}}
>
deckbrew.xyz/root
</a>
</div>
)}
</div>
<div className="deckyStoreCardButtonRow">
<PanelSectionRow>
<Focusable style={{ display: 'flex', maxWidth: '100%' }}>
<Focusable style={{ display: 'flex', gap: '5px', padding: 0 }}>
<div
className="deckyStoreCardInstallContainer"
style={{
paddingTop: '0px',
paddingBottom: '0px',
width: '40%',
}}
style={
{
paddingTop: '0px',
paddingBottom: '0px',
flexGrow: 1,
'--field-negative-horizontal-margin': 0,
} as CSSProperties
}
>
<ButtonItem
bottomSeparator="none"
layout="below"
onClick={() => requestPluginInstall(plugin.name, plugin.versions[selectedOption])}
onClick={() =>
requestPluginInstall(plugin.name, plugin.versions[selectedOption], InstallType.INSTALL)
}
>
<span className="deckyStoreCardInstallText">Install</span>
<span className="deckyStoreCardInstallText">{t('PluginCard.plugin_install')}</span>
</ButtonItem>
</div>
<div
className="deckyStoreCardVersionContainer"
style={{
marginLeft: '5%',
width: '30%',
}}
>
<div className="deckyStoreCardVersionContainer" style={{ minWidth: '130px' }}>
<Dropdown
rgOptions={
plugin.versions.map((version: StorePluginVersion, index) => ({
@@ -163,7 +161,7 @@ const PluginCard: FC<PluginCardProps> = ({ plugin }) => {
label: version.name,
})) as SingleDropdownOption[]
}
menuLabel="Plugin Version"
menuLabel={t('PluginCard.plugin_version_label') as string}
selectedOption={selectedOption}
onChange={({ data }) => setSelectedOption(data)}
/>
+31 -23
View File
@@ -9,6 +9,7 @@ import {
findModule,
} from 'decky-frontend-lib';
import { FC, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import logo from '../../../assets/plugin_store.png';
import Logger from '../../logger';
@@ -25,6 +26,8 @@ const StorePage: FC<{}> = () => {
return false;
});
const { t } = useTranslation();
useEffect(() => {
(async () => {
const res = await getPluginList();
@@ -54,13 +57,13 @@ const StorePage: FC<{}> = () => {
}}
tabs={[
{
title: 'Browse',
title: t('Store.store_tabs.title'),
content: <BrowseTab children={{ data: data }} />,
id: 'browse',
renderTabAddon: () => <span className={TabCount}>{data.length}</span>,
},
{
title: 'About',
title: t('Store.store_tabs.about'),
content: <AboutTab />,
id: 'about',
},
@@ -73,10 +76,12 @@ const StorePage: FC<{}> = () => {
};
const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
const { t } = useTranslation();
const sortOptions = useMemo(
(): DropdownOption[] => [
{ data: 1, label: 'Alphabetical (A to Z)' },
{ data: 2, label: 'Alphabetical (Z to A)' },
{ data: 1, label: t('Store.store_tabs.alph_desc') },
{ data: 2, label: t('Store.store_tabs.alph_asce') },
],
[],
);
@@ -105,11 +110,11 @@ const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
width: '47.5%',
}}
>
<span className="DialogLabel">Sort</span>
<span className="DialogLabel">{t("Store.store_sort.label")}</span>
<Dropdown
menuLabel="Sort"
menuLabel={t("Store.store_sort.label") as string}
rgOptions={sortOptions}
strDefaultLabel="Last Updated (Newest)"
strDefaultLabel={t("Store.store_sort.label_def") as string}
selectedOption={selectedSort}
onChange={(e) => setSort(e.data)}
/>
@@ -122,11 +127,11 @@ const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
marginLeft: 'auto',
}}
>
<span className="DialogLabel">Filter</span>
<span className="DialogLabel">{t("Store.store_filter.label")}</span>
<Dropdown
menuLabel="Filter"
menuLabel={t("Store.store_filter.label")}
rgOptions={filterOptions}
strDefaultLabel="All"
strDefaultLabel={t("Store.store_filter.label_def")}
selectedOption={selectedFilter}
onChange={(e) => setFilter(e.data)}
/>
@@ -136,7 +141,7 @@ const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
<div style={{ justifyContent: 'center', display: 'flex' }}>
<Focusable style={{ display: 'flex', alignItems: 'center', width: '96%' }}>
<div style={{ width: '100%' }}>
<TextField label="Search" value={searchFieldValue} onChange={(e) => setSearchValue(e.target.value)} />
<TextField label={t("Store.store_search.label")} value={searchFieldValue} onChange={(e) => setSearchValue(e.target.value)} />
</div>
</Focusable>
</div>
@@ -151,11 +156,11 @@ const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
maxWidth: '100%',
}}
>
<span className="DialogLabel">Sort</span>
<span className="DialogLabel">{t('Store.store_sort.label')}</span>
<Dropdown
menuLabel="Sort"
menuLabel={t('Store.store_sort.label') as string}
rgOptions={sortOptions}
strDefaultLabel="Last Updated (Newest)"
strDefaultLabel={t('Store.store_sort.label_def') as string}
selectedOption={selectedSort}
onChange={(e) => setSort(e.data)}
/>
@@ -165,7 +170,11 @@ const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
<div style={{ justifyContent: 'center', display: 'flex' }}>
<Focusable style={{ display: 'flex', alignItems: 'center', width: '96%' }}>
<div style={{ width: '100%' }}>
<TextField label="Search" value={searchFieldValue} onChange={(e) => setSearchValue(e.target.value)} />
<TextField
label={t('Store.store_search.label')}
value={searchFieldValue}
onChange={(e) => setSearchValue(e.target.value)}
/>
</div>
</Focusable>
</div>
@@ -192,6 +201,8 @@ const BrowseTab: FC<{ children: { data: StorePlugin[] } }> = (data) => {
};
const AboutTab: FC<{}> = () => {
const { t } = useTranslation();
return (
<div
style={{
@@ -216,7 +227,7 @@ const AboutTab: FC<{}> = () => {
/>
<span className="deckyStoreAboutHeader">Testing</span>
<span>
Please consider testing new plugins to help the Decky Loader team!{' '}
{t('Store.store_testing_cta')}{' '}
<a
href="https://deckbrew.xyz/testing"
target="_blank"
@@ -227,13 +238,10 @@ const AboutTab: FC<{}> = () => {
deckbrew.xyz/testing
</a>
</span>
<span className="deckyStoreAboutHeader">Contributing</span>
<span>
If you would like to contribute to the Decky Plugin Store, check the SteamDeckHomebrew/decky-plugin-template
repository on GitHub. Information on development and distribution is available in the README.
</span>
<span className="deckyStoreAboutHeader">Source Code</span>
<span>All plugin source code is available on SteamDeckHomebrew/decky-plugin-database repository on GitHub.</span>
<span className="deckyStoreAboutHeader">{t('Store.store_contrib.label')}</span>
<span>{t('Store.store_contrib.desc')}</span>
<span className="deckyStoreAboutHeader">{t('Store.store_source.label')}</span>
<span>{t('Store.store_source.desc')}</span>
</div>
);
};
+9 -47
View File
@@ -1,27 +1,10 @@
import {
Navigation,
ReactRouter,
Router,
fakeRenderComponent,
findInReactTree,
findInTree,
findModule,
findModuleChild,
gamepadDialogClasses,
gamepadSliderClasses,
playSectionClasses,
quickAccessControlsClasses,
quickAccessMenuClasses,
scrollClasses,
scrollPanelClasses,
sleep,
staticClasses,
updaterFieldClasses,
} from 'decky-frontend-lib';
import { findModuleChild, sleep } from 'decky-frontend-lib';
import { useTranslation } from 'react-i18next';
import { FaReact } from 'react-icons/fa';
import Logger from './logger';
import { getSetting } from './utils/settings';
import TranslationHelper, { TranslationClass } from './utils/TranslationHelper';
const logger = new Logger('DeveloperMode');
@@ -59,8 +42,12 @@ export async function setShowValveInternal(show: boolean) {
export async function setShouldConnectToReactDevTools(enable: boolean) {
window.DeckyPluginLoader.toaster.toast({
title: (enable ? 'Enabling' : 'Disabling') + ' React DevTools',
body: 'Reloading in 5 seconds',
title: enable ? (
<TranslationHelper trans_class={TranslationClass.DEVELOPER} trans_text={'enabling'} />
) : (
<TranslationHelper trans_class={TranslationClass.DEVELOPER} trans_text={'disabling'} />
),
body: <TranslationHelper trans_class={TranslationClass.DEVELOPER} trans_text={'5secreload'} />,
icon: <FaReact />,
});
await sleep(5000);
@@ -77,29 +64,4 @@ export async function startup() {
if ((isRDTEnabled && !window.deckyHasConnectedRDT) || (!isRDTEnabled && window.deckyHasConnectedRDT))
setShouldConnectToReactDevTools(isRDTEnabled);
logger.log('Exposing decky-frontend-lib APIs as DFL');
window.DFL = {
findModuleChild,
findModule,
Navigation,
Router,
ReactRouter,
ReactUtils: {
fakeRenderComponent,
findInReactTree,
findInTree,
},
classes: {
scrollClasses,
staticClasses,
playSectionClasses,
scrollPanelClasses,
updaterFieldClasses,
gamepadDialogClasses,
gamepadSliderClasses,
quickAccessMenuClasses,
quickAccessControlsClasses,
},
};
}
+6
View File
@@ -0,0 +1,6 @@
// Sets up DFL, then loads start.ts which starts up the loader
(async () => {
console.debug('Setting up decky-frontend-lib...');
window.DFL = await import('decky-frontend-lib');
await import('./start');
})();
+92 -23
View File
@@ -1,16 +1,28 @@
import { ConfirmModal, ModalRoot, Patch, QuickAccessTab, Router, showModal, sleep } from 'decky-frontend-lib';
import {
ConfirmModal,
ModalRoot,
PanelSection,
PanelSectionRow,
Patch,
QuickAccessTab,
Router,
quickAccessMenuClasses,
showModal,
sleep,
} from 'decky-frontend-lib';
import { FC, lazy } from 'react';
import { FaCog, FaExclamationCircle, FaPlug } from 'react-icons/fa';
import { FaExclamationCircle, FaPlug } from 'react-icons/fa';
import { DeckyState, DeckyStateContextProvider, useDeckyState } from './components/DeckyState';
import LegacyPlugin from './components/LegacyPlugin';
import { deinitFilepickerPatches, initFilepickerPatches } from './components/modals/filepicker/patches';
import MultiplePluginsInstallModal from './components/modals/MultiplePluginsInstallModal';
import PluginInstallModal from './components/modals/PluginInstallModal';
import NotificationBadge from './components/NotificationBadge';
import PluginView from './components/PluginView';
import WithSuspense from './components/WithSuspense';
import Logger from './logger';
import { Plugin } from './plugin';
import { InstallType, Plugin } from './plugin';
import RouterHook from './router-hook';
import { deinitSteamFixes, initSteamFixes } from './steamfixes';
import { checkForUpdates } from './store';
@@ -19,6 +31,7 @@ import OldTabsHook from './tabs-hook.old';
import Toaster from './toaster';
import { VerInfo, callUpdaterMethod } from './updater';
import { getSetting } from './utils/settings';
import TranslationHelper, { TranslationClass } from './utils/TranslationHelper';
const StorePage = lazy(() => import('./components/store/Store'));
const SettingsPage = lazy(() => import('./components/settings'));
@@ -98,8 +111,14 @@ class PluginLoader extends Logger {
const versionInfo = await this.updateVersion();
if (versionInfo?.remote && versionInfo?.remote?.tag_name != versionInfo?.current) {
this.toaster.toast({
title: 'Decky',
body: `Update to ${versionInfo?.remote?.tag_name} available!`,
title: <TranslationHelper trans_class={TranslationClass.PLUGIN_LOADER} trans_text="decky_title" />,
body: (
<TranslationHelper
trans_class={TranslationClass.PLUGIN_LOADER}
trans_text="decky_update_available"
i18n_args={{ tag_name: versionInfo?.remote?.tag_name }}
/>
),
onClick: () => Router.Navigate('/decky/settings'),
});
this.deckyState.setHasLoaderUpdate(true);
@@ -118,26 +137,52 @@ class PluginLoader extends Logger {
const updates = await this.checkPluginUpdates();
if (updates?.size > 0) {
this.toaster.toast({
title: 'Decky',
body: `Updates available for ${updates.size} plugin${updates.size > 1 ? 's' : ''}!`,
title: <TranslationHelper trans_class={TranslationClass.PLUGIN_LOADER} trans_text="decky_title" />,
body: (
<TranslationHelper
trans_class={TranslationClass.PLUGIN_LOADER}
trans_text="plugin_update"
i18n_args={{ count: updates.size }}
/>
),
onClick: () => Router.Navigate('/decky/settings/plugins'),
});
}
}
public addPluginInstallPrompt(artifact: string, version: string, request_id: string, hash: string) {
public addPluginInstallPrompt(
artifact: string,
version: string,
request_id: string,
hash: string,
install_type: number,
) {
showModal(
<PluginInstallModal
artifact={artifact}
version={version}
hash={hash}
installType={install_type}
onOK={() => this.callServerMethod('confirm_plugin_install', { request_id })}
onCancel={() => this.callServerMethod('cancel_plugin_install', { request_id })}
/>,
);
}
public uninstallPlugin(name: string) {
public addMultiplePluginsInstallPrompt(
request_id: string,
requests: { name: string; version: string; hash: string; install_type: InstallType }[],
) {
showModal(
<MultiplePluginsInstallModal
requests={requests}
onOK={() => this.callServerMethod('confirm_plugin_install', { request_id })}
onCancel={() => this.callServerMethod('cancel_plugin_install', { request_id })}
/>,
);
}
public uninstallPlugin(name: string, title: string, button_text: string, description: string) {
showModal(
<ConfirmModal
onOK={async () => {
@@ -146,10 +191,10 @@ class PluginLoader extends Logger {
onCancel={() => {
// do nothing
}}
strTitle={`Uninstall ${name}`}
strOKButtonText={'Uninstall'}
strTitle={title}
strOKButtonText={button_text}
>
Are you sure you want to uninstall {name}?
{description}
</ConfirmModal>,
);
}
@@ -244,16 +289,30 @@ class PluginLoader extends Logger {
} catch (e) {
this.error('Error loading plugin ' + name, e);
const TheError: FC<{}> = () => (
<>
Error:{' '}
<pre>
<code>{e instanceof Error ? e.stack : JSON.stringify(e)}</code>
</pre>
<>
Please go to <FaCog style={{ display: 'inline' }} /> in the Decky menu if you need to uninstall this
plugin.
</>
</>
<PanelSection>
<PanelSectionRow>
<div
className={quickAccessMenuClasses.FriendsTitle}
style={{ display: 'flex', justifyContent: 'center' }}
>
<TranslationHelper trans_class={TranslationClass.PLUGIN_LOADER} trans_text="error" />
</div>
</PanelSectionRow>
<PanelSectionRow>
<pre style={{ overflowX: 'scroll' }}>
<code>{e instanceof Error ? e.stack : JSON.stringify(e)}</code>
</pre>
</PanelSectionRow>
<PanelSectionRow>
<div className={quickAccessMenuClasses.Text}>
<TranslationHelper
trans_class={TranslationClass.PLUGIN_LOADER}
trans_text="plugin_error_uninstall"
i18n_args={{ name: name }}
/>
</div>
</PanelSectionRow>
</PanelSection>
);
this.plugins.push({
name: name,
@@ -261,7 +320,17 @@ class PluginLoader extends Logger {
content: <TheError />,
icon: <FaExclamationCircle />,
});
this.toaster.toast({ title: 'Error loading ' + name, body: '' + e, icon: <FaExclamationCircle /> });
this.toaster.toast({
title: (
<TranslationHelper
trans_class={TranslationClass.PLUGIN_LOADER}
trans_text="plugin_load_error.toast"
i18n_args={{ name: name }}
/>
),
body: '' + e,
icon: <FaExclamationCircle />,
});
}
} else throw new Error(`${name} frontend_bundle not OK`);
}
+6
View File
@@ -6,3 +6,9 @@ export interface Plugin {
onDismount?(): void;
alwaysRender?: boolean;
}
export enum InstallType {
INSTALL,
REINSTALL,
UPDATE,
}
@@ -1,4 +1,6 @@
import { Navigation, Router, sleep } from 'decky-frontend-lib';
import i18n from 'i18next';
import Backend from 'i18next-http-backend';
import { initReactI18next } from 'react-i18next';
import PluginLoader from './plugin-loader';
import { DeckyUpdater } from './updater';
@@ -16,29 +18,38 @@ declare global {
}
}
(async () => {
try {
if (!Router.NavigateToAppProperties || !Router.NavigateToLibraryTab || !Router.NavigateToInvites) {
while (!Navigation.NavigateToAppProperties) await sleep(100);
const shims = {
NavigateToAppProperties: Navigation.NavigateToAppProperties,
NavigateToInvites: Navigation.NavigateToInvites,
NavigateToLibraryTab: Navigation.NavigateToLibraryTab,
};
(Router as unknown as any).deckyShim = true;
Object.assign(Router, shims);
}
} catch (e) {
console.error('[DECKY]: Error initializing Navigation interface shims', e);
}
})();
(async () => {
window.deckyAuthToken = await fetch('http://127.0.0.1:1337/auth/token').then((r) => r.text());
i18n
.use(Backend)
.use(initReactI18next)
.init({
load: 'currentOnly',
detection: {
order: ['querystring', 'navigator'],
lookupQuerystring: 'lng',
},
//debug: true,
lng: navigator.language,
fallbackLng: 'en-US',
interpolation: {
escapeValue: true,
},
returnEmptyString: false,
backend: {
loadPath: 'http://127.0.0.1:1337/locales/{{lng}}.json',
customHeaders: {
Authentication: window.deckyAuthToken,
},
requestOptions: {
credentials: 'include',
},
},
});
window.DeckyPluginLoader?.dismountAll();
window.DeckyPluginLoader?.deinit();
window.DeckyPluginLoader = new PluginLoader();
window.DeckyPluginLoader.init();
window.importDeckyPlugin = function (name: string, version: string) {
@@ -62,3 +73,5 @@ declare global {
setTimeout(() => window.syncDeckyPlugins(), 5000);
})();
export default i18n;
+26 -4
View File
@@ -1,4 +1,4 @@
import { Plugin } from './plugin';
import { InstallType, Plugin } from './plugin';
import { getSetting, setSetting } from './utils/settings';
export enum Store {
@@ -23,6 +23,12 @@ export interface StorePlugin {
image_url: string;
}
export interface PluginInstallRequest {
plugin: string;
selectedVer: StorePluginVersion;
installType: InstallType;
}
// name: version
export type PluginUpdateMapping = Map<string, StorePluginVersion>;
@@ -73,14 +79,26 @@ export async function installFromURL(url: string) {
});
}
export async function requestPluginInstall(plugin: string, selectedVer: StorePluginVersion) {
const artifactUrl =
selectedVer.artifact ?? `https://cdn.tzatzikiweeb.moe/file/steam-deck-homebrew/versions/${selectedVer.hash}.zip`;
export async function requestPluginInstall(plugin: string, selectedVer: StorePluginVersion, installType: InstallType) {
const artifactUrl = selectedVer.artifact ?? pluginUrl(selectedVer.hash);
await window.DeckyPluginLoader.callServerMethod('install_plugin', {
name: plugin,
artifact: artifactUrl,
version: selectedVer.name,
hash: selectedVer.hash,
install_type: installType,
});
}
export async function requestMultiplePluginInstalls(requests: PluginInstallRequest[]) {
await window.DeckyPluginLoader.callServerMethod('install_plugins', {
requests: requests.map(({ plugin, installType, selectedVer }) => ({
name: plugin,
artifact: selectedVer.artifact ?? pluginUrl(selectedVer.hash),
version: selectedVer.name,
hash: selectedVer.hash,
install_type: installType,
})),
});
}
@@ -95,3 +113,7 @@ export async function checkForUpdates(plugins: Plugin[]): Promise<PluginUpdateMa
}
return updateMap;
}
function pluginUrl(hash: string) {
return `https://cdn.tzatzikiweeb.moe/file/steam-deck-homebrew/versions/${hash}.zip`;
}
+64
View File
@@ -0,0 +1,64 @@
import { FC } from 'react';
import { Translation } from 'react-i18next';
import Logger from '../logger';
import { InstallType } from '../plugin';
export enum TranslationClass {
PLUGIN_LOADER = 'PluginLoader',
PLUGIN_INSTALL_MODAL = 'PluginInstallModal',
DEVELOPER = 'Developer',
}
interface TranslationHelperProps {
trans_class: TranslationClass;
trans_text: string;
i18n_args?: {};
install_type?: number;
}
const logger = new Logger('TranslationHelper');
const TranslationHelper: FC<TranslationHelperProps> = ({
trans_class,
trans_text,
i18n_args = null,
install_type = 0,
}) => {
return (
<Translation>
{(t, {}) => {
switch (trans_class) {
case TranslationClass.PLUGIN_LOADER:
return i18n_args
? t(TranslationClass.PLUGIN_LOADER + '.' + trans_text, i18n_args)
: t(TranslationClass.PLUGIN_LOADER + '.' + trans_text);
case TranslationClass.PLUGIN_INSTALL_MODAL:
switch (install_type) {
case InstallType.INSTALL:
return i18n_args
? t(TranslationClass.PLUGIN_INSTALL_MODAL + '.install.' + trans_text, i18n_args)
: t(TranslationClass.PLUGIN_INSTALL_MODAL + '.install.' + trans_text);
case InstallType.REINSTALL:
return i18n_args
? t(TranslationClass.PLUGIN_INSTALL_MODAL + '.reinstall.' + trans_text, i18n_args)
: t(TranslationClass.PLUGIN_INSTALL_MODAL + '.reinstall.' + trans_text);
case InstallType.UPDATE:
return i18n_args
? t(TranslationClass.PLUGIN_INSTALL_MODAL + '.update.' + trans_text, i18n_args)
: t(TranslationClass.PLUGIN_INSTALL_MODAL + '.update.' + trans_text);
}
case TranslationClass.DEVELOPER:
return i18n_args
? t(TranslationClass.DEVELOPER + '.' + trans_text, i18n_args)
: t(TranslationClass.DEVELOPER + '.' + trans_text);
default:
logger.error('We should never fall in the default case!');
return '';
}
}}
</Translation>
);
};
export default TranslationHelper;
+2 -1
View File
@@ -16,7 +16,8 @@
"strict": true,
"suppressImplicitAnyIndexErrors": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true
"skipLibCheck": true,
"resolveJsonModule": true
},
"include": ["src", "index.d.ts"],
"exclude": ["node_modules"]