Compare commits

..

63 Commits
v2.2.1 ... v2.3

Author SHA1 Message Date
kramo
c5b56e3100 v2.3 2023-08-29 14:02:30 +02:00
Weblate (bot)
c9c5f41ee9 Translations update from Hosted Weblate (#181)
* Translated using Weblate (Arabic)

Currently translated at 100.0% (133 of 133 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Arabic)

Currently translated at 100.0% (132 of 132 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Ali Aljishi <ahj696@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/ar/
Translation: Cartridges/Cartridges

* Translated using Weblate (Spanish)

Currently translated at 100.0% (133 of 133 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Spanish)

Currently translated at 100.0% (132 of 132 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/es/
Translation: Cartridges/Cartridges

* Translated using Weblate (Russian)

Currently translated at 100.0% (133 of 133 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Russian)

Currently translated at 99.2% (135 of 136 strings)

Translated using Weblate (Russian)

Currently translated at 98.5% (134 of 136 strings)

Translated using Weblate (Russian)

Currently translated at 98.5% (134 of 136 strings)

Translated using Weblate (Russian)

Currently translated at 97.7% (133 of 136 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Russian)

Currently translated at 100.0% (132 of 132 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Russian)

Currently translated at 100.0% (130 of 130 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (130 of 130 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Сергей <asvmail.as@gmail.com>
Co-authored-by: Сергей Ворон <voron.s.a@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/ru/
Translation: Cartridges/Cartridges

* Translated using Weblate (Tamil)

Currently translated at 100.0% (133 of 133 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: K.B.Dharun Krishna <kbdharunkrishna@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/ta/
Translation: Cartridges/Cartridges

---------

Co-authored-by: Ali Aljishi <ahj696@hotmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Сергей <asvmail.as@gmail.com>
Co-authored-by: Сергей Ворон <voron.s.a@gmail.com>
Co-authored-by: K.B.Dharun Krishna <kbdharunkrishna@gmail.com>
2023-08-29 13:54:32 +02:00
kramo
ee912ba4ca Merge pull request #180 from kra-mo/revert-172-weblate-cartridges-cartridges
Revert "Translations update from Hosted Weblate"
2023-08-29 13:53:06 +02:00
kramo
46196fd0de Revert "Translations update from Hosted Weblate" 2023-08-29 13:52:55 +02:00
kramo
94f7dbfd59 Merge pull request #172 from weblate/weblate-cartridges-cartridges
Translations update from Hosted Weblate
2023-08-29 13:50:21 +02:00
kramo
8516e19d9d Make import time global, fix sorting bug 2023-08-29 12:45:24 +02:00
Hosted Weblate
79a7c5ab3e Update translation files
Updated by "Squash Git commits" hook in Weblate.

Translation: Cartridges/Cartridges
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
2023-08-27 16:19:50 +02:00
Hosted Weblate
f273f9b23f Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Hungarian)

Currently translated at 100.0% (136 of 136 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Hungarian)

Currently translated at 100.0% (132 of 132 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: kramo <contact@kramo.hu>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/hu/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
35b23e8f27 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
200dbb067f Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Swedish)

Currently translated at 100.0% (132 of 132 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Luna Jernberg <droidbittin@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/sv/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
66a71b105e Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
c41bfef102 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
f26f9e35ef Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
6f5836a979 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
1e4c499478 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
befbfb6d51 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (132 of 132 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rafael Fontenelle <rafaelff@gnome.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/pt_BR/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
d11cc3ad0c Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
d0e36323f5 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Italian)

Currently translated at 100.0% (132 of 132 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Italian)

Currently translated at 100.0% (130 of 130 strings)

Co-authored-by: Alessandro Iepure <alessandro.iepure@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: albanobattistella <albano_battistella@hotmail.com>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/it/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
a6022484a8 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (132 of 132 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Dan <jonweblin2205@protonmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/uk/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
25aeea7f52 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (German)

Currently translated at 96.2% (127 of 132 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Simon Hahne <simonhahne@web.de>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/de/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
642f2192f8 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Turkish)

Currently translated at 100.0% (132 of 132 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Sabri Ünal <libreajans@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/tr/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
68def0a60d Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translation: Cartridges/Cartridges
2023-08-27 16:19:50 +02:00
Hosted Weblate
5dd4f2bb57 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translation: Cartridges/Cartridges
2023-08-27 16:19:49 +02:00
Hosted Weblate
0d65a43845 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Russian)

Currently translated at 99.2% (135 of 136 strings)

Translated using Weblate (Russian)

Currently translated at 98.5% (134 of 136 strings)

Translated using Weblate (Russian)

Currently translated at 98.5% (134 of 136 strings)

Translated using Weblate (Russian)

Currently translated at 97.7% (133 of 136 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Russian)

Currently translated at 100.0% (132 of 132 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Russian)

Currently translated at 100.0% (130 of 130 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (130 of 130 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Сергей <asvmail.as@gmail.com>
Co-authored-by: Сергей Ворон <voron.s.a@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/ru/
Translation: Cartridges/Cartridges
2023-08-27 16:19:49 +02:00
Hosted Weblate
a70b528eb0 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translation: Cartridges/Cartridges
2023-08-27 16:19:49 +02:00
Hosted Weblate
4e945945c3 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translation: Cartridges/Cartridges
2023-08-27 16:19:49 +02:00
Hosted Weblate
32e7af6559 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Spanish)

Currently translated at 100.0% (132 of 132 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/es/
Translation: Cartridges/Cartridges
2023-08-27 16:19:49 +02:00
Hosted Weblate
c0f1c93bb6 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Arabic)

Currently translated at 100.0% (132 of 132 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Ali Aljishi <ahj696@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/ar/
Translation: Cartridges/Cartridges
2023-08-27 16:19:49 +02:00
Hosted Weblate
74ec8cbb75 Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Dutch)

Currently translated at 100.0% (136 of 136 strings)

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Philip Goto <philip.goto@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/nl/
Translation: Cartridges/Cartridges
2023-08-27 16:19:49 +02:00
Hosted Weblate
837c46b1ba Update translation files
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translated using Weblate (Chinese (Simplified))

Currently translated at 29.4% (40 of 136 strings)

Added translation using Weblate (Chinese (Simplified))

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: IF_IceFire <zzj520llj@163.com>
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/
Translate-URL: https://hosted.weblate.org/projects/cartridges/cartridges/zh_Hans/
Translation: Cartridges/Cartridges
2023-08-27 16:19:49 +02:00
kramo
5680b08e1c Desktop entry source improvements 2023-08-27 16:19:43 +02:00
Geoffrey Coulaud
c0b6998833 Merge pull request #179 from kra-mo/geoffreys-dev-branch
Improvements to game executable + better handling of corrupted log files
2023-08-27 14:16:59 +02:00
GeoffreyCoulaud
93054b2f57 Handle log rotation errors with corrupted files 2023-08-27 14:10:31 +02:00
kramo
ae86450a01 Update translations 2023-08-27 14:03:39 +02:00
kramo
ed36feecaf Add comment to clarify gio weirdness 2023-08-27 14:01:34 +02:00
GeoffreyCoulaud
6486f5b336 Simplifying game executable 2023-08-27 13:53:23 +02:00
kramo
a1afb98b20 Better implementation for desktop entry source 2023-08-27 13:38:15 +02:00
kramo
c607a65d1f Make library-rows a guint 2023-08-26 17:54:30 +02:00
kramo
5364e6a320 Allow a custom number of library rows - fixes #173 2023-08-26 17:33:30 +02:00
kramo
89862ae266 Fix transparent animated images not working 2023-08-26 15:45:21 +02:00
kramo
82a7d4b20e Make manually added animated covers work 2023-08-26 15:14:57 +02:00
kramo
c2d671273a Composite manually added covers - fixes #177 2023-08-26 14:39:38 +02:00
kramo
38d47dae33 Merge pull request #174 from kra-mo/desktop-file-importer
Desktop file importer
2023-08-25 21:53:26 +02:00
kramo
e287ec1986 Desktop source cleanups 2023-08-25 21:50:23 +02:00
kramo
a79c6b980b Proper a11y for all popovers 2023-08-23 19:59:14 +02:00
kramo
0c55c3ba2a Make buttons in rows flat 2023-08-23 19:41:46 +02:00
kramo
8c5f4f1780 Lists are ordered and I'm silly 2023-08-22 13:32:56 +02:00
kramo
01f1f31f10 Add pixmaps to icon search paths 2023-08-22 12:01:21 +02:00
kramo
a9196c1e55 Auto-detect terminal on first run 2023-08-21 16:49:31 +02:00
kramo
489cb543de Fix copyright header 2023-08-21 16:22:06 +02:00
kramo
ab128ab461 Update translations 2023-08-21 16:18:44 +02:00
kramo
9883cc6b6b Blueprint cleanups 2023-08-21 16:13:31 +02:00
kramo
70b8493e72 Preferences cleanups 2023-08-21 16:08:47 +02:00
kramo
20f1ce6e83 Deskop importer cleanups 2023-08-21 16:04:46 +02:00
kramo
1e2d85b50d Proper game_id for desktop entries 2023-08-21 15:23:29 +02:00
kramo
2d791e46b0 Basic support for Desktop Entry source 2023-08-21 14:09:41 +02:00
kramo
bc3bc2dac6 λ my beloved 2023-08-20 14:32:23 +02:00
kramo
059709d18d Host read-write access to prevent weird file paths 2023-08-19 13:25:57 +02:00
kramo
81d3323a21 Use document-open-symbolic for picking file 2023-08-19 13:07:36 +02:00
kramo
1afd8916e3 Update translation 2023-08-19 12:45:50 +02:00
kramo
5cf41402e7 Add option to choose executable via file picker 2023-08-19 12:45:15 +02:00
kramo
4bd82c9457 Add RetroArch to excluded flatpak emulators 2023-08-18 12:51:12 +02:00
kramo
d44632de8f Cleaner syntax for shared attributes 2023-08-17 21:15:21 +02:00
36 changed files with 1268 additions and 976 deletions

View File

@@ -2,142 +2,159 @@ using Gtk 4.0;
using Adw 1;
template $DetailsWindow : Adw.Window {
default-width: 480; // Same as Nautilus' properties window
default-height: -1;
modal: true;
default-width: 480; // Same as Nautilus' properties window
default-height: -1;
modal: true;
ShortcutController {
Shortcut {
trigger: "Escape";
action: "action(window.close)";
}
ShortcutController {
Shortcut {
trigger: "Escape";
action: "action(window.close)";
}
}
Box {
orientation: vertical;
Adw.HeaderBar HeaderBar {
show-start-title-buttons: false;
show-end-title-buttons: false;
[start]
Button cancel_button {
label: _("Cancel");
action-name: "window.close";
}
[end]
Button apply_button {
styles [
"suggested-action",
]
}
}
Box {
orientation: vertical;
Adw.PreferencesPage {
vexpand: true;
Adw.HeaderBar HeaderBar {
show-start-title-buttons: false;
show-end-title-buttons: false;
Adw.PreferencesGroup cover_group {
Adw.Clamp cover_clamp {
maximum-size: 200;
[start]
Button cancel_button {
label: _("Cancel");
action-name: "window.close";
Overlay {
[overlay]
Spinner spinner {
margin-start: 72;
margin-end: 72;
}
[end]
Button apply_button {
Overlay cover_overlay {
halign: center;
valign: center;
[overlay]
Button cover_button_edit {
icon-name: "document-edit-symbolic";
tooltip-text: _("New Cover");
halign: end;
valign: end;
margin-bottom: 6;
margin-end: 6;
styles [
"suggested-action"
"circular",
"osd",
]
}
[overlay]
Revealer cover_button_delete_revealer {
transition-type: crossfade;
margin-end: 40;
Button cover_button_delete {
icon-name: "user-trash-symbolic";
tooltip-text: _("Delete Cover");
halign: end;
valign: end;
margin-bottom: 6;
margin-end: 6;
styles [
"circular",
"osd",
]
}
}
Picture cover {
width-request: 200;
height-request: 300;
styles [
"card",
]
}
}
}
}
}
Adw.PreferencesGroup {
Adw.EntryRow name {
title: _("Title");
}
Adw.PreferencesPage {
vexpand: true;
Adw.PreferencesGroup cover_group {
Adw.Clamp cover_clamp {
maximum-size: 200;
Overlay {
[overlay]
Spinner spinner {
margin-start: 72;
margin-end: 72;
}
Overlay cover_overlay {
halign: center;
valign: center;
[overlay]
Button cover_button_edit {
icon-name: "document-edit-symbolic";
tooltip-text: _("New Cover");
halign: end;
valign: end;
margin-bottom: 6;
margin-end: 6;
styles [
"circular", "osd"
]
}
[overlay]
Revealer cover_button_delete_revealer {
transition-type: crossfade;
margin-end: 40;
Button cover_button_delete {
icon-name: "user-trash-symbolic";
tooltip-text: _("Delete Cover");
halign: end;
valign: end;
margin-bottom: 6;
margin-end: 6;
styles [
"circular", "osd"
]
}
}
Picture cover {
width-request: 200;
height-request: 300;
styles [
"card"
]
}
}
}
}
}
Adw.PreferencesGroup {
Adw.EntryRow name {
title: _("Title");
}
Adw.EntryRow developer {
title: _("Developer (optional)");
}
}
Adw.PreferencesGroup {
Adw.EntryRow executable {
title: _("Executable");
[suffix]
Gtk.MenuButton exec_info_button {
valign: center;
icon-name: "help-about-symbolic";
tooltip-text: _("More Info");
popover: Popover exec_info_popover {
focusable: true;
Label exec_info_label {
use-markup: true;
wrap: true;
max-width-chars: 50;
halign: center;
valign: center;
margin-top: 6;
margin-bottom: 6;
margin-start: 6;
margin-end: 6;
}
};
styles [
"flat"
]
}
}
}
Adw.EntryRow developer {
title: _("Developer (optional)");
}
}
Adw.PreferencesGroup {
Adw.EntryRow executable {
title: _("Executable");
[suffix]
Button file_chooser_button {
valign: center;
icon-name: "document-open-symbolic";
tooltip-text: _("Select File");
styles [
"flat",
]
}
[suffix]
MenuButton exec_info_button {
valign: center;
icon-name: "help-about-symbolic";
tooltip-text: _("More Info");
popover:
Popover exec_info_popover {
focusable: true;
Label exec_info_label {
use-markup: true;
wrap: true;
max-width-chars: 50;
halign: center;
valign: center;
margin-top: 6;
margin-bottom: 6;
margin-start: 6;
margin-end: 6;
}
}
;
styles [
"flat",
]
}
}
}
}
}
}
}

View File

@@ -76,7 +76,6 @@ template $PreferencesWindow : Adw.PreferencesWindow {
]
}
}
}
}
@@ -111,6 +110,9 @@ template $PreferencesWindow : Adw.PreferencesWindow {
Button steam_data_file_chooser_button {
icon-name: "folder-symbolic";
valign: center;
styles [
"flat"
]
}
}
}
@@ -125,6 +127,9 @@ template $PreferencesWindow : Adw.PreferencesWindow {
Button lutris_data_file_chooser_button {
icon-name: "folder-symbolic";
valign: center;
styles [
"flat"
]
}
}
@@ -134,6 +139,9 @@ template $PreferencesWindow : Adw.PreferencesWindow {
Button lutris_cache_file_chooser_button {
icon-name: "folder-symbolic";
valign: center;
styles [
"flat"
]
}
}
@@ -166,6 +174,9 @@ template $PreferencesWindow : Adw.PreferencesWindow {
Button heroic_config_file_chooser_button {
icon-name: "folder-symbolic";
valign: center;
styles [
"flat"
]
}
}
@@ -216,6 +227,9 @@ template $PreferencesWindow : Adw.PreferencesWindow {
Button bottles_data_file_chooser_button {
icon-name: "folder-symbolic";
valign: center;
styles [
"flat"
]
}
}
}
@@ -230,6 +244,9 @@ template $PreferencesWindow : Adw.PreferencesWindow {
Button itch_config_file_chooser_button {
icon-name: "folder-symbolic";
valign: center;
styles [
"flat"
]
}
}
}
@@ -244,6 +261,9 @@ template $PreferencesWindow : Adw.PreferencesWindow {
Button legendary_config_file_chooser_button {
icon-name: "folder-symbolic";
valign: center;
styles [
"flat"
]
}
}
}
@@ -258,6 +278,9 @@ template $PreferencesWindow : Adw.PreferencesWindow {
Button retroarch_config_file_chooser_button {
icon-name: "folder-symbolic";
valign: center;
styles [
"flat"
]
}
}
}
@@ -272,6 +295,9 @@ template $PreferencesWindow : Adw.PreferencesWindow {
Button flatpak_data_file_chooser_button {
icon-name: "folder-symbolic";
valign: center;
styles [
"flat"
]
}
}
@@ -284,6 +310,15 @@ template $PreferencesWindow : Adw.PreferencesWindow {
}
}
}
Adw.ActionRow {
title: _("Desktop Entries");
activatable-widget: desktop_switch;
Switch desktop_switch {
valign: center;
}
}
}
}

View File

@@ -194,13 +194,19 @@ template $CartridgesWindow : Adw.ApplicationWindow {
action-name: "app.edit_game";
tooltip-text: _("Edit");
styles ["raised", "circular"]
styles [
"raised",
"circular",
]
}
Button details_view_hide_button {
action-name: "app.hide_game";
styles ["raised", "circular"]
styles [
"raised",
"circular",
]
}
Button {
@@ -208,7 +214,10 @@ template $CartridgesWindow : Adw.ApplicationWindow {
action-name: "app.remove_game";
tooltip-text: _("Remove");
styles ["raised", "circular"]
styles [
"raised",
"circular",
]
}
MenuButton {
@@ -216,7 +225,10 @@ template $CartridgesWindow : Adw.ApplicationWindow {
menu-model: search;
tooltip-text: _("Search");
styles ["raised", "circular"]
styles [
"raised",
"circular",
]
}
styles [

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist gettext-domain="cartridges">
<schema id="@APP_ID@" path="@PREFIX@/">
<key name="exit-after-launch" type="b">
<default>false</default>
@@ -76,6 +77,9 @@
<key name="retroarch-location" type="s">
<default>"~/.var/app/org.libretro.RetroArch/config/retroarch/"</default>
</key>
<key name="desktop" type="b">
<default>true</default>
</key>
<key name="flatpak" type="b">
<default>true</default>
</key>
@@ -97,7 +101,11 @@
<key name="sgdb-animated" type="b">
<default>false</default>
</key>
<key name="library-rows" type="u">
<default>0</default>
</key>
</schema>
<schema id="@APP_ID@.State" path="@PREFIX@/State/">
<key name="width" type="i">
<default>1110</default>

View File

@@ -44,10 +44,13 @@
</screenshots>
<content_rating type="oars-1.1" />
<releases>
<release version="2.2.1" date="2023-08-17">
<release version="2.3" date="2023-08-29">
<description translatable="no">
<ul>
<li>Fixes a small issue with import toasts</li>
<li>New import source: desktop entries</li>
<li>Added the ability to pick executables via the file picker</li>
<li>Manually added covers are now padded if they are too short</li>
<li>Translations since 2.2</li>
</ul>
</description>
</release>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

View File

@@ -11,7 +11,7 @@
"--device=dri",
"--socket=wayland",
"--talk-name=org.freedesktop.Flatpak",
"--filesystem=host:ro",
"--filesystem=host",
"--filesystem=~/.var/app/com.valvesoftware.Steam/data/Steam/:ro",
"--filesystem=~/.var/app/net.lutris.Lutris/:ro",
"--filesystem=~/.var/app/com.heroicgameslauncher.hgl/config/heroic/:ro",

View File

@@ -1,5 +1,5 @@
project('cartridges',
version: '2.2.1',
version: '2.3',
meson_version: '>= 0.59.0',
default_options: [ 'warning_level=2', 'werror=false', ],
)

234
po/ar.po
View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: cartridges\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-08-16 11:06+0200\n"
"PO-Revision-Date: 2023-08-15 17:07+0000\n"
"POT-Creation-Date: 2023-08-27 14:03+0200\n"
"PO-Revision-Date: 2023-08-29 10:45+0000\n"
"Last-Translator: Ali Aljishi <ahj696@hotmail.com>\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/cartridges/"
"cartridges/ar/>\n"
@@ -18,11 +18,11 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
"X-Generator: Weblate 5.0-dev\n"
"X-Generator: Weblate 5.0.1-dev\n"
#: data/hu.kramo.Cartridges.desktop.in:3
#: data/hu.kramo.Cartridges.metainfo.xml.in:6 data/gtk/window.blp:47
#: src/main.py:169
#: src/main.py:176
msgid "Cartridges"
msgstr "خراطيش"
@@ -61,13 +61,13 @@ msgid "Edit Game Details"
msgstr "حرِّر تفاصيل اللعبة"
#: data/hu.kramo.Cartridges.metainfo.xml.in:38 data/gtk/window.blp:71
#: src/details_window.py:67
#: src/details_window.py:71
msgid "Game Details"
msgstr "تفاصيل اللعبة"
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:418
#: src/details_window.py:241 src/importer/importer.py:292
#: src/importer/importer.py:342
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:430
#: src/details_window.py:265 src/importer/importer.py:301
#: src/importer/importer.py:352
msgid "Preferences"
msgstr "التفضيلات"
@@ -75,27 +75,31 @@ msgstr "التفضيلات"
msgid "Cancel"
msgstr "ألغِ"
#: data/gtk/details-window.blp:57
#: data/gtk/details-window.blp:58
msgid "New Cover"
msgstr "غلاف جديد"
#: data/gtk/details-window.blp:75
#: data/gtk/details-window.blp:77
msgid "Delete Cover"
msgstr "احذف الغلاف"
#: data/gtk/details-window.blp:102 data/gtk/game.blp:80
#: data/gtk/details-window.blp:105 data/gtk/game.blp:80
msgid "Title"
msgstr "العنوان"
#: data/gtk/details-window.blp:105
#: data/gtk/details-window.blp:109
msgid "Developer (optional)"
msgstr "المطوِّر (اختياري)"
#: data/gtk/details-window.blp:110
#: data/gtk/details-window.blp:115
msgid "Executable"
msgstr "ملفُّ التنفيذ"
#: data/gtk/details-window.blp:116
#: data/gtk/details-window.blp:121
msgid "Select File"
msgstr "اختر ملفًّا"
#: data/gtk/details-window.blp:132
msgid "More Info"
msgstr "معلومات أكثر"
@@ -103,16 +107,16 @@ msgstr "معلومات أكثر"
msgid "Edit"
msgstr "حرِّر"
#: data/gtk/game.blp:107 src/window.py:171
#: data/gtk/game.blp:107 src/window.py:190
msgid "Hide"
msgstr "أخفِ"
#: data/gtk/game.blp:112 data/gtk/game.blp:131 data/gtk/preferences.blp:56
#: data/gtk/window.blp:209
#: data/gtk/window.blp:215
msgid "Remove"
msgstr "أزل"
#: data/gtk/game.blp:126 src/window.py:173
#: data/gtk/game.blp:126 src/window.py:192
msgid "Unhide"
msgstr "اكشف"
@@ -124,8 +128,8 @@ msgstr "عام"
msgid "Quit"
msgstr "أنهِ"
#: data/gtk/help-overlay.blp:19 data/gtk/window.blp:217 data/gtk/window.blp:257
#: data/gtk/window.blp:324
#: data/gtk/help-overlay.blp:19 data/gtk/window.blp:226 data/gtk/window.blp:269
#: data/gtk/window.blp:336
msgid "Search"
msgstr "ابحث"
@@ -137,8 +141,8 @@ msgstr "أظهر التفضيلات"
msgid "Shortcuts"
msgstr "الاختصارات"
#: data/gtk/help-overlay.blp:34 src/game.py:103 src/preferences.py:120
#: src/importer/importer.py:366
#: data/gtk/help-overlay.blp:34 src/game.py:105 src/preferences.py:124
#: src/importer/importer.py:376
msgid "Undo"
msgstr "تراجع"
@@ -166,8 +170,8 @@ msgstr "أظهر الألعاب المخفية"
msgid "Remove game"
msgstr "أزل اللعبة"
#: data/gtk/preferences.blp:13 data/gtk/preferences.blp:89
#: data/gtk/preferences.blp:304
#: data/gtk/preferences.blp:13 data/gtk/preferences.blp:88
#: data/gtk/preferences.blp:339
msgid "Behavior"
msgstr "السلوك"
@@ -183,7 +187,7 @@ msgstr "تبدأ صورة الغلاف اللعبة"
msgid "Swaps the behavior of the cover image and the play button"
msgstr "يبدِّل سلوك صورة الغلاف وزرِّ «العب»"
#: data/gtk/preferences.blp:36 src/details_window.py:81
#: data/gtk/preferences.blp:36 src/details_window.py:85
msgid "Images"
msgstr "الصور"
@@ -203,116 +207,118 @@ msgstr "منطقة خطر"
msgid "Remove All Games"
msgstr "أزل كلَّ الألعاب"
#: data/gtk/preferences.blp:85 data/gtk/window.blp:27 data/gtk/window.blp:444
#: data/gtk/preferences.blp:84 data/gtk/window.blp:27 data/gtk/window.blp:456
msgid "Import"
msgstr "استورد"
#: data/gtk/preferences.blp:92
#, fuzzy
#| msgid "Remove All Games"
#: data/gtk/preferences.blp:91
msgid "Remove Uninstalled Games"
msgstr "أزل كلَّ الألعاب"
msgstr "أزل الألعاب المحذوفة"
#: data/gtk/preferences.blp:102
#: data/gtk/preferences.blp:101
msgid "Sources"
msgstr "المصادر"
#: data/gtk/preferences.blp:105
#: data/gtk/preferences.blp:104
msgid "Steam"
msgstr "ستيم"
#: data/gtk/preferences.blp:109 data/gtk/preferences.blp:123
#: data/gtk/preferences.blp:164 data/gtk/preferences.blp:214
#: data/gtk/preferences.blp:228 data/gtk/preferences.blp:242
#: data/gtk/preferences.blp:256 data/gtk/preferences.blp:270
#: data/gtk/preferences.blp:108 data/gtk/preferences.blp:125
#: data/gtk/preferences.blp:172 data/gtk/preferences.blp:225
#: data/gtk/preferences.blp:242 data/gtk/preferences.blp:259
#: data/gtk/preferences.blp:276 data/gtk/preferences.blp:293
msgid "Install Location"
msgstr "موضع التثبيت"
#: data/gtk/preferences.blp:119
#: data/gtk/preferences.blp:121
msgid "Lutris"
msgstr "لوترس"
#: data/gtk/preferences.blp:132
#: data/gtk/preferences.blp:137
msgid "Cache Location"
msgstr "موضع الذاكرة المؤقتة"
#: data/gtk/preferences.blp:141
#: data/gtk/preferences.blp:149
msgid "Import Steam Games"
msgstr "استورد ألعابًا من ستيم"
#: data/gtk/preferences.blp:150
#: data/gtk/preferences.blp:158
msgid "Import Flatpak Games"
msgstr "استورد ألعاب فلاتباك"
#: data/gtk/preferences.blp:160
#: data/gtk/preferences.blp:168
msgid "Heroic"
msgstr "هِرُوِك"
#: data/gtk/preferences.blp:173
#: data/gtk/preferences.blp:184
msgid "Import Epic Games"
msgstr "استورد ألعاب أَبِك"
#: data/gtk/preferences.blp:182
#: data/gtk/preferences.blp:193
msgid "Import GOG Games"
msgstr "استورد ألعاب جي‌أو‌جي"
#: data/gtk/preferences.blp:191
#: data/gtk/preferences.blp:202
msgid "Import Amazon Games"
msgstr "استورد ألعابًا من أمازون"
#: data/gtk/preferences.blp:200
#: data/gtk/preferences.blp:211
msgid "Import Sideloaded Games"
msgstr "استورد ألعابًا مثبَّتةً بغير متجر"
#: data/gtk/preferences.blp:210
#: data/gtk/preferences.blp:221
msgid "Bottles"
msgstr "قوارير"
#: data/gtk/preferences.blp:224
#: data/gtk/preferences.blp:238
msgid "itch"
msgstr "إتش"
#: data/gtk/preferences.blp:238
#: data/gtk/preferences.blp:255
msgid "Legendary"
msgstr "لجندري"
#: data/gtk/preferences.blp:252
#: data/gtk/preferences.blp:272
msgid "RetroArch"
msgstr "رتروآرتش"
#: data/gtk/preferences.blp:266
#: data/gtk/preferences.blp:289
msgid "Flatpak"
msgstr "فلاتباك"
#: data/gtk/preferences.blp:279
#: data/gtk/preferences.blp:305
msgid "Import Game Launchers"
msgstr "استورد مشغِّلات ألعاب"
#: data/gtk/preferences.blp:292
#: data/gtk/preferences.blp:315
msgid "Desktop Entries"
msgstr "مدخلات سطح المكتب"
#: data/gtk/preferences.blp:327
msgid "SteamGridDB"
msgstr "SteamGridDB"
#: data/gtk/preferences.blp:296
#: data/gtk/preferences.blp:331
msgid "Authentication"
msgstr "الاستيثاق"
#: data/gtk/preferences.blp:299
#: data/gtk/preferences.blp:334
msgid "API Key"
msgstr "مفتاح واجهة البرمجة"
#: data/gtk/preferences.blp:307
#: data/gtk/preferences.blp:342
msgid "Use SteamGridDB"
msgstr "استخدم SteamGridDB"
#: data/gtk/preferences.blp:308
#: data/gtk/preferences.blp:343
msgid "Download images when adding or importing games"
msgstr "نزِّل الصور حينما تنزِّل أو تستورد الألعاب"
#: data/gtk/preferences.blp:317
#: data/gtk/preferences.blp:352
msgid "Prefer Over Official Images"
msgstr "فضِّلها على الصور الرسمية"
#: data/gtk/preferences.blp:326
#: data/gtk/preferences.blp:361
msgid "Prefer Animated Images"
msgstr "فضِّل الصور المتحرِّكة"
@@ -340,7 +346,7 @@ msgstr "لا توجد ألعاب مخفية"
msgid "Games you hide will appear here."
msgstr "هنا يظهر ما أخفيت من ألعاب."
#: data/gtk/window.blp:64 data/gtk/window.blp:305
#: data/gtk/window.blp:64 data/gtk/window.blp:317
msgid "Back"
msgstr "عد"
@@ -352,114 +358,118 @@ msgstr "عنوان اللعبة"
msgid "Play"
msgstr "العب"
#: data/gtk/window.blp:243 data/gtk/window.blp:437
#: data/gtk/window.blp:255 data/gtk/window.blp:449
msgid "Add Game"
msgstr "أضف لعبةً"
#: data/gtk/window.blp:250 data/gtk/window.blp:317
#: data/gtk/window.blp:262 data/gtk/window.blp:329
msgid "Main Menu"
msgstr "القائمة الرئيسة"
#: data/gtk/window.blp:272
#: data/gtk/window.blp:284
msgid "Search games"
msgstr "ابحث عن ألعاب"
#: data/gtk/window.blp:312
#: data/gtk/window.blp:324
msgid "Hidden Games"
msgstr "الألعاب المخفية"
#: data/gtk/window.blp:339
#: data/gtk/window.blp:351
msgid "Search hidden games"
msgstr "ابحث في الألعاب المخفية"
#: data/gtk/window.blp:376
#: data/gtk/window.blp:388
msgid "Sort"
msgstr "رتِّب"
#: data/gtk/window.blp:379
#: data/gtk/window.blp:391
msgid "A-Z"
msgstr "أ-ي"
#: data/gtk/window.blp:385
#: data/gtk/window.blp:397
msgid "Z-A"
msgstr "ي-أ"
#: data/gtk/window.blp:391
#: data/gtk/window.blp:403
msgid "Newest"
msgstr "الأجدد"
#: data/gtk/window.blp:397
#: data/gtk/window.blp:409
msgid "Oldest"
msgstr "الأقدم"
#: data/gtk/window.blp:403
#: data/gtk/window.blp:415
msgid "Last Played"
msgstr "لُعبت آخر مرَّة"
#: data/gtk/window.blp:410
#: data/gtk/window.blp:422
msgid "Show Hidden"
msgstr "أظهر ما أخفي"
#: data/gtk/window.blp:423
#: data/gtk/window.blp:435
msgid "Keyboard Shortcuts"
msgstr "اختصارات لوحة المفاتيح"
#: data/gtk/window.blp:428
#: data/gtk/window.blp:440
msgid "About Cartridges"
msgstr "عن «خراطيش»"
#. Translators: Replace this with your name for it to show up in the about window
#: src/main.py:188
#: src/main.py:195
msgid "translator_credits"
msgstr "Ali Aljishi <ahj696@hotmail.com>"
#. The variable is the date when the game was added
#: src/window.py:194
#: src/window.py:213
msgid "Added: {}"
msgstr "أضيفت في: {}"
#: src/window.py:197
#: src/window.py:216
msgid "Never"
msgstr "أبدًا"
#. The variable is the date when the game was last played
#: src/window.py:201
#: src/window.py:220
msgid "Last played: {}"
msgstr "لُعبت آخر مرَّة في: {}"
#: src/details_window.py:72
#: src/details_window.py:76
msgid "Apply"
msgstr "طبِّق"
#: src/details_window.py:78
#: src/details_window.py:82
msgid "Add New Game"
msgstr "أضف لعبةً جديدةً"
#: src/details_window.py:79
#: src/details_window.py:83
msgid "Add"
msgstr "أضف"
#: src/details_window.py:93
msgid "Executables"
msgstr "ملفات التنفيذ"
#. Translate this string as you would translate "file"
#: src/details_window.py:92
#: src/details_window.py:108
msgid "file.txt"
msgstr "ملف.txt"
#. As in software
#: src/details_window.py:94
#: src/details_window.py:110
msgid "program"
msgstr "البرنامج"
#. Translate this string as you would translate "path to {}"
#: src/details_window.py:99 src/details_window.py:101
#: src/details_window.py:115 src/details_window.py:117
msgid "C:\\path\\to\\{}"
msgstr "C:\\المسار\\إلى\\{}"
#. Translate this string as you would translate "path to {}"
#: src/details_window.py:105 src/details_window.py:107
#: src/details_window.py:121 src/details_window.py:123
msgid "/path/to/{}"
msgstr "/المسار/إلى/{}"
#: src/details_window.py:112
#: src/details_window.py:128
msgid ""
"To launch the executable \"{}\", use the command:\n"
"\n"
@@ -481,103 +491,101 @@ msgstr ""
"\n"
"ولا تنسَ إحاطة المسار بعلامتي تنصيص مزدوجتين حالما تضمَّن مسافات!"
#: src/details_window.py:147 src/details_window.py:153
#: src/details_window.py:171 src/details_window.py:177
msgid "Couldn't Add Game"
msgstr "تعذَّرت إضافة اللعبة"
#: src/details_window.py:147 src/details_window.py:183
#: src/details_window.py:171 src/details_window.py:207
msgid "Game title cannot be empty."
msgstr "لا يجوز كون عنوان اللعبة فارغًا."
#: src/details_window.py:153 src/details_window.py:191
#: src/details_window.py:177 src/details_window.py:215
msgid "Executable cannot be empty."
msgstr "لا يجوز كون ملفِّ التنفيذ فارغًا."
#: src/details_window.py:182 src/details_window.py:190
#: src/details_window.py:206 src/details_window.py:214
msgid "Couldn't Apply Preferences"
msgstr "تعذَّر تطبيق التفضيلات"
#. The variable is the title of the game
#: src/game.py:139
#: src/game.py:141
msgid "{} launched"
msgstr "بُدئت {}"
#. The variable is the title of the game
#: src/game.py:153
#: src/game.py:155
msgid "{} hidden"
msgstr "أٌخفيت {}"
#: src/game.py:153
#: src/game.py:155
msgid "{} unhidden"
msgstr "أٌظهرت {}"
#. The variable is the title of the game
#. The variable is the number of games removed
#: src/game.py:170 src/importer/importer.py:363
#: src/game.py:172 src/importer/importer.py:373
msgid "{} removed"
msgstr "أزيلت {}"
#: src/preferences.py:119
#: src/preferences.py:123
msgid "All games removed"
msgstr "أُزيلت كلُّ الألعاب"
#: src/preferences.py:168
#: src/preferences.py:172
msgid ""
"An API key is required to use SteamGridDB. You can generate one {}here{}."
msgstr ""
"تحتاج مفتاح واجهة برمجة حال ما أردت استخدام SteamGridDB، {}هنا تولِّده{}."
#: src/preferences.py:294
#: src/preferences.py:293
msgid "Installation Not Found"
msgstr "لم يُعثر على التثبيت"
#: src/preferences.py:296
#: src/preferences.py:294
msgid "Select a valid directory."
msgstr "حدِّد مجلَّدًا صالحًا."
#: src/preferences.py:351
#: src/preferences.py:330 src/importer/importer.py:299
msgid "Warning"
msgstr "تحذير"
#: src/preferences.py:364
msgid "Invalid Directory"
msgstr "مجلَّد غير صالح"
#: src/preferences.py:357
#: src/preferences.py:370
msgid "Set Location"
msgstr "عيِّن الموضع"
#: src/utils/create_dialog.py:25 src/importer/importer.py:291
#: src/utils/create_dialog.py:33 src/importer/importer.py:300
msgid "Dismiss"
msgstr "تجاهل"
#: src/importer/importer.py:128
#: src/importer/importer.py:137
msgid "Importing Games…"
msgstr "تُستورد الألعاب…"
#: src/importer/importer.py:290
msgid "Warning"
msgstr ""
#: src/importer/importer.py:311
#: src/importer/importer.py:320
msgid "The following errors occured during import:"
msgstr ""
msgstr "طرأ هذا الخطأ أثناء الاستيراد:"
#: src/importer/importer.py:339
#: src/importer/importer.py:349
msgid "No new games found"
msgstr "لم يُعثر على ألعاب جديدة"
#: src/importer/importer.py:351
#: src/importer/importer.py:361
msgid "1 game imported"
msgstr "اُستوردت لعبة واحدة"
#. The variable is the number of games
#: src/importer/importer.py:355
#: src/importer/importer.py:365
msgid "{} games imported"
msgstr "اُستوردت {} لعبة"
#. A single game removed
#: src/importer/importer.py:359
#, fuzzy
#| msgid "{} removed"
#: src/importer/importer.py:369
msgid "1 removed"
msgstr "أزيلت {}"
msgstr "أزيل ١"
#. The variable is the name of the source
#: src/importer/sources/location.py:33

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Cartridges\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-08-16 11:06+0200\n"
"POT-Creation-Date: 2023-08-27 14:03+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -19,7 +19,7 @@ msgstr ""
#: data/hu.kramo.Cartridges.desktop.in:3
#: data/hu.kramo.Cartridges.metainfo.xml.in:6 data/gtk/window.blp:47
#: src/main.py:169
#: src/main.py:176
msgid "Cartridges"
msgstr ""
@@ -54,13 +54,13 @@ msgid "Edit Game Details"
msgstr ""
#: data/hu.kramo.Cartridges.metainfo.xml.in:38 data/gtk/window.blp:71
#: src/details_window.py:67
#: src/details_window.py:71
msgid "Game Details"
msgstr ""
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:418
#: src/details_window.py:241 src/importer/importer.py:292
#: src/importer/importer.py:342
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:430
#: src/details_window.py:265 src/importer/importer.py:301
#: src/importer/importer.py:352
msgid "Preferences"
msgstr ""
@@ -68,27 +68,31 @@ msgstr ""
msgid "Cancel"
msgstr ""
#: data/gtk/details-window.blp:57
#: data/gtk/details-window.blp:58
msgid "New Cover"
msgstr ""
#: data/gtk/details-window.blp:75
#: data/gtk/details-window.blp:77
msgid "Delete Cover"
msgstr ""
#: data/gtk/details-window.blp:102 data/gtk/game.blp:80
#: data/gtk/details-window.blp:105 data/gtk/game.blp:80
msgid "Title"
msgstr ""
#: data/gtk/details-window.blp:105
#: data/gtk/details-window.blp:109
msgid "Developer (optional)"
msgstr ""
#: data/gtk/details-window.blp:110
#: data/gtk/details-window.blp:115
msgid "Executable"
msgstr ""
#: data/gtk/details-window.blp:116
#: data/gtk/details-window.blp:121
msgid "Select File"
msgstr ""
#: data/gtk/details-window.blp:132
msgid "More Info"
msgstr ""
@@ -96,16 +100,16 @@ msgstr ""
msgid "Edit"
msgstr ""
#: data/gtk/game.blp:107 src/window.py:171
#: data/gtk/game.blp:107 src/window.py:190
msgid "Hide"
msgstr ""
#: data/gtk/game.blp:112 data/gtk/game.blp:131 data/gtk/preferences.blp:56
#: data/gtk/window.blp:209
#: data/gtk/window.blp:215
msgid "Remove"
msgstr ""
#: data/gtk/game.blp:126 src/window.py:173
#: data/gtk/game.blp:126 src/window.py:192
msgid "Unhide"
msgstr ""
@@ -117,8 +121,8 @@ msgstr ""
msgid "Quit"
msgstr ""
#: data/gtk/help-overlay.blp:19 data/gtk/window.blp:217 data/gtk/window.blp:257
#: data/gtk/window.blp:324
#: data/gtk/help-overlay.blp:19 data/gtk/window.blp:226 data/gtk/window.blp:269
#: data/gtk/window.blp:336
msgid "Search"
msgstr ""
@@ -130,8 +134,8 @@ msgstr ""
msgid "Shortcuts"
msgstr ""
#: data/gtk/help-overlay.blp:34 src/game.py:103 src/preferences.py:120
#: src/importer/importer.py:366
#: data/gtk/help-overlay.blp:34 src/game.py:105 src/preferences.py:124
#: src/importer/importer.py:376
msgid "Undo"
msgstr ""
@@ -159,8 +163,8 @@ msgstr ""
msgid "Remove game"
msgstr ""
#: data/gtk/preferences.blp:13 data/gtk/preferences.blp:89
#: data/gtk/preferences.blp:304
#: data/gtk/preferences.blp:13 data/gtk/preferences.blp:88
#: data/gtk/preferences.blp:339
msgid "Behavior"
msgstr ""
@@ -176,7 +180,7 @@ msgstr ""
msgid "Swaps the behavior of the cover image and the play button"
msgstr ""
#: data/gtk/preferences.blp:36 src/details_window.py:81
#: data/gtk/preferences.blp:36 src/details_window.py:85
msgid "Images"
msgstr ""
@@ -196,114 +200,118 @@ msgstr ""
msgid "Remove All Games"
msgstr ""
#: data/gtk/preferences.blp:85 data/gtk/window.blp:27 data/gtk/window.blp:444
#: data/gtk/preferences.blp:84 data/gtk/window.blp:27 data/gtk/window.blp:456
msgid "Import"
msgstr ""
#: data/gtk/preferences.blp:92
#: data/gtk/preferences.blp:91
msgid "Remove Uninstalled Games"
msgstr ""
#: data/gtk/preferences.blp:102
#: data/gtk/preferences.blp:101
msgid "Sources"
msgstr ""
#: data/gtk/preferences.blp:105
#: data/gtk/preferences.blp:104
msgid "Steam"
msgstr ""
#: data/gtk/preferences.blp:109 data/gtk/preferences.blp:123
#: data/gtk/preferences.blp:164 data/gtk/preferences.blp:214
#: data/gtk/preferences.blp:228 data/gtk/preferences.blp:242
#: data/gtk/preferences.blp:256 data/gtk/preferences.blp:270
#: data/gtk/preferences.blp:108 data/gtk/preferences.blp:125
#: data/gtk/preferences.blp:172 data/gtk/preferences.blp:225
#: data/gtk/preferences.blp:242 data/gtk/preferences.blp:259
#: data/gtk/preferences.blp:276 data/gtk/preferences.blp:293
msgid "Install Location"
msgstr ""
#: data/gtk/preferences.blp:119
#: data/gtk/preferences.blp:121
msgid "Lutris"
msgstr ""
#: data/gtk/preferences.blp:132
#: data/gtk/preferences.blp:137
msgid "Cache Location"
msgstr ""
#: data/gtk/preferences.blp:141
#: data/gtk/preferences.blp:149
msgid "Import Steam Games"
msgstr ""
#: data/gtk/preferences.blp:150
#: data/gtk/preferences.blp:158
msgid "Import Flatpak Games"
msgstr ""
#: data/gtk/preferences.blp:160
#: data/gtk/preferences.blp:168
msgid "Heroic"
msgstr ""
#: data/gtk/preferences.blp:173
#: data/gtk/preferences.blp:184
msgid "Import Epic Games"
msgstr ""
#: data/gtk/preferences.blp:182
#: data/gtk/preferences.blp:193
msgid "Import GOG Games"
msgstr ""
#: data/gtk/preferences.blp:191
#: data/gtk/preferences.blp:202
msgid "Import Amazon Games"
msgstr ""
#: data/gtk/preferences.blp:200
#: data/gtk/preferences.blp:211
msgid "Import Sideloaded Games"
msgstr ""
#: data/gtk/preferences.blp:210
#: data/gtk/preferences.blp:221
msgid "Bottles"
msgstr ""
#: data/gtk/preferences.blp:224
#: data/gtk/preferences.blp:238
msgid "itch"
msgstr ""
#: data/gtk/preferences.blp:238
#: data/gtk/preferences.blp:255
msgid "Legendary"
msgstr ""
#: data/gtk/preferences.blp:252
#: data/gtk/preferences.blp:272
msgid "RetroArch"
msgstr ""
#: data/gtk/preferences.blp:266
#: data/gtk/preferences.blp:289
msgid "Flatpak"
msgstr ""
#: data/gtk/preferences.blp:279
#: data/gtk/preferences.blp:305
msgid "Import Game Launchers"
msgstr ""
#: data/gtk/preferences.blp:292
#: data/gtk/preferences.blp:315
msgid "Desktop Entries"
msgstr ""
#: data/gtk/preferences.blp:327
msgid "SteamGridDB"
msgstr ""
#: data/gtk/preferences.blp:296
#: data/gtk/preferences.blp:331
msgid "Authentication"
msgstr ""
#: data/gtk/preferences.blp:299
#: data/gtk/preferences.blp:334
msgid "API Key"
msgstr ""
#: data/gtk/preferences.blp:307
#: data/gtk/preferences.blp:342
msgid "Use SteamGridDB"
msgstr ""
#: data/gtk/preferences.blp:308
#: data/gtk/preferences.blp:343
msgid "Download images when adding or importing games"
msgstr ""
#: data/gtk/preferences.blp:317
#: data/gtk/preferences.blp:352
msgid "Prefer Over Official Images"
msgstr ""
#: data/gtk/preferences.blp:326
#: data/gtk/preferences.blp:361
msgid "Prefer Animated Images"
msgstr ""
@@ -331,7 +339,7 @@ msgstr ""
msgid "Games you hide will appear here."
msgstr ""
#: data/gtk/window.blp:64 data/gtk/window.blp:305
#: data/gtk/window.blp:64 data/gtk/window.blp:317
msgid "Back"
msgstr ""
@@ -343,114 +351,118 @@ msgstr ""
msgid "Play"
msgstr ""
#: data/gtk/window.blp:243 data/gtk/window.blp:437
#: data/gtk/window.blp:255 data/gtk/window.blp:449
msgid "Add Game"
msgstr ""
#: data/gtk/window.blp:250 data/gtk/window.blp:317
#: data/gtk/window.blp:262 data/gtk/window.blp:329
msgid "Main Menu"
msgstr ""
#: data/gtk/window.blp:272
#: data/gtk/window.blp:284
msgid "Search games"
msgstr ""
#: data/gtk/window.blp:312
#: data/gtk/window.blp:324
msgid "Hidden Games"
msgstr ""
#: data/gtk/window.blp:339
#: data/gtk/window.blp:351
msgid "Search hidden games"
msgstr ""
#: data/gtk/window.blp:376
#: data/gtk/window.blp:388
msgid "Sort"
msgstr ""
#: data/gtk/window.blp:379
#: data/gtk/window.blp:391
msgid "A-Z"
msgstr ""
#: data/gtk/window.blp:385
#: data/gtk/window.blp:397
msgid "Z-A"
msgstr ""
#: data/gtk/window.blp:391
#: data/gtk/window.blp:403
msgid "Newest"
msgstr ""
#: data/gtk/window.blp:397
#: data/gtk/window.blp:409
msgid "Oldest"
msgstr ""
#: data/gtk/window.blp:403
#: data/gtk/window.blp:415
msgid "Last Played"
msgstr ""
#: data/gtk/window.blp:410
#: data/gtk/window.blp:422
msgid "Show Hidden"
msgstr ""
#: data/gtk/window.blp:423
#: data/gtk/window.blp:435
msgid "Keyboard Shortcuts"
msgstr ""
#: data/gtk/window.blp:428
#: data/gtk/window.blp:440
msgid "About Cartridges"
msgstr ""
#. Translators: Replace this with your name for it to show up in the about window
#: src/main.py:188
#: src/main.py:195
msgid "translator_credits"
msgstr ""
#. The variable is the date when the game was added
#: src/window.py:194
#: src/window.py:213
msgid "Added: {}"
msgstr ""
#: src/window.py:197
#: src/window.py:216
msgid "Never"
msgstr ""
#. The variable is the date when the game was last played
#: src/window.py:201
#: src/window.py:220
msgid "Last played: {}"
msgstr ""
#: src/details_window.py:72
#: src/details_window.py:76
msgid "Apply"
msgstr ""
#: src/details_window.py:78
#: src/details_window.py:82
msgid "Add New Game"
msgstr ""
#: src/details_window.py:79
#: src/details_window.py:83
msgid "Add"
msgstr ""
#: src/details_window.py:93
msgid "Executables"
msgstr ""
#. Translate this string as you would translate "file"
#: src/details_window.py:92
#: src/details_window.py:108
msgid "file.txt"
msgstr ""
#. As in software
#: src/details_window.py:94
#: src/details_window.py:110
msgid "program"
msgstr ""
#. Translate this string as you would translate "path to {}"
#: src/details_window.py:99 src/details_window.py:101
#: src/details_window.py:115 src/details_window.py:117
msgid "C:\\path\\to\\{}"
msgstr ""
#. Translate this string as you would translate "path to {}"
#: src/details_window.py:105 src/details_window.py:107
#: src/details_window.py:121 src/details_window.py:123
msgid "/path/to/{}"
msgstr ""
#: src/details_window.py:112
#: src/details_window.py:128
msgid ""
"To launch the executable \"{}\", use the command:\n"
"\n"
@@ -463,98 +475,98 @@ msgid ""
"If the path contains spaces, make sure to wrap it in double quotes!"
msgstr ""
#: src/details_window.py:147 src/details_window.py:153
#: src/details_window.py:171 src/details_window.py:177
msgid "Couldn't Add Game"
msgstr ""
#: src/details_window.py:147 src/details_window.py:183
#: src/details_window.py:171 src/details_window.py:207
msgid "Game title cannot be empty."
msgstr ""
#: src/details_window.py:153 src/details_window.py:191
#: src/details_window.py:177 src/details_window.py:215
msgid "Executable cannot be empty."
msgstr ""
#: src/details_window.py:182 src/details_window.py:190
#: src/details_window.py:206 src/details_window.py:214
msgid "Couldn't Apply Preferences"
msgstr ""
#. The variable is the title of the game
#: src/game.py:139
#: src/game.py:141
msgid "{} launched"
msgstr ""
#. The variable is the title of the game
#: src/game.py:153
#: src/game.py:155
msgid "{} hidden"
msgstr ""
#: src/game.py:153
#: src/game.py:155
msgid "{} unhidden"
msgstr ""
#. The variable is the title of the game
#. The variable is the number of games removed
#: src/game.py:170 src/importer/importer.py:363
#: src/game.py:172 src/importer/importer.py:373
msgid "{} removed"
msgstr ""
#: src/preferences.py:119
#: src/preferences.py:123
msgid "All games removed"
msgstr ""
#: src/preferences.py:168
#: src/preferences.py:172
msgid ""
"An API key is required to use SteamGridDB. You can generate one {}here{}."
msgstr ""
#: src/preferences.py:294
#: src/preferences.py:293
msgid "Installation Not Found"
msgstr ""
#: src/preferences.py:296
#: src/preferences.py:294
msgid "Select a valid directory."
msgstr ""
#: src/preferences.py:351
msgid "Invalid Directory"
msgstr ""
#: src/preferences.py:357
msgid "Set Location"
msgstr ""
#: src/utils/create_dialog.py:25 src/importer/importer.py:291
msgid "Dismiss"
msgstr ""
#: src/importer/importer.py:128
msgid "Importing Games…"
msgstr ""
#: src/importer/importer.py:290
#: src/preferences.py:330 src/importer/importer.py:299
msgid "Warning"
msgstr ""
#: src/importer/importer.py:311
#: src/preferences.py:364
msgid "Invalid Directory"
msgstr ""
#: src/preferences.py:370
msgid "Set Location"
msgstr ""
#: src/utils/create_dialog.py:33 src/importer/importer.py:300
msgid "Dismiss"
msgstr ""
#: src/importer/importer.py:137
msgid "Importing Games…"
msgstr ""
#: src/importer/importer.py:320
msgid "The following errors occured during import:"
msgstr ""
#: src/importer/importer.py:339
#: src/importer/importer.py:349
msgid "No new games found"
msgstr ""
#: src/importer/importer.py:351
#: src/importer/importer.py:361
msgid "1 game imported"
msgstr ""
#. The variable is the number of games
#: src/importer/importer.py:355
#: src/importer/importer.py:365
msgid "{} games imported"
msgstr ""
#. A single game removed
#: src/importer/importer.py:359
#: src/importer/importer.py:369
msgid "1 removed"
msgstr ""

246
po/es.po
View File

@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: cartridges\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-08-16 11:06+0200\n"
"PO-Revision-Date: 2023-08-16 15:22+0000\n"
"POT-Creation-Date: 2023-08-27 14:03+0200\n"
"PO-Revision-Date: 2023-08-29 10:45+0000\n"
"Last-Translator: gallegonovato <fran-carro@hotmail.es>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/cartridges/"
"cartridges/es/>\n"
@@ -18,11 +18,11 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.0-dev\n"
"X-Generator: Weblate 5.0.1-dev\n"
#: data/hu.kramo.Cartridges.desktop.in:3
#: data/hu.kramo.Cartridges.metainfo.xml.in:6 data/gtk/window.blp:47
#: src/main.py:169
#: src/main.py:176
msgid "Cartridges"
msgstr "Cartuchos"
@@ -63,13 +63,13 @@ msgid "Edit Game Details"
msgstr "Editar detalles del juego"
#: data/hu.kramo.Cartridges.metainfo.xml.in:38 data/gtk/window.blp:71
#: src/details_window.py:67
#: src/details_window.py:71
msgid "Game Details"
msgstr "Detalles del juego"
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:418
#: src/details_window.py:241 src/importer/importer.py:292
#: src/importer/importer.py:342
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:430
#: src/details_window.py:265 src/importer/importer.py:301
#: src/importer/importer.py:352
msgid "Preferences"
msgstr "Preferencias"
@@ -77,27 +77,31 @@ msgstr "Preferencias"
msgid "Cancel"
msgstr "Cancelar"
#: data/gtk/details-window.blp:57
#: data/gtk/details-window.blp:58
msgid "New Cover"
msgstr "Portada nueva"
#: data/gtk/details-window.blp:75
#: data/gtk/details-window.blp:77
msgid "Delete Cover"
msgstr "Borrar portada"
#: data/gtk/details-window.blp:102 data/gtk/game.blp:80
#: data/gtk/details-window.blp:105 data/gtk/game.blp:80
msgid "Title"
msgstr "Título"
#: data/gtk/details-window.blp:105
#: data/gtk/details-window.blp:109
msgid "Developer (optional)"
msgstr "Desarrollador (opcional)"
#: data/gtk/details-window.blp:110
#: data/gtk/details-window.blp:115
msgid "Executable"
msgstr "Ejecutable"
#: data/gtk/details-window.blp:116
#: data/gtk/details-window.blp:121
msgid "Select File"
msgstr "Seleccionar el archivo"
#: data/gtk/details-window.blp:132
msgid "More Info"
msgstr "Más información"
@@ -105,16 +109,16 @@ msgstr "Más información"
msgid "Edit"
msgstr "Editar"
#: data/gtk/game.blp:107 src/window.py:171
#: data/gtk/game.blp:107 src/window.py:190
msgid "Hide"
msgstr "Ocultar"
#: data/gtk/game.blp:112 data/gtk/game.blp:131 data/gtk/preferences.blp:56
#: data/gtk/window.blp:209
#: data/gtk/window.blp:215
msgid "Remove"
msgstr "Eliminar"
#: data/gtk/game.blp:126 src/window.py:173
#: data/gtk/game.blp:126 src/window.py:192
msgid "Unhide"
msgstr "Desocultar"
@@ -126,8 +130,8 @@ msgstr "General"
msgid "Quit"
msgstr "Salir"
#: data/gtk/help-overlay.blp:19 data/gtk/window.blp:217 data/gtk/window.blp:257
#: data/gtk/window.blp:324
#: data/gtk/help-overlay.blp:19 data/gtk/window.blp:226 data/gtk/window.blp:269
#: data/gtk/window.blp:336
msgid "Search"
msgstr "Buscar"
@@ -139,8 +143,8 @@ msgstr "Mostrar preferencias"
msgid "Shortcuts"
msgstr "Atajos"
#: data/gtk/help-overlay.blp:34 src/game.py:103 src/preferences.py:120
#: src/importer/importer.py:366
#: data/gtk/help-overlay.blp:34 src/game.py:105 src/preferences.py:124
#: src/importer/importer.py:376
msgid "Undo"
msgstr "Deshacer"
@@ -154,7 +158,7 @@ msgstr "Juegos"
#: data/gtk/help-overlay.blp:48
msgid "Add new game"
msgstr "Añadir juego nuevo"
msgstr "Añadir un nuevo juego"
#: data/gtk/help-overlay.blp:53
msgid "Import games"
@@ -168,8 +172,8 @@ msgstr "Mostrar juegos ocultos"
msgid "Remove game"
msgstr "Eliminar juego"
#: data/gtk/preferences.blp:13 data/gtk/preferences.blp:89
#: data/gtk/preferences.blp:304
#: data/gtk/preferences.blp:13 data/gtk/preferences.blp:88
#: data/gtk/preferences.blp:339
msgid "Behavior"
msgstr "Comportamiento"
@@ -186,7 +190,7 @@ msgid "Swaps the behavior of the cover image and the play button"
msgstr ""
"Cambia el comportamiento de la imagen de portada y del botón de reproducción"
#: data/gtk/preferences.blp:36 src/details_window.py:81
#: data/gtk/preferences.blp:36 src/details_window.py:85
msgid "Images"
msgstr "Imágenes"
@@ -206,114 +210,118 @@ msgstr "Zona de peligro"
msgid "Remove All Games"
msgstr "Eliminar todos los juegos"
#: data/gtk/preferences.blp:85 data/gtk/window.blp:27 data/gtk/window.blp:444
#: data/gtk/preferences.blp:84 data/gtk/window.blp:27 data/gtk/window.blp:456
msgid "Import"
msgstr "Importar"
#: data/gtk/preferences.blp:92
#: data/gtk/preferences.blp:91
msgid "Remove Uninstalled Games"
msgstr "Eliminar los juegos desinstalados"
#: data/gtk/preferences.blp:102
#: data/gtk/preferences.blp:101
msgid "Sources"
msgstr "Fuentes"
#: data/gtk/preferences.blp:105
#: data/gtk/preferences.blp:104
msgid "Steam"
msgstr "Steam"
#: data/gtk/preferences.blp:109 data/gtk/preferences.blp:123
#: data/gtk/preferences.blp:164 data/gtk/preferences.blp:214
#: data/gtk/preferences.blp:228 data/gtk/preferences.blp:242
#: data/gtk/preferences.blp:256 data/gtk/preferences.blp:270
#: data/gtk/preferences.blp:108 data/gtk/preferences.blp:125
#: data/gtk/preferences.blp:172 data/gtk/preferences.blp:225
#: data/gtk/preferences.blp:242 data/gtk/preferences.blp:259
#: data/gtk/preferences.blp:276 data/gtk/preferences.blp:293
msgid "Install Location"
msgstr "Ruta de instalación"
#: data/gtk/preferences.blp:119
#: data/gtk/preferences.blp:121
msgid "Lutris"
msgstr "Lutris"
#: data/gtk/preferences.blp:132
#: data/gtk/preferences.blp:137
msgid "Cache Location"
msgstr "Ruta de la caché"
#: data/gtk/preferences.blp:141
#: data/gtk/preferences.blp:149
msgid "Import Steam Games"
msgstr "Importar juegos de Steam"
#: data/gtk/preferences.blp:150
#: data/gtk/preferences.blp:158
msgid "Import Flatpak Games"
msgstr "Importar juegos Flatpak"
#: data/gtk/preferences.blp:160
#: data/gtk/preferences.blp:168
msgid "Heroic"
msgstr "Heroic"
#: data/gtk/preferences.blp:173
#: data/gtk/preferences.blp:184
msgid "Import Epic Games"
msgstr "Importar juegos de Epic"
#: data/gtk/preferences.blp:182
#: data/gtk/preferences.blp:193
msgid "Import GOG Games"
msgstr "Importar juegos de GOG"
#: data/gtk/preferences.blp:191
#: data/gtk/preferences.blp:202
msgid "Import Amazon Games"
msgstr "Importar de Amazon Games"
#: data/gtk/preferences.blp:200
#: data/gtk/preferences.blp:211
msgid "Import Sideloaded Games"
msgstr "Importar juegos descargados"
#: data/gtk/preferences.blp:210
#: data/gtk/preferences.blp:221
msgid "Bottles"
msgstr "Bottles"
#: data/gtk/preferences.blp:224
#: data/gtk/preferences.blp:238
msgid "itch"
msgstr "itch"
#: data/gtk/preferences.blp:238
#: data/gtk/preferences.blp:255
msgid "Legendary"
msgstr "Legendario"
#: data/gtk/preferences.blp:252
#: data/gtk/preferences.blp:272
msgid "RetroArch"
msgstr "RetroArch"
#: data/gtk/preferences.blp:266
#: data/gtk/preferences.blp:289
msgid "Flatpak"
msgstr "Flatpak"
#: data/gtk/preferences.blp:279
#: data/gtk/preferences.blp:305
msgid "Import Game Launchers"
msgstr "Importar lanzadores de juegos"
#: data/gtk/preferences.blp:292
#: data/gtk/preferences.blp:315
msgid "Desktop Entries"
msgstr "Entradas en el escritorio"
#: data/gtk/preferences.blp:327
msgid "SteamGridDB"
msgstr "SteamGridDB"
#: data/gtk/preferences.blp:296
#: data/gtk/preferences.blp:331
msgid "Authentication"
msgstr "Autenticación"
#: data/gtk/preferences.blp:299
#: data/gtk/preferences.blp:334
msgid "API Key"
msgstr "Clave API"
#: data/gtk/preferences.blp:307
#: data/gtk/preferences.blp:342
msgid "Use SteamGridDB"
msgstr "Usar SteamGridDB"
#: data/gtk/preferences.blp:308
#: data/gtk/preferences.blp:343
msgid "Download images when adding or importing games"
msgstr "Descargar las imágenes al añadir o importar juegos"
#: data/gtk/preferences.blp:317
#: data/gtk/preferences.blp:352
msgid "Prefer Over Official Images"
msgstr "Preferir las imágenes oficiales"
#: data/gtk/preferences.blp:326
#: data/gtk/preferences.blp:361
msgid "Prefer Animated Images"
msgstr "Prefiero las imágenes animadas"
@@ -341,7 +349,7 @@ msgstr "No hay juegos ocultos"
msgid "Games you hide will appear here."
msgstr "Los juegos que oculte aparecerán aquí."
#: data/gtk/window.blp:64 data/gtk/window.blp:305
#: data/gtk/window.blp:64 data/gtk/window.blp:317
msgid "Back"
msgstr "Volver"
@@ -353,114 +361,118 @@ msgstr "Título del juego"
msgid "Play"
msgstr "Jugar"
#: data/gtk/window.blp:243 data/gtk/window.blp:437
#: data/gtk/window.blp:255 data/gtk/window.blp:449
msgid "Add Game"
msgstr "Añadir juego"
#: data/gtk/window.blp:250 data/gtk/window.blp:317
#: data/gtk/window.blp:262 data/gtk/window.blp:329
msgid "Main Menu"
msgstr "Menú principal"
#: data/gtk/window.blp:272
#: data/gtk/window.blp:284
msgid "Search games"
msgstr "Buscar los juegos"
#: data/gtk/window.blp:312
#: data/gtk/window.blp:324
msgid "Hidden Games"
msgstr "Juegos ocultos"
#: data/gtk/window.blp:339
#: data/gtk/window.blp:351
msgid "Search hidden games"
msgstr "Buscar los juegos ocultos"
#: data/gtk/window.blp:376
#: data/gtk/window.blp:388
msgid "Sort"
msgstr "Ordenar"
#: data/gtk/window.blp:379
#: data/gtk/window.blp:391
msgid "A-Z"
msgstr "A-Z"
#: data/gtk/window.blp:385
#: data/gtk/window.blp:397
msgid "Z-A"
msgstr "Z-A"
#: data/gtk/window.blp:391
#: data/gtk/window.blp:403
msgid "Newest"
msgstr "Más recientes"
#: data/gtk/window.blp:397
#: data/gtk/window.blp:409
msgid "Oldest"
msgstr "Más antiguos"
#: data/gtk/window.blp:403
#: data/gtk/window.blp:415
msgid "Last Played"
msgstr "Último jugado"
#: data/gtk/window.blp:410
#: data/gtk/window.blp:422
msgid "Show Hidden"
msgstr "Mostrar ocultos"
#: data/gtk/window.blp:423
#: data/gtk/window.blp:435
msgid "Keyboard Shortcuts"
msgstr "Atajos del teclado"
#: data/gtk/window.blp:428
#: data/gtk/window.blp:440
msgid "About Cartridges"
msgstr "Acerca de Cartuchos"
#. Translators: Replace this with your name for it to show up in the about window
#: src/main.py:188
#: src/main.py:195
msgid "translator_credits"
msgstr "Óscar Fernández Díaz <oscfdezdz@tuta.io>"
#. The variable is the date when the game was added
#: src/window.py:194
#: src/window.py:213
msgid "Added: {}"
msgstr "Añadido: {}"
#: src/window.py:197
#: src/window.py:216
msgid "Never"
msgstr "Nunca"
#. The variable is the date when the game was last played
#: src/window.py:201
#: src/window.py:220
msgid "Last played: {}"
msgstr "Último jugado: {}"
#: src/details_window.py:72
#: src/details_window.py:76
msgid "Apply"
msgstr "Aplicar"
#: src/details_window.py:78
#: src/details_window.py:82
msgid "Add New Game"
msgstr "Añadir juego nuevo"
msgstr "Añadir un nuevo Juego"
#: src/details_window.py:79
#: src/details_window.py:83
msgid "Add"
msgstr "Añadir"
#: src/details_window.py:93
msgid "Executables"
msgstr "Ejecutables"
#. Translate this string as you would translate "file"
#: src/details_window.py:92
#: src/details_window.py:108
msgid "file.txt"
msgstr "archivo.txt"
#. As in software
#: src/details_window.py:94
#: src/details_window.py:110
msgid "program"
msgstr "programa"
#. Translate this string as you would translate "path to {}"
#: src/details_window.py:99 src/details_window.py:101
#: src/details_window.py:115 src/details_window.py:117
msgid "C:\\path\\to\\{}"
msgstr "C:\\ruta\\hasta\\{}"
#. Translate this string as you would translate "path to {}"
#: src/details_window.py:105 src/details_window.py:107
#: src/details_window.py:121 src/details_window.py:123
msgid "/path/to/{}"
msgstr "/ruta/hasta/{}"
#: src/details_window.py:112
#: src/details_window.py:128
msgid ""
"To launch the executable \"{}\", use the command:\n"
"\n"
@@ -482,100 +494,100 @@ msgstr ""
"\n"
"Si la ruta contiene espacios, ¡asegúrese de entrecomillarla!"
#: src/details_window.py:147 src/details_window.py:153
#: src/details_window.py:171 src/details_window.py:177
msgid "Couldn't Add Game"
msgstr "No se puede añadir el juego"
#: src/details_window.py:147 src/details_window.py:183
#: src/details_window.py:171 src/details_window.py:207
msgid "Game title cannot be empty."
msgstr "El título del juego no puede estar vacío."
#: src/details_window.py:153 src/details_window.py:191
#: src/details_window.py:177 src/details_window.py:215
msgid "Executable cannot be empty."
msgstr "El ejecutable no puede estar vacío."
#: src/details_window.py:182 src/details_window.py:190
#: src/details_window.py:206 src/details_window.py:214
msgid "Couldn't Apply Preferences"
msgstr "No se pudieron aplicar las preferencias"
#. The variable is the title of the game
#: src/game.py:139
#: src/game.py:141
msgid "{} launched"
msgstr "{} comenzó"
#. The variable is the title of the game
#: src/game.py:153
#: src/game.py:155
msgid "{} hidden"
msgstr "{} oculto"
#: src/game.py:153
#: src/game.py:155
msgid "{} unhidden"
msgstr "{} visible"
#. The variable is the title of the game
#. The variable is the number of games removed
#: src/game.py:170 src/importer/importer.py:363
#: src/game.py:172 src/importer/importer.py:373
msgid "{} removed"
msgstr "{} eliminado"
#: src/preferences.py:119
#: src/preferences.py:123
msgid "All games removed"
msgstr "Todos los juegos eliminados"
#: src/preferences.py:168
#: src/preferences.py:172
msgid ""
"An API key is required to use SteamGridDB. You can generate one {}here{}."
msgstr ""
"Se necesita una clave API para utilizar SteamGridDB. Puedes generar una {}"
"aquí{}."
#: src/preferences.py:294
#: src/preferences.py:293
msgid "Installation Not Found"
msgstr "Instalación no encontrada"
#: src/preferences.py:296
#: src/preferences.py:294
msgid "Select a valid directory."
msgstr "Selecciona un directorio válido."
#: src/preferences.py:351
msgid "Invalid Directory"
msgstr "Directorio incorrecto"
#: src/preferences.py:357
msgid "Set Location"
msgstr "Escoger la ubicación"
#: src/utils/create_dialog.py:25 src/importer/importer.py:291
msgid "Dismiss"
msgstr "Descartar"
#: src/importer/importer.py:128
msgid "Importing Games…"
msgstr "Importando juegos…"
#: src/importer/importer.py:290
#: src/preferences.py:330 src/importer/importer.py:299
msgid "Warning"
msgstr "Advertencia"
#: src/importer/importer.py:311
#: src/preferences.py:364
msgid "Invalid Directory"
msgstr "Directorio incorrecto"
#: src/preferences.py:370
msgid "Set Location"
msgstr "Escoger la ubicación"
#: src/utils/create_dialog.py:33 src/importer/importer.py:300
msgid "Dismiss"
msgstr "Descartar"
#: src/importer/importer.py:137
msgid "Importing Games…"
msgstr "Importando juegos…"
#: src/importer/importer.py:320
msgid "The following errors occured during import:"
msgstr "Han sucedido los siguientes fallos durante la importación:"
#: src/importer/importer.py:339
#: src/importer/importer.py:349
msgid "No new games found"
msgstr "No se encontraron juegos nuevos"
#: src/importer/importer.py:351
#: src/importer/importer.py:361
msgid "1 game imported"
msgstr "1 juego importado"
#. The variable is the number of games
#: src/importer/importer.py:355
#: src/importer/importer.py:365
msgid "{} games imported"
msgstr "0 juegos importados"
#. A single game removed
#: src/importer/importer.py:359
#: src/importer/importer.py:369
msgid "1 removed"
msgstr "1 eliminado"

277
po/ru.po
View File

@@ -3,12 +3,13 @@
# This file is distributed under the same license as the cartridges package.
# Сергей <asvmail.as@gmail.com>, 2023.
# kramo <contact@kramo.hu>, 2023.
# Сергей Ворон <voron.s.a@gmail.com>, 2023.
msgid ""
msgstr ""
"Project-Id-Version: cartridges\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-08-16 11:06+0200\n"
"PO-Revision-Date: 2023-07-31 00:05+0000\n"
"POT-Creation-Date: 2023-08-27 14:03+0200\n"
"PO-Revision-Date: 2023-08-29 10:45+0000\n"
"Last-Translator: Сергей <asvmail.as@gmail.com>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/cartridges/"
"cartridges/ru/>\n"
@@ -16,13 +17,13 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 5.0-dev\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 5.0.1-dev\n"
#: data/hu.kramo.Cartridges.desktop.in:3
#: data/hu.kramo.Cartridges.metainfo.xml.in:6 data/gtk/window.blp:47
#: src/main.py:169
#: src/main.py:176
msgid "Cartridges"
msgstr "Картриджи"
@@ -36,12 +37,11 @@ msgid "Launch all your games"
msgstr "Запустите все свои игры"
#: data/hu.kramo.Cartridges.desktop.in:11
#, fuzzy
#| msgid "gaming;launcher;steam;lutris;heroic;bottles;itch;flatpak;legendary;"
msgid ""
"gaming;launcher;steam;lutris;heroic;bottles;itch;flatpak;legendary;retroarch;"
msgstr ""
"gaming;launcher;steam;lutris;heroic;bottles;itch;flatpak;legendary;игры;стим;"
"gaming;launcher;steam;lutris;heroic;bottles;itch;flatpak;legendary;retroarch;"
"игры;стим;"
#: data/hu.kramo.Cartridges.metainfo.xml.in:9
msgid ""
@@ -64,13 +64,13 @@ msgid "Edit Game Details"
msgstr "Редактировать подробности об игре"
#: data/hu.kramo.Cartridges.metainfo.xml.in:38 data/gtk/window.blp:71
#: src/details_window.py:67
#: src/details_window.py:71
msgid "Game Details"
msgstr "Подробности об игре"
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:418
#: src/details_window.py:241 src/importer/importer.py:292
#: src/importer/importer.py:342
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:430
#: src/details_window.py:265 src/importer/importer.py:301
#: src/importer/importer.py:352
msgid "Preferences"
msgstr "Параметры"
@@ -78,29 +78,31 @@ msgstr "Параметры"
msgid "Cancel"
msgstr "Отменить"
#: data/gtk/details-window.blp:57
#: data/gtk/details-window.blp:58
msgid "New Cover"
msgstr "Новая обложка"
#: data/gtk/details-window.blp:75
#: data/gtk/details-window.blp:77
msgid "Delete Cover"
msgstr "Удалить обложку"
#: data/gtk/details-window.blp:102 data/gtk/game.blp:80
#: data/gtk/details-window.blp:105 data/gtk/game.blp:80
msgid "Title"
msgstr "Название"
#: data/gtk/details-window.blp:105
#, fuzzy
#| msgid "The developer or publisher (optional)"
#: data/gtk/details-window.blp:109
msgid "Developer (optional)"
msgstr "Разработчик или издатель (необязательно)"
msgstr "Разработчик (необязательно)"
#: data/gtk/details-window.blp:110
#: data/gtk/details-window.blp:115
msgid "Executable"
msgstr "Исполняемый"
#: data/gtk/details-window.blp:116
#: data/gtk/details-window.blp:121
msgid "Select File"
msgstr "Выбрать файл"
#: data/gtk/details-window.blp:132
msgid "More Info"
msgstr "Дополнительная информация"
@@ -108,29 +110,29 @@ msgstr "Дополнительная информация"
msgid "Edit"
msgstr "Редактировать"
#: data/gtk/game.blp:107 src/window.py:171
#: data/gtk/game.blp:107 src/window.py:190
msgid "Hide"
msgstr "Скрыть"
#: data/gtk/game.blp:112 data/gtk/game.blp:131 data/gtk/preferences.blp:56
#: data/gtk/window.blp:209
#: data/gtk/window.blp:215
msgid "Remove"
msgstr "Удалить"
#: data/gtk/game.blp:126 src/window.py:173
#: data/gtk/game.blp:126 src/window.py:192
msgid "Unhide"
msgstr "Показать"
#: data/gtk/help-overlay.blp:11 data/gtk/preferences.blp:9
msgid "General"
msgstr "Основное"
msgstr "Общее"
#: data/gtk/help-overlay.blp:14
msgid "Quit"
msgstr "Выйти"
#: data/gtk/help-overlay.blp:19 data/gtk/window.blp:217 data/gtk/window.blp:257
#: data/gtk/window.blp:324
#: data/gtk/help-overlay.blp:19 data/gtk/window.blp:226 data/gtk/window.blp:269
#: data/gtk/window.blp:336
msgid "Search"
msgstr "Поиск"
@@ -142,8 +144,8 @@ msgstr "Показать параметры"
msgid "Shortcuts"
msgstr "Комбинации клавиш"
#: data/gtk/help-overlay.blp:34 src/game.py:103 src/preferences.py:120
#: src/importer/importer.py:366
#: data/gtk/help-overlay.blp:34 src/game.py:105 src/preferences.py:124
#: src/importer/importer.py:376
msgid "Undo"
msgstr "Вернуть"
@@ -171,24 +173,24 @@ msgstr "Показать скрытые игры"
msgid "Remove game"
msgstr "Удалить игру"
#: data/gtk/preferences.blp:13 data/gtk/preferences.blp:89
#: data/gtk/preferences.blp:304
#: data/gtk/preferences.blp:13 data/gtk/preferences.blp:88
#: data/gtk/preferences.blp:339
msgid "Behavior"
msgstr "Поведение"
#: data/gtk/preferences.blp:16
msgid "Exit After Launching Games"
msgstr "Выход после запуска игр"
msgstr "Выход из приложения после запуска игры"
#: data/gtk/preferences.blp:25
msgid "Cover Image Launches Game"
msgstr "Запуск игры используя изображение обложки"
msgstr "Запускать игры используя изображение обложки"
#: data/gtk/preferences.blp:26
msgid "Swaps the behavior of the cover image and the play button"
msgstr "Меняет местами поведение изображения обложки и кнопки запуска"
#: data/gtk/preferences.blp:36 src/details_window.py:81
#: data/gtk/preferences.blp:36 src/details_window.py:85
msgid "Images"
msgstr "Изображения"
@@ -208,116 +210,118 @@ msgstr "Небезопасная область"
msgid "Remove All Games"
msgstr "Удалить все игры"
#: data/gtk/preferences.blp:85 data/gtk/window.blp:27 data/gtk/window.blp:444
#: data/gtk/preferences.blp:84 data/gtk/window.blp:27 data/gtk/window.blp:456
msgid "Import"
msgstr "Импортировать"
msgstr "Импорт"
#: data/gtk/preferences.blp:92
#, fuzzy
#| msgid "Remove All Games"
#: data/gtk/preferences.blp:91
msgid "Remove Uninstalled Games"
msgstr "Удалить все игры"
msgstr "Удалять деинсталлированные игры"
#: data/gtk/preferences.blp:102
#: data/gtk/preferences.blp:101
msgid "Sources"
msgstr "Источники"
#: data/gtk/preferences.blp:105
#: data/gtk/preferences.blp:104
msgid "Steam"
msgstr "Steam"
#: data/gtk/preferences.blp:109 data/gtk/preferences.blp:123
#: data/gtk/preferences.blp:164 data/gtk/preferences.blp:214
#: data/gtk/preferences.blp:228 data/gtk/preferences.blp:242
#: data/gtk/preferences.blp:256 data/gtk/preferences.blp:270
#: data/gtk/preferences.blp:108 data/gtk/preferences.blp:125
#: data/gtk/preferences.blp:172 data/gtk/preferences.blp:225
#: data/gtk/preferences.blp:242 data/gtk/preferences.blp:259
#: data/gtk/preferences.blp:276 data/gtk/preferences.blp:293
msgid "Install Location"
msgstr "Место установки"
#: data/gtk/preferences.blp:119
#: data/gtk/preferences.blp:121
msgid "Lutris"
msgstr "Lutris"
#: data/gtk/preferences.blp:132
#: data/gtk/preferences.blp:137
msgid "Cache Location"
msgstr "Расположение кэша"
#: data/gtk/preferences.blp:141
#: data/gtk/preferences.blp:149
msgid "Import Steam Games"
msgstr "Импорт игр Steam"
#: data/gtk/preferences.blp:150
#: data/gtk/preferences.blp:158
msgid "Import Flatpak Games"
msgstr "Импорт игр Flatpak"
#: data/gtk/preferences.blp:160
#: data/gtk/preferences.blp:168
msgid "Heroic"
msgstr "Heroic"
#: data/gtk/preferences.blp:173
#: data/gtk/preferences.blp:184
msgid "Import Epic Games"
msgstr "Импорт игр Epic"
#: data/gtk/preferences.blp:182
#: data/gtk/preferences.blp:193
msgid "Import GOG Games"
msgstr "Импорт игр GOG"
#: data/gtk/preferences.blp:191
#: data/gtk/preferences.blp:202
msgid "Import Amazon Games"
msgstr "Импорт игр Amazon"
#: data/gtk/preferences.blp:200
#: data/gtk/preferences.blp:211
msgid "Import Sideloaded Games"
msgstr "Импорт сторонних игр"
#: data/gtk/preferences.blp:210
#: data/gtk/preferences.blp:221
msgid "Bottles"
msgstr "Bottles"
#: data/gtk/preferences.blp:224
#: data/gtk/preferences.blp:238
msgid "itch"
msgstr "itch"
#: data/gtk/preferences.blp:238
#: data/gtk/preferences.blp:255
msgid "Legendary"
msgstr "Legendary"
#: data/gtk/preferences.blp:252
#: data/gtk/preferences.blp:272
msgid "RetroArch"
msgstr ""
msgstr "RetroArch"
#: data/gtk/preferences.blp:266
#: data/gtk/preferences.blp:289
msgid "Flatpak"
msgstr "Flatpak"
#: data/gtk/preferences.blp:279
#: data/gtk/preferences.blp:305
msgid "Import Game Launchers"
msgstr "Импорт средств запуска игр"
#: data/gtk/preferences.blp:292
#: data/gtk/preferences.blp:315
msgid "Desktop Entries"
msgstr "Интеграция в среду рабочего стола"
#: data/gtk/preferences.blp:327
msgid "SteamGridDB"
msgstr "SteamGridDB"
#: data/gtk/preferences.blp:296
#: data/gtk/preferences.blp:331
msgid "Authentication"
msgstr "Аутентификация"
#: data/gtk/preferences.blp:299
#: data/gtk/preferences.blp:334
msgid "API Key"
msgstr "API-ключ"
#: data/gtk/preferences.blp:307
#: data/gtk/preferences.blp:342
msgid "Use SteamGridDB"
msgstr "Использовать SteamGridDB"
#: data/gtk/preferences.blp:308
#: data/gtk/preferences.blp:343
msgid "Download images when adding or importing games"
msgstr "Загрузка изображений при добавлении или импорте игр"
#: data/gtk/preferences.blp:317
#: data/gtk/preferences.blp:352
msgid "Prefer Over Official Images"
msgstr "Отдавать предпочтение официальным изображениям"
#: data/gtk/preferences.blp:326
#: data/gtk/preferences.blp:361
msgid "Prefer Animated Images"
msgstr "Отдавать предпочтение анимированным изображениям"
@@ -345,7 +349,7 @@ msgstr "Нет скрытых игр"
msgid "Games you hide will appear here."
msgstr "Здесь появятся скрытые игры."
#: data/gtk/window.blp:64 data/gtk/window.blp:305
#: data/gtk/window.blp:64 data/gtk/window.blp:317
msgid "Back"
msgstr "Назад"
@@ -357,118 +361,118 @@ msgstr "Название игры"
msgid "Play"
msgstr "Играть"
#: data/gtk/window.blp:243 data/gtk/window.blp:437
#: data/gtk/window.blp:255 data/gtk/window.blp:449
msgid "Add Game"
msgstr "Добавить игру"
#: data/gtk/window.blp:250 data/gtk/window.blp:317
#: data/gtk/window.blp:262 data/gtk/window.blp:329
msgid "Main Menu"
msgstr "Главное меню"
#: data/gtk/window.blp:272
#, fuzzy
#| msgid "Search"
#: data/gtk/window.blp:284
msgid "Search games"
msgstr "Поиск"
msgstr "Поиск игр"
#: data/gtk/window.blp:312
#: data/gtk/window.blp:324
msgid "Hidden Games"
msgstr "Скрытые игры"
#: data/gtk/window.blp:339
#, fuzzy
#| msgid "Show hidden games"
#: data/gtk/window.blp:351
msgid "Search hidden games"
msgstr "Показать скрытые игры"
msgstr "Поиск скрытых игр"
#: data/gtk/window.blp:376
#: data/gtk/window.blp:388
msgid "Sort"
msgstr "Сортировать"
#: data/gtk/window.blp:379
#: data/gtk/window.blp:391
msgid "A-Z"
msgstr "А-Я"
#: data/gtk/window.blp:385
#: data/gtk/window.blp:397
msgid "Z-A"
msgstr "Я-А"
#: data/gtk/window.blp:391
#: data/gtk/window.blp:403
msgid "Newest"
msgstr "Сначала новые"
#: data/gtk/window.blp:397
#: data/gtk/window.blp:409
msgid "Oldest"
msgstr "Сначала старые"
#: data/gtk/window.blp:403
#: data/gtk/window.blp:415
msgid "Last Played"
msgstr "Последняя игра"
#: data/gtk/window.blp:410
#: data/gtk/window.blp:422
msgid "Show Hidden"
msgstr "Показать скрытые"
#: data/gtk/window.blp:423
#: data/gtk/window.blp:435
msgid "Keyboard Shortcuts"
msgstr "Комбинации клавиш"
#: data/gtk/window.blp:428
#: data/gtk/window.blp:440
msgid "About Cartridges"
msgstr "О приложении"
#. Translators: Replace this with your name for it to show up in the about window
#: src/main.py:188
#: src/main.py:195
msgid "translator_credits"
msgstr "Ser82-png"
#. The variable is the date when the game was added
#: src/window.py:194
#: src/window.py:213
msgid "Added: {}"
msgstr "Добавлено: {}"
#: src/window.py:197
#: src/window.py:216
msgid "Never"
msgstr "Никогда"
#. The variable is the date when the game was last played
#: src/window.py:201
#: src/window.py:220
msgid "Last played: {}"
msgstr "Последний раз запускалась: {}"
#: src/details_window.py:72
#: src/details_window.py:76
msgid "Apply"
msgstr "Применить"
#: src/details_window.py:78
#: src/details_window.py:82
msgid "Add New Game"
msgstr "Добавить новую игру"
#: src/details_window.py:79
#: src/details_window.py:83
msgid "Add"
msgstr ""
msgstr "Добавить"
#: src/details_window.py:93
msgid "Executables"
msgstr "Исполняемые"
#. Translate this string as you would translate "file"
#: src/details_window.py:92
#: src/details_window.py:108
msgid "file.txt"
msgstr "file.txt"
#. As in software
#: src/details_window.py:94
#: src/details_window.py:110
msgid "program"
msgstr "программа"
#. Translate this string as you would translate "path to {}"
#: src/details_window.py:99 src/details_window.py:101
#: src/details_window.py:115 src/details_window.py:117
msgid "C:\\path\\to\\{}"
msgstr "C:\\путь\\к\\{}"
#. Translate this string as you would translate "path to {}"
#: src/details_window.py:105 src/details_window.py:107
#: src/details_window.py:121 src/details_window.py:123
msgid "/path/to/{}"
msgstr "/путь/к/{}"
#: src/details_window.py:112
#: src/details_window.py:128
msgid ""
"To launch the executable \"{}\", use the command:\n"
"\n"
@@ -490,104 +494,102 @@ msgstr ""
"\n"
"Если путь содержит пробелы, обязательно заключите его в двойные кавычки!"
#: src/details_window.py:147 src/details_window.py:153
#: src/details_window.py:171 src/details_window.py:177
msgid "Couldn't Add Game"
msgstr "Не удалось добавить игру"
#: src/details_window.py:147 src/details_window.py:183
#: src/details_window.py:171 src/details_window.py:207
msgid "Game title cannot be empty."
msgstr "Название игры не может быть пустым."
#: src/details_window.py:153 src/details_window.py:191
#: src/details_window.py:177 src/details_window.py:215
msgid "Executable cannot be empty."
msgstr "Исполняемый файл не может быть пустым."
#: src/details_window.py:182 src/details_window.py:190
#: src/details_window.py:206 src/details_window.py:214
msgid "Couldn't Apply Preferences"
msgstr "Не удалось применить параметры"
#. The variable is the title of the game
#: src/game.py:139
#: src/game.py:141
msgid "{} launched"
msgstr "{} - запущена"
#. The variable is the title of the game
#: src/game.py:153
#: src/game.py:155
msgid "{} hidden"
msgstr "{} - скрытая"
#: src/game.py:153
#: src/game.py:155
msgid "{} unhidden"
msgstr "{} - не скрыта"
#. The variable is the title of the game
#. The variable is the number of games removed
#: src/game.py:170 src/importer/importer.py:363
#: src/game.py:172 src/importer/importer.py:373
msgid "{} removed"
msgstr "{} удалена"
#: src/preferences.py:119
#: src/preferences.py:123
msgid "All games removed"
msgstr "Все игры удалены"
#: src/preferences.py:168
#: src/preferences.py:172
msgid ""
"An API key is required to use SteamGridDB. You can generate one {}here{}."
msgstr ""
"Для использования SteamGridDB требуется ключ API. Вы можете сгенерировать "
"его {}здесь{}."
#: src/preferences.py:294
#: src/preferences.py:293
msgid "Installation Not Found"
msgstr "Установка не найдена"
#: src/preferences.py:296
#: src/preferences.py:294
msgid "Select a valid directory."
msgstr "Выберите действующий каталог."
#: src/preferences.py:351
#: src/preferences.py:330 src/importer/importer.py:299
msgid "Warning"
msgstr "Предупреждение"
#: src/preferences.py:364
msgid "Invalid Directory"
msgstr "Неверный каталог"
#: src/preferences.py:357
#: src/preferences.py:370
msgid "Set Location"
msgstr "Установить расположение"
#: src/utils/create_dialog.py:25 src/importer/importer.py:291
#: src/utils/create_dialog.py:33 src/importer/importer.py:300
msgid "Dismiss"
msgstr "Отклонить"
#: src/importer/importer.py:128
#: src/importer/importer.py:137
msgid "Importing Games…"
msgstr "Импорт игр…"
#: src/importer/importer.py:290
msgid "Warning"
msgstr ""
#: src/importer/importer.py:311
#: src/importer/importer.py:320
msgid "The following errors occured during import:"
msgstr ""
msgstr "При импорте возникли следующие ошибки:"
#: src/importer/importer.py:339
#: src/importer/importer.py:349
msgid "No new games found"
msgstr "Новых игр не найдено"
#: src/importer/importer.py:351
#: src/importer/importer.py:361
msgid "1 game imported"
msgstr "1 игра импортирована"
#. The variable is the number of games
#: src/importer/importer.py:355
#: src/importer/importer.py:365
msgid "{} games imported"
msgstr "{} игр(ы) импортировано"
#. A single game removed
#: src/importer/importer.py:359
#, fuzzy
#| msgid "{} removed"
#: src/importer/importer.py:369
msgid "1 removed"
msgstr "{} удалена"
msgstr "1 удалена"
#. The variable is the name of the source
#: src/importer/sources/location.py:33
@@ -612,6 +614,15 @@ msgstr "Не удалось пройти аутентификацию SteamGridD
msgid "Verify your API key in preferences"
msgstr "Проверьте ключ API-ключ в параметрах"
#~ msgid "Terminal"
#~ msgstr "Терминал"
#~ msgid "Used only by games that require one to run"
#~ msgstr "Используется только играми, требующими его запуска"
#~ msgid "Custom"
#~ msgstr "Пользовательский"
#~ msgid "The title of the game"
#~ msgstr "Название игры"

234
po/ta.po
View File

@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Cartridges\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-08-16 11:06+0200\n"
"PO-Revision-Date: 2023-08-15 04:05+0000\n"
"POT-Creation-Date: 2023-08-27 14:03+0200\n"
"PO-Revision-Date: 2023-08-29 10:45+0000\n"
"Last-Translator: \"K.B.Dharun Krishna\" <kbdharunkrishna@gmail.com>\n"
"Language-Team: Tamil <https://hosted.weblate.org/projects/cartridges/"
"cartridges/ta/>\n"
@@ -18,11 +18,11 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.0-dev\n"
"X-Generator: Weblate 5.0.1-dev\n"
#: data/hu.kramo.Cartridges.desktop.in:3
#: data/hu.kramo.Cartridges.metainfo.xml.in:6 data/gtk/window.blp:47
#: src/main.py:169
#: src/main.py:176
msgid "Cartridges"
msgstr "கார்ட்ரிட்ஜ்கள்"
@@ -63,13 +63,13 @@ msgid "Edit Game Details"
msgstr "விளையாட்டு விவரங்களைத் திருத்து"
#: data/hu.kramo.Cartridges.metainfo.xml.in:38 data/gtk/window.blp:71
#: src/details_window.py:67
#: src/details_window.py:71
msgid "Game Details"
msgstr "விளையாட்டு விவரங்கள்"
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:418
#: src/details_window.py:241 src/importer/importer.py:292
#: src/importer/importer.py:342
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/window.blp:430
#: src/details_window.py:265 src/importer/importer.py:301
#: src/importer/importer.py:352
msgid "Preferences"
msgstr "விருப்பங்கள்"
@@ -77,27 +77,31 @@ msgstr "விருப்பங்கள்"
msgid "Cancel"
msgstr "ரத்துசெய்"
#: data/gtk/details-window.blp:57
#: data/gtk/details-window.blp:58
msgid "New Cover"
msgstr "புதிய அட்டை"
#: data/gtk/details-window.blp:75
#: data/gtk/details-window.blp:77
msgid "Delete Cover"
msgstr "அட்டையை நீக்கு"
#: data/gtk/details-window.blp:102 data/gtk/game.blp:80
#: data/gtk/details-window.blp:105 data/gtk/game.blp:80
msgid "Title"
msgstr "தலைப்பு"
#: data/gtk/details-window.blp:105
#: data/gtk/details-window.blp:109
msgid "Developer (optional)"
msgstr "டெவலப்பர் (விரும்பினால்)"
#: data/gtk/details-window.blp:110
#: data/gtk/details-window.blp:115
msgid "Executable"
msgstr "செயல்படுத்தக்கூடியது"
#: data/gtk/details-window.blp:116
#: data/gtk/details-window.blp:121
msgid "Select File"
msgstr "கோப்பைத் தேர்ந்தெடுக்கவும்"
#: data/gtk/details-window.blp:132
msgid "More Info"
msgstr "மேலும் தகவல்"
@@ -105,16 +109,16 @@ msgstr "மேலும் தகவல்"
msgid "Edit"
msgstr "தொகு"
#: data/gtk/game.blp:107 src/window.py:171
#: data/gtk/game.blp:107 src/window.py:190
msgid "Hide"
msgstr "மறை"
#: data/gtk/game.blp:112 data/gtk/game.blp:131 data/gtk/preferences.blp:56
#: data/gtk/window.blp:209
#: data/gtk/window.blp:215
msgid "Remove"
msgstr "அகற்று"
#: data/gtk/game.blp:126 src/window.py:173
#: data/gtk/game.blp:126 src/window.py:192
msgid "Unhide"
msgstr "மறை காட்டு"
@@ -126,8 +130,8 @@ msgstr "பொது"
msgid "Quit"
msgstr "வெளியேறு"
#: data/gtk/help-overlay.blp:19 data/gtk/window.blp:217 data/gtk/window.blp:257
#: data/gtk/window.blp:324
#: data/gtk/help-overlay.blp:19 data/gtk/window.blp:226 data/gtk/window.blp:269
#: data/gtk/window.blp:336
msgid "Search"
msgstr "தேடு"
@@ -139,8 +143,8 @@ msgstr "விருப்பங்களைக் காட்டு"
msgid "Shortcuts"
msgstr "குறுக்குவழிகள்"
#: data/gtk/help-overlay.blp:34 src/game.py:103 src/preferences.py:120
#: src/importer/importer.py:366
#: data/gtk/help-overlay.blp:34 src/game.py:105 src/preferences.py:124
#: src/importer/importer.py:376
msgid "Undo"
msgstr "செயல்தவிர்"
@@ -168,8 +172,8 @@ msgstr "மறைக்கப்பட்ட விளையாட்டுக
msgid "Remove game"
msgstr "விளையாட்டை அகற்று"
#: data/gtk/preferences.blp:13 data/gtk/preferences.blp:89
#: data/gtk/preferences.blp:304
#: data/gtk/preferences.blp:13 data/gtk/preferences.blp:88
#: data/gtk/preferences.blp:339
msgid "Behavior"
msgstr "நடத்தை"
@@ -185,7 +189,7 @@ msgstr "அட்டைப் படம் விளையாட்டை தொ
msgid "Swaps the behavior of the cover image and the play button"
msgstr "அட்டைப் படத்தின் நடத்தை மற்றும் பிளே பட்டனை மாற்றுகிறது"
#: data/gtk/preferences.blp:36 src/details_window.py:81
#: data/gtk/preferences.blp:36 src/details_window.py:85
msgid "Images"
msgstr "படங்கள்"
@@ -205,117 +209,119 @@ msgstr "ஆபத்து மண்டலம்"
msgid "Remove All Games"
msgstr "அனைத்து விளையாட்டுகளையும் அகற்று"
#: data/gtk/preferences.blp:85 data/gtk/window.blp:27 data/gtk/window.blp:444
#: data/gtk/preferences.blp:84 data/gtk/window.blp:27 data/gtk/window.blp:456
msgid "Import"
msgstr "இறக்குமதி"
#: data/gtk/preferences.blp:92
#, fuzzy
#| msgid "Remove All Games"
#: data/gtk/preferences.blp:91
msgid "Remove Uninstalled Games"
msgstr "அனைத்து விளையாட்டுகளையும் அகற்று"
msgstr "நிறுவல் நீக்கப்பட்ட விளையாட்டுகளை அகற்று"
#: data/gtk/preferences.blp:102
#: data/gtk/preferences.blp:101
msgid "Sources"
msgstr "மூலங்கள்"
#: data/gtk/preferences.blp:105
#: data/gtk/preferences.blp:104
msgid "Steam"
msgstr "Steam"
#: data/gtk/preferences.blp:109 data/gtk/preferences.blp:123
#: data/gtk/preferences.blp:164 data/gtk/preferences.blp:214
#: data/gtk/preferences.blp:228 data/gtk/preferences.blp:242
#: data/gtk/preferences.blp:256 data/gtk/preferences.blp:270
#: data/gtk/preferences.blp:108 data/gtk/preferences.blp:125
#: data/gtk/preferences.blp:172 data/gtk/preferences.blp:225
#: data/gtk/preferences.blp:242 data/gtk/preferences.blp:259
#: data/gtk/preferences.blp:276 data/gtk/preferences.blp:293
msgid "Install Location"
msgstr "நிறுவல் இடம்"
#: data/gtk/preferences.blp:119
#: data/gtk/preferences.blp:121
msgid "Lutris"
msgstr "Lutris"
#: data/gtk/preferences.blp:132
#: data/gtk/preferences.blp:137
msgid "Cache Location"
msgstr "தற்காலிக சேமிப்பு இடம்"
#: data/gtk/preferences.blp:141
#: data/gtk/preferences.blp:149
msgid "Import Steam Games"
msgstr "Steam விளையாட்டுகளை இறக்குமதி செய்யவும்"
#: data/gtk/preferences.blp:150
#: data/gtk/preferences.blp:158
msgid "Import Flatpak Games"
msgstr "Flatpak கேம்களை இறக்குமதி செய்யவும்"
#: data/gtk/preferences.blp:160
#: data/gtk/preferences.blp:168
msgid "Heroic"
msgstr "Heroic"
#: data/gtk/preferences.blp:173
#: data/gtk/preferences.blp:184
msgid "Import Epic Games"
msgstr "Epic விளையாட்டுகளை இறக்குமதி செய்"
#: data/gtk/preferences.blp:182
#: data/gtk/preferences.blp:193
msgid "Import GOG Games"
msgstr "GOG விளையாட்டுகளை இறக்குமதி செய்யவும்"
#: data/gtk/preferences.blp:191
#: data/gtk/preferences.blp:202
msgid "Import Amazon Games"
msgstr "Amazon விளையாட்டுகளை இறக்குமதி செய்யவும்"
#: data/gtk/preferences.blp:200
#: data/gtk/preferences.blp:211
msgid "Import Sideloaded Games"
msgstr "பக்க ஏற்றப்பட்ட விளையாட்டுகளை இறக்குமதி செய்யவும்"
#: data/gtk/preferences.blp:210
#: data/gtk/preferences.blp:221
msgid "Bottles"
msgstr "பாட்டில்கள்"
#: data/gtk/preferences.blp:224
#: data/gtk/preferences.blp:238
msgid "itch"
msgstr "itch"
#: data/gtk/preferences.blp:238
#: data/gtk/preferences.blp:255
msgid "Legendary"
msgstr "Legendary"
#: data/gtk/preferences.blp:252
#: data/gtk/preferences.blp:272
msgid "RetroArch"
msgstr "RetroArch"
#: data/gtk/preferences.blp:266
#: data/gtk/preferences.blp:289
msgid "Flatpak"
msgstr "Flatpak"
#: data/gtk/preferences.blp:279
#: data/gtk/preferences.blp:305
msgid "Import Game Launchers"
msgstr "விளையாட்டு துவக்கிகளை இறக்குமதி செய்"
#: data/gtk/preferences.blp:292
#: data/gtk/preferences.blp:315
msgid "Desktop Entries"
msgstr "டெஸ்க்டாப் உள்ளீடுகள்"
#: data/gtk/preferences.blp:327
msgid "SteamGridDB"
msgstr "SteamGridDB"
#: data/gtk/preferences.blp:296
#: data/gtk/preferences.blp:331
msgid "Authentication"
msgstr "அங்கீகாரம்"
#: data/gtk/preferences.blp:299
#: data/gtk/preferences.blp:334
msgid "API Key"
msgstr "API விசை"
#: data/gtk/preferences.blp:307
#: data/gtk/preferences.blp:342
msgid "Use SteamGridDB"
msgstr "SteamGridDB ஐப் பயன்படுத்தவும்"
#: data/gtk/preferences.blp:308
#: data/gtk/preferences.blp:343
msgid "Download images when adding or importing games"
msgstr ""
"விளையாட்டுகளைச் சேர்க்கும் போது அல்லது இறக்குமதி செய்யும் போது படங்களைப் பதிவிறக்கவும்"
#: data/gtk/preferences.blp:317
#: data/gtk/preferences.blp:352
msgid "Prefer Over Official Images"
msgstr "அதிகாரப்பூர்வ படங்களை விட முன்னுரிமை"
#: data/gtk/preferences.blp:326
#: data/gtk/preferences.blp:361
msgid "Prefer Animated Images"
msgstr "இயங்குபடம் செய்யப்பட்ட படங்களுக்கு முன்னுரிமை கொடுங்கள்"
@@ -343,7 +349,7 @@ msgstr "மறைக்கப்பட்ட விளையாட்டுக
msgid "Games you hide will appear here."
msgstr "நீங்கள் மறைக்கும் விளையாட்டுகள் இங்கே தோன்றும்."
#: data/gtk/window.blp:64 data/gtk/window.blp:305
#: data/gtk/window.blp:64 data/gtk/window.blp:317
msgid "Back"
msgstr "மீண்டும்"
@@ -355,114 +361,118 @@ msgstr "விளையாட்டு தலைப்பு"
msgid "Play"
msgstr "விளையாடு"
#: data/gtk/window.blp:243 data/gtk/window.blp:437
#: data/gtk/window.blp:255 data/gtk/window.blp:449
msgid "Add Game"
msgstr "விளையாட்டைச் சேர்க்கவும்"
#: data/gtk/window.blp:250 data/gtk/window.blp:317
#: data/gtk/window.blp:262 data/gtk/window.blp:329
msgid "Main Menu"
msgstr "முதன்மை பட்டியல்"
#: data/gtk/window.blp:272
#: data/gtk/window.blp:284
msgid "Search games"
msgstr "விளையாட்டுகளைத் தேடுங்கள்"
#: data/gtk/window.blp:312
#: data/gtk/window.blp:324
msgid "Hidden Games"
msgstr "மறைக்கப்பட்ட விளையாட்டுகள்"
#: data/gtk/window.blp:339
#: data/gtk/window.blp:351
msgid "Search hidden games"
msgstr "மறைக்கப்பட்ட விளையாட்டுகளைத் தேடுங்கள்"
#: data/gtk/window.blp:376
#: data/gtk/window.blp:388
msgid "Sort"
msgstr "வகைபடுத்து"
#: data/gtk/window.blp:379
#: data/gtk/window.blp:391
msgid "A-Z"
msgstr "A-Z"
#: data/gtk/window.blp:385
#: data/gtk/window.blp:397
msgid "Z-A"
msgstr "Z-A"
#: data/gtk/window.blp:391
#: data/gtk/window.blp:403
msgid "Newest"
msgstr "புதியது"
#: data/gtk/window.blp:397
#: data/gtk/window.blp:409
msgid "Oldest"
msgstr "பழமையானது"
#: data/gtk/window.blp:403
#: data/gtk/window.blp:415
msgid "Last Played"
msgstr "கடைசியாக விளையாடியது"
#: data/gtk/window.blp:410
#: data/gtk/window.blp:422
msgid "Show Hidden"
msgstr "மறைக்கப்பட்டதைக் காட்டு"
#: data/gtk/window.blp:423
#: data/gtk/window.blp:435
msgid "Keyboard Shortcuts"
msgstr "விசைப்பலகை குறுக்குவழிகள்"
#: data/gtk/window.blp:428
#: data/gtk/window.blp:440
msgid "About Cartridges"
msgstr "கார்ட்ரிட்ஜ்கள் பற்றி"
#. Translators: Replace this with your name for it to show up in the about window
#: src/main.py:188
#: src/main.py:195
msgid "translator_credits"
msgstr "K.B.Dharun Krishna <kbdharunkrishna@gmail.com>"
#. The variable is the date when the game was added
#: src/window.py:194
#: src/window.py:213
msgid "Added: {}"
msgstr "சேர்க்கப்பட்டது: {}"
#: src/window.py:197
#: src/window.py:216
msgid "Never"
msgstr "ஒருபோதும் இல்லை"
#. The variable is the date when the game was last played
#: src/window.py:201
#: src/window.py:220
msgid "Last played: {}"
msgstr "கடைசியாக விளையாடியது: {}"
#: src/details_window.py:72
#: src/details_window.py:76
msgid "Apply"
msgstr "விண்ணப்பி"
#: src/details_window.py:78
#: src/details_window.py:82
msgid "Add New Game"
msgstr "புதிய விளையாட்டைச் சேர்க்கவும்"
#: src/details_window.py:79
#: src/details_window.py:83
msgid "Add"
msgstr "சேர்"
#: src/details_window.py:93
msgid "Executables"
msgstr "செயல்படுத்தக்கூடியவை"
#. Translate this string as you would translate "file"
#: src/details_window.py:92
#: src/details_window.py:108
msgid "file.txt"
msgstr "கோப்பு.txt"
#. As in software
#: src/details_window.py:94
#: src/details_window.py:110
msgid "program"
msgstr "பயன்பாடு"
#. Translate this string as you would translate "path to {}"
#: src/details_window.py:99 src/details_window.py:101
#: src/details_window.py:115 src/details_window.py:117
msgid "C:\\path\\to\\{}"
msgstr "C:\\பாதை\\டு \\{}"
#. Translate this string as you would translate "path to {}"
#: src/details_window.py:105 src/details_window.py:107
#: src/details_window.py:121 src/details_window.py:123
msgid "/path/to/{}"
msgstr "/பாதை/டு/ {}"
#: src/details_window.py:112
#: src/details_window.py:128
msgid ""
"To launch the executable \"{}\", use the command:\n"
"\n"
@@ -484,102 +494,100 @@ msgstr ""
"\n"
"பாதையில் இடைவெளிகள் இருந்தால், அதை இரட்டை மேற்கோள்களில் போர்த்துவதை உறுதிசெய்யவும்!"
#: src/details_window.py:147 src/details_window.py:153
#: src/details_window.py:171 src/details_window.py:177
msgid "Couldn't Add Game"
msgstr "விளையாட்டைச் சேர்க்க முடியவில்லை"
#: src/details_window.py:147 src/details_window.py:183
#: src/details_window.py:171 src/details_window.py:207
msgid "Game title cannot be empty."
msgstr "விளையாட்டு தலைப்பு காலியாக இருக்கக்கூடாது."
#: src/details_window.py:153 src/details_window.py:191
#: src/details_window.py:177 src/details_window.py:215
msgid "Executable cannot be empty."
msgstr "இயங்கக்கூடியது காலியாக இருக்க முடியாது."
#: src/details_window.py:182 src/details_window.py:190
#: src/details_window.py:206 src/details_window.py:214
msgid "Couldn't Apply Preferences"
msgstr "விருப்பங்களைப் பயன்படுத்த முடியவில்லை"
#. The variable is the title of the game
#: src/game.py:139
#: src/game.py:141
msgid "{} launched"
msgstr "{} தொடங்கப்பட்டது"
#. The variable is the title of the game
#: src/game.py:153
#: src/game.py:155
msgid "{} hidden"
msgstr "{} மறைக்கப்பட்டுள்ளது"
#: src/game.py:153
#: src/game.py:155
msgid "{} unhidden"
msgstr "{} மறைக்கப்படாதது"
#. The variable is the title of the game
#. The variable is the number of games removed
#: src/game.py:170 src/importer/importer.py:363
#: src/game.py:172 src/importer/importer.py:373
msgid "{} removed"
msgstr "{} அகற்றப்பட்டது"
#: src/preferences.py:119
#: src/preferences.py:123
msgid "All games removed"
msgstr "அனைத்து விளையாட்டுகளும் அகற்றப்பட்டன"
#: src/preferences.py:168
#: src/preferences.py:172
msgid ""
"An API key is required to use SteamGridDB. You can generate one {}here{}."
msgstr "SteamGridDB ஐப் பயன்படுத்த API விசை தேவை. நீங்கள் ஒன்றை {}இங்கே{} உருவாக்கலாம்."
#: src/preferences.py:294
#: src/preferences.py:293
msgid "Installation Not Found"
msgstr "நிறுவல் கிடைக்கவில்லை"
#: src/preferences.py:296
#: src/preferences.py:294
msgid "Select a valid directory."
msgstr "சரியான கோப்பகத்தைத் தேர்ந்தெடுக்கவும்."
#: src/preferences.py:351
#: src/preferences.py:330 src/importer/importer.py:299
msgid "Warning"
msgstr "எச்சரிக்கை"
#: src/preferences.py:364
msgid "Invalid Directory"
msgstr "தவறான கோப்பகம்"
#: src/preferences.py:357
#: src/preferences.py:370
msgid "Set Location"
msgstr "இருப்பிடத்தை அமைக்கவும்"
#: src/utils/create_dialog.py:25 src/importer/importer.py:291
#: src/utils/create_dialog.py:33 src/importer/importer.py:300
msgid "Dismiss"
msgstr "நிராகரி"
#: src/importer/importer.py:128
#: src/importer/importer.py:137
msgid "Importing Games…"
msgstr "விளையாட்டுகளை இறக்குமதி செய்கிறது…"
#: src/importer/importer.py:290
msgid "Warning"
msgstr ""
#: src/importer/importer.py:311
#: src/importer/importer.py:320
msgid "The following errors occured during import:"
msgstr ""
msgstr "இறக்குமதியின் போது பின்வரும் பிழைகள் ஏற்பட்டன:"
#: src/importer/importer.py:339
#: src/importer/importer.py:349
msgid "No new games found"
msgstr "புதிய விளையாட்டுகள் எதுவும் கண்டறியப்படவில்லை"
#: src/importer/importer.py:351
#: src/importer/importer.py:361
msgid "1 game imported"
msgstr "1 விளையாட்டு இறக்குமதி செய்யப்பட்டது"
#. The variable is the number of games
#: src/importer/importer.py:355
#: src/importer/importer.py:365
msgid "{} games imported"
msgstr "{} விளையாட்டுகள் இறக்குமதி செய்யப்பட்டன"
#. A single game removed
#: src/importer/importer.py:359
#, fuzzy
#| msgid "{} removed"
#: src/importer/importer.py:369
msgid "1 removed"
msgstr "{} அகற்றப்பட்டது"
msgstr "1 அகற்றப்பட்டது"
#. The variable is the name of the source
#: src/importer/sources/location.py:33

View File

@@ -18,19 +18,22 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import os
import shlex
from pathlib import Path
from time import time
from typing import Any, Optional
from gi.repository import Adw, Gio, GLib, Gtk
from PIL import Image
from PIL import Image, UnidentifiedImageError
from src import shared
from src.errors.friendly_error import FriendlyError
from src.game import Game
from src.game_cover import GameCover
from src.store.managers.cover_manager import CoverManager
from src.store.managers.sgdb_manager import SGDBManager
from src.utils.create_dialog import create_dialog
from src.utils.save_cover import resize_cover, save_cover
from src.utils.save_cover import convert_cover, save_cover
@Gtk.Template(resource_path=shared.PREFIX + "/gtk/details-window.ui")
@@ -50,6 +53,7 @@ class DetailsWindow(Adw.Window):
exec_info_label = Gtk.Template.Child()
exec_info_popover = Gtk.Template.Child()
file_chooser_button = Gtk.Template.Child()
apply_button = Gtk.Template.Child()
@@ -83,10 +87,22 @@ class DetailsWindow(Adw.Window):
image_filter.add_suffix(extension[1:])
image_filter.add_suffix("svg") # Gdk.Texture supports .svg but PIL doesn't
file_filters = Gio.ListStore.new(Gtk.FileFilter)
file_filters.append(image_filter)
self.file_dialog = Gtk.FileDialog()
self.file_dialog.set_filters(file_filters)
image_filters = Gio.ListStore.new(Gtk.FileFilter)
image_filters.append(image_filter)
exec_filter = Gtk.FileFilter(name=_("Executables"))
exec_filter.add_mime_type("application/x-executable")
exec_filters = Gio.ListStore.new(Gtk.FileFilter)
exec_filters.append(exec_filter)
self.image_file_dialog = Gtk.FileDialog()
self.image_file_dialog.set_filters(image_filters)
self.image_file_dialog.set_default_filter(image_filter)
self.exec_file_dialog = Gtk.FileDialog()
self.exec_file_dialog.set_filters(exec_filters)
self.exec_file_dialog.set_default_filter(exec_filter)
# Translate this string as you would translate "file"
file_name = _("file.txt")
@@ -128,6 +144,7 @@ class DetailsWindow(Adw.Window):
self.cover_button_delete.connect("clicked", self.delete_pixbuf)
self.cover_button_edit.connect("clicked", self.choose_cover)
self.file_chooser_button.connect("clicked", self.choose_executable)
self.apply_button.connect("clicked", self.apply_preferences)
self.name.connect("entry-activated", self.focus_executable)
@@ -262,19 +279,47 @@ class DetailsWindow(Adw.Window):
def set_cover(self, _source: Any, result: Gio.Task, *_args: Any) -> None:
try:
path = self.file_dialog.open_finish(result).get_path()
path = self.image_file_dialog.open_finish(result).get_path()
except GLib.GError:
return
def resize() -> None:
if cover := resize_cover(path):
self.game_cover.new_cover(cover)
def thread_func() -> None:
new_path = None
try:
with Image.open(path) as image:
if getattr(image, "is_animated", False):
new_path = convert_cover(path)
except UnidentifiedImageError:
pass
if not new_path:
new_path = convert_cover(
pixbuf=shared.store.managers[CoverManager].composite_cover(
Path(path)
)
)
if new_path:
self.game_cover.new_cover(new_path)
self.cover_button_delete_revealer.set_reveal_child(True)
self.cover_changed = True
self.toggle_loading()
self.toggle_loading()
GLib.Thread.new(None, resize)
GLib.Thread.new(None, thread_func)
def set_executable(self, _source: Any, result: Gio.Task, *_args: Any) -> None:
try:
path = self.exec_file_dialog.open_finish(result).get_path()
except GLib.GError:
return
self.executable.set_text(shlex.quote(path))
def choose_executable(self, *_args: Any) -> None:
self.exec_file_dialog.open(self, None, self.set_executable)
def choose_cover(self, *_args: Any) -> None:
self.file_dialog.open(self, None, self.set_cover)
self.image_file_dialog.open(self, None, self.set_cover)

View File

@@ -18,7 +18,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from pathlib import Path
from typing import Any, Callable, Optional
from typing import Optional
from gi.repository import Gdk, GdkPixbuf, Gio, GLib, Gtk
from PIL import Image, ImageFilter, ImageStat
@@ -45,16 +45,6 @@ class GameCover:
self.pictures = pictures
self.new_cover(path)
# Wrap the function in another one as Gio.Task.run_in_thread does not allow for passing args
def create_func(self, path: Optional[Path]) -> Callable:
self.animation = GdkPixbuf.PixbufAnimation.new_from_file(str(path))
self.anim_iter = self.animation.get_iter()
def wrapper(task: Gio.Task, *_args: Any) -> None:
self.update_animation((task, self.animation))
return wrapper
def new_cover(self, path: Optional[Path] = None) -> None:
self.animation = None
self.texture = None
@@ -64,8 +54,12 @@ class GameCover:
if path:
if path.suffix == ".gif":
self.animation = GdkPixbuf.PixbufAnimation.new_from_file(str(path))
self.anim_iter = self.animation.get_iter()
self.task = Gio.Task.new()
self.task.run_in_thread(self.create_func(self.path))
self.task.run_in_thread(
lambda *_: self.update_animation((self.task, self.animation))
)
else:
self.texture = Gdk.Texture.new_from_filename(str(path))

View File

@@ -19,9 +19,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
from time import time
from typing import Any, Optional
from gi.repository import Adw, GLib, Gtk
from gi.repository import Adw, Gio, GLib, Gtk
from src import shared
from src.errors.error_producer import ErrorProducer
@@ -31,7 +32,6 @@ from src.importer.sources.location import UnresolvableLocationError
from src.importer.sources.source import Source
from src.store.managers.async_manager import AsyncManager
from src.store.pipeline import Pipeline
from src.utils.task import Task
# pylint: disable=too-many-instance-attributes
@@ -56,6 +56,8 @@ class Importer(ErrorProducer):
def __init__(self) -> None:
super().__init__()
shared.import_time = int(time())
# TODO: make this stateful
shared.store.new_game_ids = set()
shared.store.duplicate_game_ids = set()
@@ -103,8 +105,8 @@ class Importer(ErrorProducer):
def run(self) -> None:
"""Use several Gio.Task to import games from added sources"""
if Importer.summary_toast:
Importer.summary_toast.dismiss()
if self.__class__.summary_toast:
self.__class__.summary_toast.dismiss()
shared.win.get_application().lookup_action("import").set_enabled(False)
@@ -121,10 +123,13 @@ class Importer(ErrorProducer):
for source in self.sources:
logging.debug("Importing games from source %s", source.source_id)
task = Task.new(None, None, self.source_callback, (source,))
task = Gio.Task.new(None, None, self.source_callback, (source,))
self.n_source_tasks_created += 1
task.set_task_data((source,))
task.run_in_thread(self.source_task_thread_func)
task.run_in_thread(
lambda _task, _obj, _data, _cancellable, src=source: self.source_task_thread_func(
(src,)
)
)
self.progress_changed_callback()
@@ -145,9 +150,7 @@ class Importer(ErrorProducer):
)
self.import_dialog.present()
def source_task_thread_func(
self, _task: Any, _obj: Any, data: tuple, _cancellable: Any
) -> None:
def source_task_thread_func(self, data: tuple) -> None:
"""Source import task code"""
source: Source
@@ -266,7 +269,7 @@ class Importer(ErrorProducer):
shared.store.new_game_ids = set()
shared.store.duplicate_game_ids = set()
self.import_dialog.close()
Importer.summary_toast = self.create_summary_toast()
self.__class__.summary_toast = self.create_summary_toast()
self.create_error_dialog()
shared.win.get_application().lookup_action("import").set_enabled(True)
@@ -335,8 +338,8 @@ class Importer(ErrorProducer):
self.imported_game_ids = set()
self.removed_game_ids = set()
if Importer.summary_toast:
Importer.summary_toast.dismiss()
if self.__class__.summary_toast:
self.__class__.summary_toast.dismiss()
logging.info("Import undone")
@@ -392,8 +395,8 @@ class Importer(ErrorProducer):
def timeout_toast(self, *_args: Any) -> None:
"""Manually timeout the toast after the user has dismissed all warnings"""
if Importer.summary_toast:
GLib.timeout_add_seconds(5, Importer.summary_toast.dismiss)
if self.__class__.summary_toast:
GLib.timeout_add_seconds(5, self.__class__.summary_toast.dismiss)
def dialog_response_callback(self, _widget: Any, response: str, *args: Any) -> None:
"""Handle after-import dialogs callback"""

View File

@@ -19,7 +19,6 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from pathlib import Path
from time import time
from typing import NamedTuple
import yaml
@@ -38,17 +37,17 @@ class BottlesSourceIterable(SourceIterable):
data = self.source.locations.data["library.yml"].read_text("utf-8")
library: dict = yaml.safe_load(data)
added_time = int(time())
for entry in library.values():
# Build game
values = {
"source": self.source.source_id,
"added": added_time,
"added": shared.import_time,
"name": entry["name"],
"game_id": self.source.game_id_format.format(game_id=entry["id"]),
"executable": self.source.executable_format.format(
bottle_name=entry["bottle"]["name"], game_name=entry["name"]
"executable": self.source.make_executable(
bottle_name=entry["bottle"]["name"],
game_name=entry["name"],
),
}
game = Game(values)
@@ -73,7 +72,6 @@ class BottlesSourceIterable(SourceIterable):
image_path = bottles_location / bottle_path / "grids" / image_name
additional_data = {"local_image_path": image_path}
# Produce game
yield (game, additional_data)

View File

@@ -0,0 +1,204 @@
# desktop_source.py
#
# Copyright 2023 kramo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later
import os
import shlex
import subprocess
from pathlib import Path
from typing import NamedTuple
from gi.repository import GLib, Gtk
from src import shared
from src.game import Game
from src.importer.sources.source import Source, SourceIterable
class DesktopSourceIterable(SourceIterable):
source: "DesktopSource"
def __iter__(self):
"""Generator method producing games"""
icon_theme = Gtk.IconTheme.new()
search_paths = [
shared.home / ".local" / "share",
"/run/host/usr/local/share",
"/run/host/usr/share",
"/run/host/usr/share/pixmaps",
"/usr/share/pixmaps",
] + GLib.get_system_data_dirs()
for search_path in search_paths:
path = Path(search_path)
if not str(search_path).endswith("/pixmaps"):
path = path / "icons"
if not path.is_dir():
continue
if str(path).startswith("/app/"):
continue
icon_theme.add_search_path(str(path))
launch_command, full_path = self.check_launch_command()
for path in search_paths:
if str(path).startswith("/app/"):
continue
path = Path(path) / "applications"
if not path.is_dir():
continue
for entry in path.iterdir():
if entry.suffix != ".desktop":
continue
# Skip Lutris games
if str(entry.name).startswith("net.lutris."):
continue
keyfile = GLib.KeyFile.new()
try:
keyfile.load_from_file(str(entry), 0)
if "Game" not in keyfile.get_string_list(
"Desktop Entry", "Categories"
):
continue
name = keyfile.get_string("Desktop Entry", "Name")
executable = keyfile.get_string("Desktop Entry", "Exec").split(
" %"
)[0]
except GLib.GError:
continue
# Skip Steam games
if "steam://rungameid/" in executable:
continue
# Skip Heroic games
if "heroic://launch/" in executable:
continue
# Skip Bottles games
if "bottles-cli " in executable:
continue
try:
if keyfile.get_boolean("Desktop Entry", "NoDisplay"):
continue
except GLib.GError:
pass
# Strip /run/host from Flatpak paths
if entry.is_relative_to(prefix := "/run/host"):
entry = Path("/") / entry.relative_to(prefix)
launch_arg = shlex.quote(str(entry if full_path else entry.stem))
values = {
"source": self.source.source_id,
"added": shared.import_time,
"name": name,
"game_id": f"desktop_{entry.stem}",
"executable": f"{launch_command} {launch_arg}",
}
game = Game(values)
additional_data = {}
try:
icon_str = keyfile.get_string("Desktop Entry", "Icon")
except GLib.GError:
yield game
continue
else:
if "/" in icon_str:
additional_data = {"local_icon_path": Path(icon_str)}
yield (game, additional_data)
continue
try:
if (
icon_path := icon_theme.lookup_icon(
icon_str,
None,
512,
1,
shared.win.get_direction(),
0,
)
.get_file()
.get_path()
):
additional_data = {"local_icon_path": Path(icon_path)}
except GLib.GError:
pass
yield (game, additional_data)
def check_launch_command(self) -> (str, bool):
"""Check whether `gio launch` `gtk4-launch` or `gtk-launch` are available on the system"""
commands = (("gio launch", True), ("gtk4-launch", False), ("gtk-launch", False))
flatpak_str = "flatpak-spawn --host /bin/sh -c "
for command, full_path in commands:
# Even if `gio` is available, `gio launch` is only available on GLib >= 2.67.2
check_command = (
"gio help launch"
if command == "gio launch"
else f"type {command} &> /dev/null"
)
if os.getenv("FLATPAK_ID") == shared.APP_ID:
check_command = flatpak_str + shlex.quote(check_command)
try:
subprocess.run(check_command, shell=True, check=True)
return command, full_path
except subprocess.CalledProcessError:
pass
return commands[2]
class DesktopLocations(NamedTuple):
pass
class DesktopSource(Source):
"""Generic Flatpak source"""
source_id = "desktop"
name = _("Desktop")
iterable_class = DesktopSourceIterable
available_on = {"linux"}
locations: DesktopLocations
def __init__(self) -> None:
super().__init__()
self.locations = DesktopLocations()

View File

@@ -18,7 +18,6 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from pathlib import Path
from time import time
from typing import NamedTuple
from gi.repository import GLib, Gtk
@@ -35,8 +34,6 @@ class FlatpakSourceIterable(SourceIterable):
def __iter__(self):
"""Generator method producing games"""
added_time = int(time())
icon_theme = Gtk.IconTheme.new()
icon_theme.add_search_path(str(self.source.locations.data["icons"]))
@@ -51,6 +48,7 @@ class FlatpakSourceIterable(SourceIterable):
"com.heroicgameslauncher.hgl",
"com.usebottles.Bottles",
"io.itch.itch",
"org.libretro.RetroArch",
}
)
@@ -78,12 +76,10 @@ class FlatpakSourceIterable(SourceIterable):
values = {
"source": self.source.source_id,
"added": added_time,
"added": shared.import_time,
"name": name,
"game_id": self.source.game_id_format.format(game_id=flatpak_id),
"executable": self.source.executable_format.format(
flatpak_id=flatpak_id
),
"executable": self.source.make_executable(flatpak_id=flatpak_id),
}
game = Game(values)
@@ -108,7 +104,6 @@ class FlatpakSourceIterable(SourceIterable):
except GLib.GError:
pass
# Produce game
yield (game, additional_data)

View File

@@ -25,7 +25,6 @@ from functools import cached_property
from hashlib import sha256
from json import JSONDecodeError
from pathlib import Path
from time import time
from typing import Iterable, NamedTuple, Optional, TypedDict
from src import shared
@@ -91,9 +90,7 @@ class SubSourceIterable(Iterable):
logging.debug("Using Heroic %s library.json path %s", self.name, path)
return path
def process_library_entry(
self, entry: HeroicLibraryEntry, added_time: int
) -> SourceIterationResult:
def process_library_entry(self, entry: HeroicLibraryEntry) -> SourceIterationResult:
"""Build a Game from a Heroic library entry"""
app_name = entry["app_name"]
@@ -102,15 +99,13 @@ class SubSourceIterable(Iterable):
# Build game
values = {
"source": f"{self.source.source_id}_{self.service}",
"added": added_time,
"added": shared.import_time,
"name": entry["title"],
"developer": entry.get("developer", None),
"game_id": self.source.game_id_format.format(
service=self.service, game_id=app_name
),
"executable": self.source.executable_format.format(
runner=runner, app_name=app_name
),
"executable": self.source.make_executable(runner=runner, app_name=app_name),
"hidden": self.source_iterable.is_hidden(app_name),
}
game = Game(values)
@@ -129,7 +124,7 @@ class SubSourceIterable(Iterable):
Iterate through the games with a generator
:raises InvalidLibraryFileError: on initial call if the library file is bad
"""
added_time = int(time())
try:
iterator = iter(
path_json_load(self.library_path)[self.library_json_entries_key]
@@ -140,7 +135,7 @@ class SubSourceIterable(Iterable):
) from error
for entry in iterator:
try:
yield self.process_library_entry(entry, added_time)
yield self.process_library_entry(entry)
except KeyError as error:
logging.warning(
"Skipped invalid %s game %s",
@@ -178,7 +173,7 @@ class StoreSubSourceIterable(SubSourceIterable):
def is_installed(self, app_name: str) -> bool:
return app_name in self.installed_app_names
def process_library_entry(self, entry, added_time):
def process_library_entry(self, entry):
# Skip games that are not installed
app_name = entry["app_name"]
if not self.is_installed(app_name):
@@ -190,7 +185,7 @@ class StoreSubSourceIterable(SubSourceIterable):
)
return None
# Process entry as normal
return super().process_library_entry(entry, added_time)
return super().process_library_entry(entry)
def __iter__(self):
"""

View File

@@ -20,7 +20,6 @@
from shutil import rmtree
from sqlite3 import connect
from time import time
from typing import NamedTuple
from src import shared
@@ -56,16 +55,14 @@ class ItchSourceIterable(SourceIterable):
connection = connect(db_path)
cursor = connection.execute(db_request)
added_time = int(time())
# Create games from the db results
for row in cursor:
values = {
"added": added_time,
"added": shared.import_time,
"source": self.source.source_id,
"name": row[1],
"game_id": self.source.game_id_format.format(game_id=row[0]),
"executable": self.source.executable_format.format(cave_id=row[4]),
"executable": self.source.make_executable(cave_id=row[4]),
}
additional_data = {"online_cover_url": row[3] or row[2]}
game = Game(values)

View File

@@ -20,7 +20,6 @@
import json
import logging
from json import JSONDecodeError
from time import time
from typing import NamedTuple
from src import shared
@@ -28,17 +27,15 @@ from src.game import Game
from src.importer.sources.location import Location, LocationSubPath
from src.importer.sources.source import (
ExecutableFormatSource,
SourceIterationResult,
SourceIterable,
SourceIterationResult,
)
class LegendarySourceIterable(SourceIterable):
source: "LegendarySource"
def game_from_library_entry(
self, entry: dict, added_time: int
) -> SourceIterationResult:
def game_from_library_entry(self, entry: dict) -> SourceIterationResult:
# Skip non-games
if entry["is_dlc"]:
return None
@@ -46,11 +43,11 @@ class LegendarySourceIterable(SourceIterable):
# Build game
app_name = entry["app_name"]
values = {
"added": added_time,
"added": shared.import_time,
"source": self.source.source_id,
"name": entry["title"],
"game_id": self.source.game_id_format.format(game_id=app_name),
"executable": self.source.executable_format.format(app_name=app_name),
"executable": self.source.make_executable(app_name=app_name),
}
data = {}
@@ -78,12 +75,10 @@ class LegendarySourceIterable(SourceIterable):
logging.warning("Couldn't open Legendary file: %s", str(file))
return
added_time = int(time())
# Generate games from library
for entry in library.values():
try:
result = self.game_from_library_entry(entry, added_time)
result = self.game_from_library_entry(entry)
except KeyError as error:
# Skip invalid games
logging.warning(

View File

@@ -19,7 +19,6 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from shutil import rmtree
from sqlite3 import connect
from time import time
from typing import NamedTuple
from src import shared
@@ -56,20 +55,18 @@ class LutrisSourceIterable(SourceIterable):
connection = connect(db_path)
cursor = connection.execute(request, params)
added_time = int(time())
# Create games from the DB results
for row in cursor:
# Create game
values = {
"added": added_time,
"added": shared.import_time,
"hidden": row[4],
"name": row[1],
"source": f"{self.source.source_id}_{row[3]}",
"game_id": self.source.game_id_format.format(
runner=row[3], game_id=row[0]
),
"executable": self.source.executable_format.format(game_id=row[0]),
"executable": self.source.make_executable(game_id=row[0]),
}
game = Game(values)
@@ -77,7 +74,6 @@ class LutrisSourceIterable(SourceIterable):
image_path = self.source.locations.cache["coverart"] / f"{row[2]}.jpg"
additional_data = {"local_image_path": image_path}
# Produce game
yield (game, additional_data)
# Cleanup

View File

@@ -24,9 +24,7 @@ from hashlib import md5
from json import JSONDecodeError
from pathlib import Path
from shlex import quote as shell_quote
from time import time
from typing import NamedTuple
from urllib.parse import quote as url_quote
from src import shared
from src.errors.friendly_error import FriendlyError
@@ -54,7 +52,6 @@ class RetroarchSourceIterable(SourceIterable):
raise KeyError(f"Key not found in RetroArch config: {key}")
def __iter__(self):
added_time = int(time())
bad_playlists = set()
config_file = self.source.locations.config["retroarch.cfg"]
@@ -102,7 +99,7 @@ class RetroarchSourceIterable(SourceIterable):
values = {
"source": self.source.source_id,
"added": added_time,
"added": shared.import_time,
"name": item["label"],
"game_id": self.source.game_id_format.format(game_id=game_id),
"executable": self.source.make_executable(

View File

@@ -78,7 +78,6 @@ class Source(Iterable):
def is_available(self) -> bool:
return sys.platform in self.available_on
@abstractmethod
def make_executable(self, *args, **kwargs) -> str:
"""
Create a game executable command.
@@ -105,7 +104,7 @@ class ExecutableFormatSource(Source):
def make_executable(self, *args, **kwargs) -> str:
"""Use the executable format to"""
return self.executable_format.format(args, kwargs)
return self.executable_format.format(*args, **kwargs)
# pylint: disable=abstract-method

View File

@@ -21,7 +21,6 @@
import logging
import re
from pathlib import Path
from time import time
from typing import Iterable, NamedTuple
from src import shared
@@ -64,8 +63,6 @@ class SteamSourceIterable(SourceIterable):
appid_cache = set()
manifests = self.get_manifests()
added_time = int(time())
for manifest in manifests:
# Get metadata from manifest
steam = SteamFileHelper()
@@ -90,11 +87,11 @@ class SteamSourceIterable(SourceIterable):
# Build game from local data
values = {
"added": added_time,
"added": shared.import_time,
"name": local_data["name"],
"source": self.source.source_id,
"game_id": self.source.game_id_format.format(game_id=appid),
"executable": self.source.executable_format.format(game_id=appid),
"executable": self.source.make_executable(game_id=appid),
}
game = Game(values)
@@ -105,7 +102,6 @@ class SteamSourceIterable(SourceIterable):
)
additional_data = {"local_image_path": image_path, "steam_appid": appid}
# Produce game
yield (game, additional_data)

View File

@@ -89,18 +89,24 @@ class SessionFileHandler(StreamHandler):
# If uncompressed, compress
if not path.name.endswith(".xz"):
try:
with open(path, "r", encoding="utf-8") as original_file:
original_data = original_file.read()
except UnicodeDecodeError:
# If the file is corrupted, throw it away
path.unlink()
return
# Compress the file
compressed_path = path.with_suffix(path.suffix + ".xz")
with (
lzma.open(
compressed_path,
"wt",
format=FORMAT_XZ,
preset=PRESET_DEFAULT,
encoding="utf-8",
) as lzma_file,
open(path, "r", encoding="utf-8") as original_file,
):
lzma_file.write(original_file.read())
with lzma.open(
compressed_path,
"wt",
format=FORMAT_XZ,
preset=PRESET_DEFAULT,
encoding="utf-8",
) as lzma_file:
lzma_file.write(original_data)
path.unlink()
path = compressed_path

View File

@@ -20,6 +20,8 @@
import json
import lzma
import os
import shlex
import subprocess
import sys
from typing import Any, Optional
@@ -36,6 +38,7 @@ from src.details_window import DetailsWindow
from src.game import Game
from src.importer.importer import Importer
from src.importer.sources.bottles_source import BottlesSource
from src.importer.sources.desktop_source import DesktopSource
from src.importer.sources.flatpak_source import FlatpakSource
from src.importer.sources.heroic_source import HeroicSource
from src.importer.sources.itch_source import ItchSource
@@ -155,9 +158,9 @@ class CartridgesApplication(Adw.Application):
def on_about_action(self, *_args: Any) -> None:
# Get the debug info from the log files
debug_str = ""
for i, path in enumerate(shared.log_files):
for index, path in enumerate(shared.log_files):
# Add a horizontal line between runs
if i > 0:
if index > 0:
debug_str += "" * 37 + "\n"
# Add the run's logs
log_file = (
@@ -241,6 +244,9 @@ class CartridgesApplication(Adw.Application):
if shared.schema.get_boolean("flatpak"):
shared.importer.add_source(FlatpakSource())
if shared.schema.get_boolean("desktop"):
shared.importer.add_source(DesktopSource())
if shared.schema.get_boolean("itch"):
shared.importer.add_source(ItchSource())

View File

@@ -97,6 +97,8 @@ class PreferencesWindow(Adw.PreferencesWindow):
flatpak_data_file_chooser_button = Gtk.Template.Child()
flatpak_import_launchers_switch = Gtk.Template.Child()
desktop_switch = Gtk.Template.Child()
sgdb_key_group = Gtk.Template.Child()
sgdb_key_entry_row = Gtk.Template.Child()
sgdb_switch = Gtk.Template.Child()
@@ -199,6 +201,7 @@ class PreferencesWindow(Adw.PreferencesWindow):
"sgdb",
"sgdb-prefer",
"sgdb-animated",
"desktop",
}
)
@@ -276,9 +279,6 @@ class PreferencesWindow(Adw.PreferencesWindow):
def resolve_locations(self, source: Source) -> None:
"""Resolve locations and add a warning if location cannot be found"""
def clear_warning_selection(_widget: Any, label: Gtk.Label) -> None:
label.select_region(-1, -1)
for location_name, location in source.locations._asdict().items():
action_row = getattr(
self, f"{source.source_id}_{location_name}_action_row", None
@@ -290,15 +290,16 @@ class PreferencesWindow(Adw.PreferencesWindow):
location.resolve()
except UnresolvableLocationError:
title = _("Installation Not Found")
description = _("Select a valid directory.")
format_start = '<span rise="12pt"><b><big>'
format_end = "</big></b></span>\n"
popover = Gtk.Popover(
focusable=True,
child=(
label := Gtk.Label(
label=(
'<span rise="12pt"><b><big>'
+ _("Installation Not Found")
+ "</big></b></span>\n"
+ _("Select a valid directory.")
),
Gtk.Label(
label=format_start + title + format_end + description,
use_markup=True,
wrap=True,
max_width_chars=50,
@@ -309,17 +310,24 @@ class PreferencesWindow(Adw.PreferencesWindow):
margin_bottom=9,
margin_start=12,
margin_end=12,
selectable=True,
)
)
),
)
popover.connect("show", clear_warning_selection, label)
popover.update_property(
(Gtk.AccessibleProperty.LABEL,), (title + description,)
)
def set_a11y_label(widget: Gtk.Popover) -> None:
self.set_focus(widget)
popover.connect("show", set_a11y_label)
menu_button = Gtk.MenuButton(
icon_name="dialog-warning-symbolic",
valign=Gtk.Align.CENTER,
popover=popover,
tooltip_text=_("Warning"),
)
menu_button.add_css_class("warning")

View File

@@ -52,5 +52,6 @@ image_size = (200 * scale_factor, 300 * scale_factor)
# pylint: disable=invalid-name
win = None
importer = None
import_time = None
store = None
log_files = None

View File

@@ -17,13 +17,12 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
from typing import Callable, Any
from typing import Any, Callable
from gi.repository import Gio
from src.game import Game
from src.store.managers.manager import Manager
from src.utils.task import Task
class AsyncManager(Manager):
@@ -49,11 +48,10 @@ class AsyncManager(Manager):
self, game: Game, additional_data: dict, callback: Callable[["Manager"], Any]
) -> None:
"""Create a task to process the game in a separate thread"""
task = Task.new(None, self.cancellable, self._task_callback, (callback,))
task.set_task_data((game, additional_data))
task.run_in_thread(self._task_thread_func)
task = Gio.Task.new(None, self.cancellable, self._task_callback, (callback,))
task.run_in_thread(lambda *_: self._task_thread_func((game, additional_data)))
def _task_thread_func(self, _task, _source_object, data, _cancellable):
def _task_thread_func(self, data):
"""Task thread entry point"""
game, additional_data, *_rest = data
self.run(game, additional_data)

View File

@@ -22,14 +22,14 @@ from pathlib import Path
from typing import NamedTuple
import requests
from gi.repository import Gio, GdkPixbuf
from gi.repository import GdkPixbuf, Gio
from requests.exceptions import HTTPError, SSLError
from src import shared
from src.game import Game
from src.store.managers.manager import Manager
from src.store.managers.steam_api_manager import SteamAPIManager
from src.utils.save_cover import resize_cover, save_cover
from src.utils.save_cover import convert_cover, save_cover
class ImageSize(NamedTuple):
@@ -110,18 +110,16 @@ class CoverManager(Manager):
stretch = 1 - (resized_height / cover_size.height)
return stretch <= max_stretch
def save_composited_cover(
def composite_cover(
self,
game: Game,
image_path: Path,
scale: float = 1,
blur_size: ImageSize = ImageSize(2, 2),
) -> None:
) -> GdkPixbuf.Pixbuf:
"""
Save the image composited with a background blur.
Return the image composited with a background blur.
If the image is stretchable, just stretch it.
:param game: The game to save the cover for
:param path: Path where the source image is located
:param scale:
Scale of the smalled image side
@@ -130,14 +128,15 @@ class CoverManager(Manager):
"""
# Load source image
source = GdkPixbuf.Pixbuf.new_from_file(str(image_path))
source = GdkPixbuf.Pixbuf.new_from_file(
str(convert_cover(image_path, resize=False))
)
source_size = ImageSize(source.get_width(), source.get_height())
cover_size = ImageSize._make(shared.image_size)
# Stretch if possible
if scale == 1 and self.is_stretchable(source_size, cover_size):
save_cover(game.game_id, resize_cover(pixbuf=source))
return
return source
# Create the blurred cover background
# fmt: off
@@ -164,7 +163,7 @@ class CoverManager(Manager):
GdkPixbuf.InterpType.BILINEAR,
255,
)
save_cover(game.game_id, resize_cover(pixbuf=cover))
return cover
def main(self, game: Game, additional_data: dict) -> None:
if game.blacklisted:
@@ -185,13 +184,15 @@ class CoverManager(Manager):
continue
# Icon cover
if key == "local_icon_path":
self.save_composited_cover(
game,
image_path,
scale=0.7,
blur_size=ImageSize(1, 2),
)
return
composite_kwargs = {}
self.save_composited_cover(game, image_path)
if key == "local_icon_path":
composite_kwargs["scale"] = 0.7
composite_kwargs["blur_size"] = ImageSize(1, 2)
save_cover(
game.game_id,
convert_cover(
pixbuf=self.composite_cover(image_path, **composite_kwargs)
),
)

View File

@@ -28,12 +28,22 @@ from PIL import Image, ImageSequence, UnidentifiedImageError
from src import shared
def resize_cover(
cover_path: Optional[Path] = None, pixbuf: Optional[GdkPixbuf.Pixbuf] = None
def convert_cover(
cover_path: Optional[Path] = None,
pixbuf: Optional[GdkPixbuf.Pixbuf] = None,
resize: bool = True,
) -> Optional[Path]:
if not cover_path and not pixbuf:
return None
pixbuf_extensions = set()
for pixbuf_format in GdkPixbuf.Pixbuf.get_formats():
for pixbuf_extension in pixbuf_format.get_extensions():
pixbuf_extensions.add(pixbuf_extension)
if not resize and cover_path and cover_path.suffix.lower()[1:] in pixbuf_extensions:
return cover_path
if pixbuf:
cover_path = Path(Gio.File.new_tmp("XXXXXX.tiff")[0].get_path())
pixbuf.savev(str(cover_path), "tiff", ["compression"], ["1"])
@@ -42,7 +52,8 @@ def resize_cover(
with Image.open(cover_path) as image:
if getattr(image, "is_animated", False):
frames = tuple(
frame.resize((200, 300)) for frame in ImageSequence.Iterator(image)
frame.resize((200, 300)) if resize else frame
for frame in ImageSequence.Iterator(image)
)
tmp_path = Path(Gio.File.new_tmp("XXXXXX.gif")[0].get_path())
@@ -50,6 +61,7 @@ def resize_cover(
tmp_path,
save_all=True,
append_images=frames[1:],
disposal=2,
)
else:
@@ -59,7 +71,7 @@ def resize_cover(
image = image.convert("RGBA")
tmp_path = Path(Gio.File.new_tmp("XXXXXX.tiff")[0].get_path())
image.resize(shared.image_size).save(
(image.resize(shared.image_size) if resize else image).save(
tmp_path,
compression="tiff_adobe_deflate"
if shared.schema.get_boolean("high-quality-images")
@@ -70,7 +82,7 @@ def resize_cover(
Gdk.Texture.new_from_filename(str(cover_path)).save_to_tiff(
tmp_path := Gio.File.new_tmp("XXXXXX.tiff")[0].get_path()
)
return resize_cover(tmp_path)
return convert_cover(tmp_path)
except GLib.GError:
return None

View File

@@ -28,7 +28,7 @@ from requests.exceptions import HTTPError
from src import shared
from src.game import Game
from src.utils.save_cover import resize_cover, save_cover
from src.utils.save_cover import convert_cover, save_cover
class SGDBError(Exception):
@@ -134,7 +134,7 @@ class SGDBHelper:
tmp_file = Gio.File.new_tmp()[0]
tmp_file_path = tmp_file.get_path()
Path(tmp_file_path).write_bytes(response.content)
save_cover(game.game_id, resize_cover(tmp_file_path))
save_cover(game.game_id, convert_cover(tmp_file_path))
except SGDBAuthError as error:
# Let caller handle auth errors
raise error

View File

@@ -1,95 +0,0 @@
# task.py
#
# Copyright 2023 Geoffrey Coulaud
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later
from functools import wraps
from typing import Any, Callable
from gi.repository import Gio
def create_task_thread_func_closure(func: Callable, data: Any) -> Callable:
"""Wrap a Gio.TaskThreadFunc with the given data in a closure"""
def closure(
task: Gio.Task, source_object: object, _data: Any, cancellable: Gio.Cancellable
) -> Any:
func(task, source_object, data, cancellable)
return closure
def decorate_set_task_data(task: Gio.Task) -> Callable:
"""Decorate Gio.Task.set_task_data to replace it"""
def decorator(original_method: Callable) -> Callable:
@wraps(original_method)
def new_method(task_data: Any) -> None:
task.task_data = task_data
return new_method
return decorator
def decorate_run_in_thread(task: Gio.Task) -> Callable:
"""Decorate Gio.Task.run_in_thread to pass the task data correctly
Creates a closure around task_thread_func with the task data available."""
def decorator(original_method: Callable) -> Callable:
@wraps(original_method)
def new_method(task_thread_func: Callable) -> None:
closure = create_task_thread_func_closure(task_thread_func, task.task_data)
original_method(closure)
return new_method
return decorator
# pylint: disable=too-few-public-methods
class Task:
"""Wrapper around Gio.Task to patch task data not being passed"""
@classmethod
def new(
cls,
source_object: object,
cancellable: Gio.Cancellable,
callback: Callable,
callback_data: Any,
) -> Gio.Task:
"""Create a new, monkey-patched Gio.Task.
The `set_task_data` and `run_in_thread` methods are decorated.
As of 2023-05-19, PyGObject does not work well with Gio.Task, so to pass data
the only viable way it to create a closure with the thread function and its data.
This class is supposed to make Gio.Task comply with its expected behaviour
per the docs:
http://lazka.github.io/pgi-docs/#Gio-2.0/classes/Task.html#Gio.Task.set_task_data
This code may break if pygobject overrides change in the future.
We need to manually pass `self` to the decorators since it's otherwise bound but
not accessible from Python's side.
"""
task = Gio.Task.new(source_object, cancellable, callback, callback_data)
task.set_task_data = decorate_set_task_data(task)(task.set_task_data)
task.run_in_thread = decorate_run_in_thread(task)(task.run_in_thread)
return task

View File

@@ -114,6 +114,21 @@ class CartridgesWindow(Adw.ApplicationWindow):
style_manager.connect("notify::dark", self.set_details_view_opacity)
style_manager.connect("notify::high-contrast", self.set_details_view_opacity)
# Allow for a custom number of rows for the library
if shared.schema.get_uint("library-rows"):
shared.schema.bind(
"library-rows",
self.library,
"max-children-per-line",
Gio.SettingsBindFlags.DEFAULT,
)
shared.schema.bind(
"library-rows",
self.hidden_library,
"max-children-per-line",
Gio.SettingsBindFlags.DEFAULT,
)
def search_changed(self, _widget: Any, hidden: bool) -> None:
# Refresh search filter on keystroke in search box
(self.hidden_library if hidden else self.library).invalidate_filter()
@@ -243,7 +258,7 @@ class CartridgesWindow(Adw.ApplicationWindow):
).lower()
if var != "name" and get_value(0) == get_value(1):
var, order = "name", True
var, order = "name", False
return ((get_value(0) > get_value(1)) ^ order) * 2 - 1