Compare commits

...

311 Commits

Author SHA1 Message Date
advplyr
fb3834156b Version bump v2.28.0 2025-08-10 17:42:32 -05:00
advplyr
c03f3f722d Merge pull request #4559 from weblate/weblate-audiobookshelf-abs-web-client
Translations update from Hosted Weblate
2025-08-10 18:31:40 -04:00
FiendFEARing
a06f48ca29 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1138 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-08-10 22:26:37 +00:00
NickSkier
9d79552dda Translated using Weblate (Russian)
Currently translated at 100.0% (1138 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/ru/
2025-08-10 22:26:36 +00:00
Laurin Sorgend
ed98614b6f Translated using Weblate (German)
Currently translated at 99.9% (1137 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-08-10 22:26:36 +00:00
owlcollector
09dd2cc79c Translated using Weblate (Japanese)
Currently translated at 6.0% (69 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/ja/
2025-08-10 22:26:35 +00:00
weblate.user.1274
e87237048a Translated using Weblate (Norwegian Bokmål)
Currently translated at 92.1% (1049 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/nb_NO/
2025-08-10 22:26:35 +00:00
Kent Henriksen
d71968fd80 Translated using Weblate (Norwegian Bokmål)
Currently translated at 92.1% (1049 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/nb_NO/
2025-08-10 22:26:34 +00:00
Thomas
f83c605ae1 Translated using Weblate (French)
Currently translated at 99.1% (1128 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/fr/
2025-08-10 22:26:34 +00:00
J. Lavoie
4325f470dd Translated using Weblate (German)
Currently translated at 99.8% (1136 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-08-10 22:26:33 +00:00
numerfolt
800ecf8e82 Translated using Weblate (German)
Currently translated at 99.8% (1136 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-08-10 22:26:32 +00:00
Vito0912
5cb143d50b Translated using Weblate (German)
Currently translated at 99.8% (1136 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-08-10 22:26:32 +00:00
Troj@
798c73c66c Translated using Weblate (Belarusian)
Currently translated at 64.6% (736 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/be/
2025-08-10 22:26:31 +00:00
Максим Горпиніч
0fa7c46274 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1138 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/uk/
2025-08-10 22:26:31 +00:00
Kent Henriksen
c2d420ec70 Translated using Weblate (Norwegian Bokmål)
Currently translated at 91.0% (1036 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/nb_NO/
2025-08-10 22:26:30 +00:00
biuklija
152daf7bf3 Translated using Weblate (Croatian)
Currently translated at 100.0% (1138 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/hr/
2025-08-10 22:26:29 +00:00
Ashish Wadekar
8d99249e50 Translated using Weblate (Hindi)
Currently translated at 8.7% (100 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/hi/
2025-08-10 22:26:29 +00:00
Camille de Lune
c6724ba353 Translated using Weblate (French)
Currently translated at 99.1% (1128 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/fr/
2025-08-10 22:26:28 +00:00
Aleksandr Zakirov
a519d44666 Translated using Weblate (Estonian)
Currently translated at 65.4% (745 of 1138 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/et/
2025-08-10 22:26:27 +00:00
Grzegorz Orlowski
7e8bf977cc Translated using Weblate (Polish)
Currently translated at 82.9% (942 of 1135 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/pl/
2025-08-10 22:26:27 +00:00
advplyr
4018be6330 Fix oidc auto-register not cleaning up new user on errors #4563 2025-08-10 17:26:15 -05:00
advplyr
99a3867ce9 Update callback url check
Co-authored-by: Denis Arnst <git@sapd.eu>
2025-08-10 17:08:25 -05:00
advplyr
2116f60133 Merge pull request #4565 from advplyr/redirect_transcode_requests
Fix server crash when transcode requests are made to the direct play endpoint
2025-08-07 18:31:45 -04:00
advplyr
794f0ef42a Fix server crash when transcode requests are made to the direct play endpoint #4555 2025-08-07 17:21:05 -05:00
advplyr
e510174f12 Merge pull request #4557 from Vito0912/cors
Allow a whitelist of CORS origins
2025-08-04 19:02:30 -04:00
advplyr
08c9e8d47d Fix i18n string order 2025-08-04 17:56:56 -05:00
advplyr
1908ec3df5 Remove commented out experimental features setting 2025-08-04 17:54:59 -05:00
advplyr
df3878d4ca Add Security section to settings with allowed cors origin setting, increase width of setting inputs 2025-08-04 17:54:29 -05:00
Vito0912
1097de6f1f now updates the input field 2025-08-04 19:17:46 +02:00
Vito0912
e408070b19 better heading 2025-08-03 14:02:33 +02:00
Vito0912
af67c2e86f locale 2025-08-03 13:57:44 +02:00
Vito0912
6a52d2a968 CORS 2025-08-03 13:52:58 +02:00
advplyr
3337b3af18 Version bump v2.27.0 2025-08-02 17:53:27 -05:00
advplyr
835d2c7f36 Merge pull request #4535 from weblate/weblate-audiobookshelf-abs-web-client
Translations update from Hosted Weblate
2025-08-02 18:52:04 -04:00
FiendFEARing
03f91099e0 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1135 of 1135 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-08-02 15:02:00 +02:00
Максим Горпиніч
c04afd0787 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1135 of 1135 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/uk/
2025-08-02 15:01:59 +02:00
Grzegorz Orlowski
b03bd79f5d Translated using Weblate (Polish)
Currently translated at 77.6% (881 of 1135 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/pl/
2025-08-02 15:01:57 +02:00
Troj@
79b4042e8e Translated using Weblate (Belarusian)
Currently translated at 63.6% (721 of 1133 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/be/
2025-08-01 02:51:15 +02:00
FiendFEARing
8f718ef91c Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1133 of 1133 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-08-01 02:51:15 +02:00
Pepijn
4053b20623 Translated using Weblate (Dutch)
Currently translated at 100.0% (1133 of 1133 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/nl/
2025-08-01 02:51:15 +02:00
Remco Schrijver
c4d654635f Translated using Weblate (Dutch)
Currently translated at 100.0% (1133 of 1133 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/nl/
2025-08-01 02:51:15 +02:00
enosh
ef5d0ffa48 Translated using Weblate (Hebrew)
Currently translated at 74.7% (847 of 1133 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/he/
2025-08-01 02:51:15 +02:00
Troj@
6a826cdb36 Translated using Weblate (Belarusian)
Currently translated at 58.1% (659 of 1133 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/be/
2025-08-01 02:51:15 +02:00
thehijacker
1d837f5f21 Translated using Weblate (Slovenian)
Currently translated at 100.0% (1133 of 1133 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/sl/
2025-08-01 02:51:15 +02:00
Максим Горпиніч
80873b379c Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1133 of 1133 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/uk/
2025-08-01 02:51:15 +02:00
Remco Schrijver
82a8f8f126 Translated using Weblate (Dutch)
Currently translated at 98.6% (1118 of 1133 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/nl/
2025-08-01 02:51:15 +02:00
Kabika82
4725a466da Translated using Weblate (Hungarian)
Currently translated at 100.0% (1133 of 1133 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/hu/
2025-08-01 02:51:15 +02:00
Jannik
031edc870c Translated using Weblate (German)
Currently translated at 99.8% (1131 of 1133 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-08-01 02:51:15 +02:00
Jan-Eric Myhrgren
625e2445b5 Translated using Weblate (Swedish)
Currently translated at 96.2% (1089 of 1131 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/sv/
2025-08-01 02:51:15 +02:00
max grakov
1640af2f1c Translated using Weblate (Russian)
Currently translated at 100.0% (1131 of 1131 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/ru/
2025-08-01 02:51:15 +02:00
Remco Schrijver
c76f76cc27 Translated using Weblate (Dutch)
Currently translated at 98.4% (1113 of 1131 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/nl/
2025-08-01 02:51:15 +02:00
ugyes
74af212293 Translated using Weblate (Hungarian)
Currently translated at 100.0% (1131 of 1131 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/hu/
2025-08-01 02:51:15 +02:00
Vito0912
e04efb9c6a Translated using Weblate (German)
Currently translated at 99.9% (1130 of 1131 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-08-01 02:51:14 +02:00
B0rax
ee17e7a555 Translated using Weblate (German)
Currently translated at 99.9% (1130 of 1131 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-08-01 02:51:14 +02:00
FiendFEARing
694a852c07 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1131 of 1131 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-08-01 02:51:14 +02:00
Максим Горпиніч
18068bb261 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1131 of 1131 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/uk/
2025-08-01 02:51:14 +02:00
Mikkel Dupont Olesen
71257f6c6c Translated using Weblate (Danish)
Currently translated at 99.4% (1124 of 1130 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/da/
2025-08-01 02:51:14 +02:00
advplyr
4d70929d2e Add locale strings for user stats heatmap #4550 2025-07-31 19:51:05 -05:00
advplyr
578e9559e4 Merge pull request #4551 from chriscam85/master
Including total durations into the de-branding from #4226 as warning message is always present currently
2025-07-31 20:23:47 -04:00
advplyr
894ea0b80a Update chapter data log 2025-07-31 19:19:11 -05:00
Chris Campanile
e54571f011 Including total durations into the de-branding from #4226 as warning message is always present currently 2025-07-31 16:48:05 -07:00
advplyr
32da0f1224 Merge pull request #4542 from advplyr/progress_updated_sort
Add book library sort by progress updated #1215
2025-07-28 15:13:40 -04:00
advplyr
2054accdc9 Update library sort dropdown to use max height available 2025-07-28 15:07:57 -04:00
advplyr
7d8b857c77 Add book library sort by progress updated #1215 2025-07-28 14:58:28 -04:00
advplyr
0107cb4782 UI/UX fix x overflow for sessions tables on mobile 2025-07-26 09:45:44 -05:00
advplyr
f273eee807 Merge pull request #4534 from michaeldvinci/sepia-theme
Add 'sepia' theme to EpubReader
2025-07-25 17:34:34 -05:00
advplyr
4af21b079a Fix epub toc search input colors for themes 2025-07-25 17:31:59 -05:00
Michael Vinci
c9eaf2db2d Add 'sepia' theme to EpubReader 2025-07-25 17:01:16 -05:00
advplyr
a5fb0d9cdb Merge pull request #4530 from advplyr/fix_ereader_socket_event
Fix ereader update socket event sending all devices #4529
2025-07-24 17:33:42 -05:00
advplyr
53c80d9798 Merge pull request #4528 from FelixSche/master
Update SideRail.vue
2025-07-24 17:32:44 -05:00
advplyr
832165716b Fix ereader update socket event sending all devices #4529 2025-07-24 17:29:08 -05:00
Felix
d9f2d8bf1d Update SideRail.vue
Changed cursor at version to pointer
2025-07-24 13:57:26 +02:00
advplyr
a7a3a56509 Version bump v2.26.3 2025-07-23 17:18:51 -05:00
advplyr
4082fadf90 Merge pull request #4525 from weblate/weblate-audiobookshelf-abs-web-client
Translations update from Hosted Weblate
2025-07-23 17:17:51 -05:00
FiendFEARing
93160b83bf Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1130 of 1130 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-23 13:06:32 +02:00
Максим Горпиніч
472240f994 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1130 of 1130 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/uk/
2025-07-23 13:06:31 +02:00
Dmitry
c3f0fb8e5e Translated using Weblate (Russian)
Currently translated at 100.0% (1130 of 1130 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/ru/
2025-07-23 13:06:30 +02:00
Daniel Schosser
b156ebeb9f Translated using Weblate (German)
Currently translated at 99.9% (1129 of 1130 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-23 13:06:29 +02:00
advplyr
e4c775c847 Merge pull request #4523 from advplyr/fix_change_empty_root_password
Update change password to support null or empty string passwords #4522
2025-07-22 17:01:07 -05:00
advplyr
45e8e72759 Update change password to support null or empty string passwords #4522 2025-07-22 15:17:00 -05:00
advplyr
0ae7340889 Merge pull request #4520 from advplyr/fix_podcast_session_track_index
Fix podcast episode track index null in playback session
2025-07-22 15:04:22 -05:00
advplyr
8c38987d92 Fix podcast episode track index null in playback session 2025-07-22 14:44:36 -05:00
advplyr
878f0787ba Merge branch 'master' of https://github.com/advplyr/audiobookshelf 2025-07-21 17:07:12 -05:00
advplyr
880d85eaef Version bump v2.26.2 2025-07-21 17:07:06 -05:00
advplyr
f7aaebc1de Merge pull request #4508 from weblate/weblate-audiobookshelf-abs-web-client
Translations update from Hosted Weblate
2025-07-21 17:01:15 -05:00
Charlie
d96ebbe82d Translated using Weblate (French)
Currently translated at 100.0% (1129 of 1129 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/fr/
2025-07-22 00:00:51 +02:00
kuci-JK
70d67156f0 Translated using Weblate (Czech)
Currently translated at 99.2% (1121 of 1129 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/cs/
2025-07-22 00:00:51 +02:00
Serhat Gülaştı
f293b317be Translated using Weblate (Turkish)
Currently translated at 28.3% (320 of 1129 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/tr/
2025-07-22 00:00:51 +02:00
Simple16
1f23794f88 Translated using Weblate (Russian)
Currently translated at 99.9% (1128 of 1129 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/ru/
2025-07-22 00:00:51 +02:00
FiendFEARing
e6bfd118f6 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1129 of 1129 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-22 00:00:51 +02:00
SunSpring
1166400ab1 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1129 of 1129 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-22 00:00:51 +02:00
Максим Горпиніч
55f0ac871b Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1129 of 1129 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/uk/
2025-07-22 00:00:51 +02:00
Angelo Prandelli
3584f6e24f Translated using Weblate (Italian)
Currently translated at 98.2% (1109 of 1129 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/it/
2025-07-22 00:00:51 +02:00
biuklija
23bf2594c8 Translated using Weblate (Croatian)
Currently translated at 100.0% (1129 of 1129 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/hr/
2025-07-22 00:00:51 +02:00
advplyr
8fb460ce05 Merge pull request #4319 from mikiher/audible-confidence-score
Audible confidence score
2025-07-21 17:00:44 -05:00
advplyr
8c4bbfd6a2 Add match confidence as a badge on match book card 2025-07-21 16:52:21 -05:00
advplyr
742961e0b8 Merge pull request #4510 from advplyr/fix_set_token
Fix set token on page load #4509
2025-07-18 17:11:09 -05:00
advplyr
5b6807892f Fix set token on page load #4509 2025-07-18 16:59:27 -05:00
advplyr
b911a25c57 Version bump v2.26.1 2025-07-16 17:16:43 -05:00
advplyr
53110674e4 Merge pull request #4492 from weblate/weblate-audiobookshelf-abs-web-client
Translations update from Hosted Weblate
2025-07-16 17:15:48 -05:00
Grzegorz Orlowski
f963cd4753 Translated using Weblate (Polish)
Currently translated at 76.1% (859 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/pl/
2025-07-16 22:11:56 +00:00
Grzegorz Orlowski
0dccc3bcae Translated using Weblate (Polish)
Currently translated at 76.0% (858 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/pl/
2025-07-16 22:11:55 +00:00
FiendFEARing
5b4fd5b254 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1128 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-16 22:11:55 +00:00
Fredrik Lindqvist
bdb9d3caeb Translated using Weblate (Swedish)
Currently translated at 95.2% (1074 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/sv/
2025-07-16 22:11:54 +00:00
Jannik
9aca824b59 Translated using Weblate (German)
Currently translated at 99.9% (1127 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-16 22:11:53 +00:00
Jannik
8e891805eb Translated using Weblate (German)
Currently translated at 99.9% (1127 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-16 22:11:53 +00:00
Jannik
2760517445 Translated using Weblate (German)
Currently translated at 99.9% (1127 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-16 22:11:52 +00:00
Jannik
889ee33320 Translated using Weblate (German)
Currently translated at 99.9% (1127 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-16 22:11:51 +00:00
Jannik
4f65801713 Translated using Weblate (German)
Currently translated at 99.9% (1127 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-16 22:11:50 +00:00
Jannik
3e75acd4ef Translated using Weblate (German)
Currently translated at 99.9% (1127 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-16 22:11:50 +00:00
Jannik
3e8fe2ef60 Translated using Weblate (German)
Currently translated at 99.9% (1127 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-16 22:11:49 +00:00
Jannik
0bc441de20 Translated using Weblate (German)
Currently translated at 99.9% (1127 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-16 22:11:48 +00:00
Jannik
a8c2f0d4c8 Translated using Weblate (German)
Currently translated at 99.9% (1127 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-16 22:11:48 +00:00
FiendFEARing
b59da8bd0c Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1128 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-16 22:11:47 +00:00
FiendFEARing
77cb4f75c6 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1128 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-16 22:11:46 +00:00
Максим Горпиніч
9cf1711fae Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1128 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/uk/
2025-07-16 22:11:45 +00:00
Jan-Eric Myhrgren
f472116dc3 Translated using Weblate (Swedish)
Currently translated at 94.5% (1066 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/sv/
2025-07-16 22:11:45 +00:00
Jan-Eric Myhrgren
c7eb9d7799 Translated using Weblate (Swedish)
Currently translated at 94.5% (1066 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/sv/
2025-07-16 22:11:44 +00:00
Jan-Eric Myhrgren
c66380eaeb Translated using Weblate (Swedish)
Currently translated at 94.5% (1066 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/sv/
2025-07-16 22:11:43 +00:00
Simple16
1bebb22705 Translated using Weblate (Russian)
Currently translated at 100.0% (1128 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/ru/
2025-07-16 22:11:43 +00:00
Simple16
4e96649fe3 Translated using Weblate (Russian)
Currently translated at 100.0% (1128 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/ru/
2025-07-16 22:11:42 +00:00
Simple16
a21cec806e Translated using Weblate (Russian)
Currently translated at 100.0% (1128 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/ru/
2025-07-16 22:11:41 +00:00
biuklija
8a3b8d2249 Translated using Weblate (Croatian)
Currently translated at 100.0% (1128 of 1128 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/hr/
2025-07-16 22:11:40 +00:00
advplyr
581277914c Merge pull request #4503 from advplyr/session_modal_user
Update sessions modal to show username & update legacy token input with warning
2025-07-16 17:11:28 -05:00
advplyr
e678fe6e2f Update sessions modal to show username & update sessions endpoints to always return username 2025-07-16 16:56:07 -05:00
advplyr
3845940245 Add warning under legacy token input on users page to use api keys instead 2025-07-16 16:43:53 -05:00
advplyr
6c63e2131c Update AllowCors to apply to every request #4497 2025-07-15 16:28:41 -05:00
advplyr
e25e2b238f Merge pull request #4493 from advplyr/localize_durations
Localize elapsed duration on sessions tables
2025-07-14 17:28:58 -05:00
advplyr
99110f587a Localize elapsed duration on sessions tables 2025-07-14 17:17:39 -05:00
advplyr
b553e959e2 Merge pull request #4486 from advplyr/fix_oidc_create_user
Fix OIDC auto register user #4485
2025-07-13 17:09:40 -05:00
advplyr
f7b94a4b6d Fix OIDC auto register user #4485 2025-07-13 17:04:02 -05:00
mikiher
e9a705587a Merge branch 'advplyr:master' into audible-confidence-score 2025-07-13 10:13:00 +03:00
advplyr
264ae928a9 Version bump v2.26.0 2025-07-12 11:43:14 -05:00
advplyr
f5248a9f00 Merge pull request #4476 from weblate/weblate-audiobookshelf-abs-web-client
Translations update from Hosted Weblate
2025-07-12 11:41:54 -05:00
FiendFEARing
3473ff594a Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-12 18:32:35 +02:00
FiendFEARing
20bb6e13b5 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-12 18:32:35 +02:00
FiendFEARing
a05d32b1d7 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-12 18:32:34 +02:00
Kabika82
c6b3521cb6 Translated using Weblate (Hungarian)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/hu/
2025-07-12 18:32:34 +02:00
Kabika82
2444504c6a Translated using Weblate (Hungarian)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/hu/
2025-07-12 18:32:33 +02:00
advplyr
d38532c07a Merge pull request #4444 from advplyr/jwt_auth_refactor
Implement new JWT auth
2025-07-12 11:32:22 -05:00
advplyr
4f7831611f Update auth re-login i18n string 2025-07-12 11:23:08 -05:00
advplyr
d09db19cd5 Update re-login message to show for users without github discussion link, add message to i18n strings 2025-07-12 11:21:52 -05:00
advplyr
030e43f382 Support disabled rate limiter by setting max to 0, add logs when rate limit is changed from default 2025-07-12 10:51:07 -05:00
advplyr
f081a7fdc1 Update rate limiter to use requestIp as key, pass in configurable error message 2025-07-12 10:32:35 -05:00
advplyr
f0d5f46199 Merge branch 'master' into jwt_auth_refactor 2025-07-11 16:59:19 -05:00
advplyr
0b8f6db45e Merge pull request #4445 from weblate/weblate-audiobookshelf-abs-web-client
Translations update from Hosted Weblate
2025-07-11 16:58:05 -05:00
advplyr
806c0a2991 Remove return_tokens query param for login 2025-07-11 16:01:45 -05:00
advplyr
7d6d3e6687 Move invalidate refresh token to TokenManager 2025-07-11 14:43:07 -05:00
FiendFEARing
ad07ed7e25 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-11 03:04:29 +02:00
advplyr
d3402e30c2 Update ereaders to handle refreshing, epubjs to use custom request method, separate accessToken in store 2025-07-10 16:54:28 -05:00
advplyr
25fe4dee3a Update epub reader to use axios for handling refresh tokens 2025-07-09 17:03:10 -05:00
advplyr
3c21c82ce1 Merge branch 'master' into jwt_auth_refactor 2025-07-09 14:55:05 -05:00
thehijacker
3c8876a37d Translated using Weblate (Slovenian)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/sl/
2025-07-09 19:54:31 +00:00
thehijacker
fba70c9831 Translated using Weblate (Slovenian)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/sl/
2025-07-09 19:54:30 +00:00
SunSpring
27e40d16fd Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-09 19:54:30 +00:00
FiendFEARing
448cbf8530 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-09 19:54:29 +00:00
SunSpring
f1153f9da5 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-09 19:54:28 +00:00
Raj
d09a21d922 Translated using Weblate (Gujarati)
Currently translated at 16.6% (184 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/gu/
2025-07-09 19:54:28 +00:00
Richard Požgay
62afa3c3ee Translated using Weblate (Czech)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/cs/
2025-07-09 19:54:27 +00:00
Richard Požgay
85446be0e5 Translated using Weblate (Czech)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/cs/
2025-07-09 19:54:27 +00:00
Michal
018ca8e7ee Translated using Weblate (Slovak)
Currently translated at 99.9% (1107 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/sk/
2025-07-09 19:54:26 +00:00
Максим Горпиніч
f02453ac92 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/uk/
2025-07-09 19:54:25 +00:00
DavevanIersel
84b77f4c7f Translated using Weblate (Dutch)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/nl/
2025-07-09 19:54:25 +00:00
FiendFEARing
d41276ba8c Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.9% (1107 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-09 19:54:24 +00:00
FiendFEARing
576d7dc024 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.9% (1107 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-09 19:54:24 +00:00
Максим Горпиніч
6d2b1df560 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/uk/
2025-07-09 19:54:23 +00:00
DavevanIersel
8255e4308c Translated using Weblate (Dutch)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/nl/
2025-07-09 19:54:22 +00:00
DavevanIersel
794adf0292 Translated using Weblate (Dutch)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/nl/
2025-07-09 19:54:22 +00:00
Daniel Schosser
f2e0b9762c Translated using Weblate (German)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-09 19:54:21 +00:00
Daniel Schosser
7d0def0edb Translated using Weblate (German)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-09 19:54:21 +00:00
Vito0912
0653572396 Translated using Weblate (German)
Currently translated at 99.9% (1106 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-09 19:54:20 +00:00
Vito0912
d9a3750667 Translated using Weblate (German)
Currently translated at 99.9% (1106 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-07-09 19:54:19 +00:00
advplyr
9c0c7b6b08 Merge pull request #4469 from advplyr/fix_scanner_deleting_single_file_books
Fix scanner after deleting single file books #4459
2025-07-09 14:54:05 -05:00
advplyr
df1391d93f Fix scanner after deleting single file books #4459 2025-07-09 13:42:53 -05:00
mikiher
bf6d81b333 Merge branch 'advplyr:master' into audible-confidence-score 2025-07-09 09:04:52 +03:00
advplyr
8775e55762 Update jwt secret handling 2025-07-08 16:39:50 -05:00
advplyr
d0d152c20d Seperate setUserToken from setUser in store 2025-07-08 09:45:24 -05:00
advplyr
4ff7355262 Fix hashPassword 2025-07-08 09:14:07 -05:00
advplyr
6cc7a44a22 Update oidc redirect to pass both new and old token in url 2025-07-07 17:21:25 -05:00
advplyr
ad092ef8f8 Merge branch 'master' into jwt_auth_refactor 2025-07-07 16:50:58 -05:00
advplyr
4102ed8be4 Fix LazySeriesCard component test 2025-07-07 16:49:20 -05:00
advplyr
691f291843 Update LibraryItemController unit test 2025-07-07 16:26:17 -05:00
advplyr
ac381854e5 Add rate limiter for auth endpoints 2025-07-07 16:23:15 -05:00
advplyr
9c8900560c Seperate out auth strategies, update change password to return error status codes 2025-07-07 15:04:40 -05:00
advplyr
d9cfcc86e7 Update oidc to return refresh token in response body for mobile 2025-07-07 09:16:07 -05:00
advplyr
ce803dd6de Use getServerSetting to ensure serverSettings is set before accessing 2025-07-06 17:39:03 -05:00
advplyr
97afd22f81 Refactor Auth to breakout functions in TokenManager, handle token generation for OIDC 2025-07-06 16:43:03 -05:00
advplyr
e24eaab3f1 Log when token expiry is set via env var, api-keys create/update returns with user association 2025-07-06 13:10:14 -05:00
advplyr
e201247d69 Handle socket re-authentication, fix socket toast to be re-usable, socket cleanup 2025-07-06 11:07:01 -05:00
advplyr
a24dae5262 Merge branch 'master' into jwt_auth_refactor 2025-07-06 09:06:39 -05:00
advplyr
e59babdf24 Force re-login if using old token, show alert if admin user, add isOldToken flag to user 2025-07-05 17:46:18 -05:00
advplyr
8dbe1e4e5d Fix express.json position 2025-07-04 16:49:45 -05:00
advplyr
cdc37ddb0f Use x-refresh-token for alt method of passing refresh token, check x-refresh-token for logout 2025-07-04 13:54:37 -05:00
advplyr
f127a7beb5 Update router for internal-api routes 2025-07-03 17:31:38 -05:00
advplyr
df60aeb456 Update narrator name to be clickable to filter by narrator 2025-07-02 17:30:00 -05:00
advplyr
30c327d92a Merge pull request #4454 from advplyr/fix_mediaprogress_updatedat_2
Fix manually setting updatedAt of mediaProgresses using progress sync lastUpdate timestamp
2025-07-01 17:08:50 -05:00
advplyr
596bddf791 Fix manually setting updatedAt of mediaProgresses using progress sync lastUpdate timestamp #4366 2025-07-01 16:48:07 -05:00
advplyr
44ff90a6f2 Update refresh endpoint to support override cookie token 2025-07-01 16:31:26 -05:00
advplyr
293851d931 Fix missing translation in remove podcast episode modal #4434 2025-06-30 17:49:05 -05:00
advplyr
8b995a179d Add support for returning refresh token for mobile clients 2025-06-30 17:31:31 -05:00
advplyr
4d32a22de9 Update API Keys to be tied to a user, add apikey lru-cache, handle deactivating expired keys 2025-06-30 14:53:11 -05:00
advplyr
af1ff12dbb Add get all, update and delete endpoints. Add api keys config page 2025-06-30 11:32:02 -05:00
advplyr
d96ed01ce4 Set up ApiKey model and create Api Key endpoint 2025-06-30 10:12:39 -05:00
advplyr
7610e97f0f Merge pull request #4416 from weblate/weblate-audiobookshelf-abs-web-client
Translations update from Hosted Weblate
2025-06-29 17:32:52 -05:00
advplyr
4f5123e842 Implement new JWT auth 2025-06-29 17:22:58 -05:00
Eigen_art
d102065d02 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1107 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/uk/
2025-06-27 00:22:11 +02:00
Dan Johansen
34315d4c10 Translated using Weblate (Danish)
Currently translated at 99.7% (1104 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/da/
2025-06-27 00:22:10 +02:00
Michael Förster
276a179446 Translated using Weblate (German)
Currently translated at 99.9% (1106 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-06-27 00:22:10 +02:00
burghy86
4462d32e98 Translated using Weblate (Italian)
Currently translated at 100.0% (1107 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/it/
2025-06-27 00:22:09 +02:00
SunSpring
9722674072 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1107 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-06-27 00:22:09 +02:00
Mathias Franco
35bb77c9c2 Translated using Weblate (Dutch)
Currently translated at 100.0% (1107 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/nl/
2025-06-27 00:22:08 +02:00
biuklija
cf6f49ce75 Translated using Weblate (Croatian)
Currently translated at 100.0% (1107 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/hr/
2025-06-27 00:22:07 +02:00
Daniel Schosser
d614373c64 Translated using Weblate (German)
Currently translated at 99.9% (1106 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-06-27 00:22:07 +02:00
Stefan Ha
b9969c78a6 Translated using Weblate (German)
Currently translated at 99.9% (1106 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-06-27 00:22:06 +02:00
B0rax
fbf482d6b6 Translated using Weblate (German)
Currently translated at 99.9% (1106 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-06-27 00:22:06 +02:00
David Havndrup Munch
dd74d0a726 Translated using Weblate (Danish)
Currently translated at 98.9% (1095 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/da/
2025-06-27 00:22:05 +02:00
petr-prikryl
b13b80e011 Translated using Weblate (Czech)
Currently translated at 99.9% (1106 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/cs/
2025-06-27 00:22:04 +02:00
advplyr
e384863148 Add support for running in production with dev.js config, node index --prod-with-dev-env 2025-06-26 17:21:58 -05:00
mikiher
9c44fc0d01 Merge branch 'advplyr:master' into audible-confidence-score 2025-06-26 18:09:13 +03:00
advplyr
d21fe49ce2 Merge pull request #4430 from advplyr/experimental_next_client
Add ENV REACT_CLIENT_PATH to target a Nextjs frontend instead of Nuxt
2025-06-23 17:23:15 -05:00
advplyr
a992400d6a Add ENV REACT_CLIENT_PATH to target a Nextjs frontend instead of Nuxt 2025-06-23 16:56:08 -05:00
advplyr
108b2a60f5 Merge pull request #4425 from Vito0912/feat/addExplicit
Add explicit filter
2025-06-21 17:03:25 -05:00
advplyr
af684e6a69 Explicit library filter not shown for users without permission 2025-06-21 17:01:13 -05:00
Vito0912
5336d0525e add explicit to podcasts 2025-06-21 12:29:54 +02:00
Vito0912
bb4eec9355 add explicit 2025-06-21 12:02:44 +02:00
advplyr
28404f37b8 Merge pull request #4422 from advplyr/podcast_episode_duration
Show duration in episode view modal & episode feed modal
2025-06-19 17:35:36 -05:00
advplyr
7b92c15a46 Include durationSeconds on RSS podcast episode parsed from duration 2025-06-19 17:28:21 -05:00
advplyr
c150ed4e98 Update view episode modal to include duration & episode feed modal to include duration & size 2025-06-19 17:14:56 -05:00
advplyr
cb7632b216 Merge pull request #4419 from advplyr/episode-timestamps-clickable
Episode view modal makes timestamps in description clickable
2025-06-18 17:28:55 -05:00
advplyr
b8849677de Episode view modal makes timestamps in description clickable 2025-06-18 17:20:36 -05:00
advplyr
9bf8d7de11 Fix server crash when FantLab provider request times out #4410 2025-06-17 17:21:21 -05:00
advplyr
6634ce8fd4 Merge pull request #4417 from advplyr/book_author_secondary_sort_title
Update book library secondary title sort to use title ignore prefixes
2025-06-17 16:40:59 -05:00
advplyr
9d4303ef7b Update book library secondary title sort to use title ignore prefixes #4414 2025-06-17 16:25:30 -05:00
advplyr
1f7be58124 Fix database cleanup query pulling duplicate mediaProgresses 2025-06-16 17:50:53 -05:00
advplyr
6b8b27b04f Merge pull request #4413 from HadrienPatte/nusqlite3-path
Make `NUSQLITE3_PATH` build arg configurable
2025-06-16 17:22:21 -05:00
Hadrien Patte
ba4061e5a4 Make NUSQLITE3_PATH build arg configurable 2025-06-16 23:03:02 +02:00
mikiher
5017e7ce9e Merge branch 'advplyr:master' into audible-confidence-score 2025-06-16 10:26:58 +03:00
advplyr
693dc00fa3 Update local session sync logs to help debug sync errors 2025-06-15 17:21:47 -05:00
advplyr
f3f5f3b9bd Version bump v2.25.1 2025-06-14 17:57:19 -05:00
advplyr
b515c6c746 Remove mediaProgresses duplicate check 2025-06-14 17:56:35 -05:00
advplyr
35e196238a Version bump v2.25.0 2025-06-14 17:18:53 -05:00
advplyr
2dc93258f1 Merge pull request #4364 from weblate/weblate-audiobookshelf-abs-web-client
Translations update from Hosted Weblate
2025-06-13 17:32:53 -05:00
thehijacker
5123f7d240 Translated using Weblate (Slovenian)
Currently translated at 100.0% (1107 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/sl/
2025-06-14 00:29:31 +02:00
Usama Khalil
06d3bd76a8 Translated using Weblate (Arabic)
Currently translated at 100.0% (1107 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/ar/
2025-06-14 00:29:31 +02:00
Ivan Smoliakov
52196afd99 Translated using Weblate (Russian)
Currently translated at 100.0% (1107 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/ru/
2025-06-14 00:29:30 +02:00
ugyes
3e44ee6f50 Translated using Weblate (Hungarian)
Currently translated at 100.0% (1107 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/hu/
2025-06-14 00:29:29 +02:00
Максим Горпиніч
9841826e10 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1107 of 1107 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/uk/
2025-06-14 00:29:29 +02:00
Dawid Kuźnicki
def93d18ec Translated using Weblate (Polish)
Currently translated at 76.9% (850 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/pl/
2025-06-14 00:29:28 +02:00
Rekentek
387a3d05b4 Translated using Weblate (Dutch)
Currently translated at 98.5% (1089 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/nl/
2025-06-14 00:29:28 +02:00
Daniel Schosser
398d04fc08 Translated using Weblate (German)
Currently translated at 100.0% (1105 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-06-14 00:29:27 +02:00
David Havndrup Munch
c5e5e516af Translated using Weblate (Danish)
Currently translated at 98.9% (1093 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/da/
2025-06-14 00:29:27 +02:00
Plazec
1c6f99b876 Translated using Weblate (Czech)
Currently translated at 99.7% (1102 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/cs/
2025-06-14 00:29:26 +02:00
Grzegorz Orlowski
d0af82e71a Translated using Weblate (Polish)
Currently translated at 76.9% (850 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/pl/
2025-06-14 00:29:25 +02:00
Usama Khalil
76e7616439 Translated using Weblate (Arabic)
Currently translated at 100.0% (1105 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/ar/
2025-06-14 00:29:25 +02:00
max grakov
fe99a269bc Translated using Weblate (Russian)
Currently translated at 100.0% (1105 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/ru/
2025-06-14 00:29:24 +02:00
thehijacker
5315f65023 Translated using Weblate (Slovenian)
Currently translated at 100.0% (1105 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/sl/
2025-06-14 00:29:24 +02:00
Максим Горпиніч
c2809808c3 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (1105 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/uk/
2025-06-14 00:29:23 +02:00
Anders Norman
204ac4f204 Translated using Weblate (Norwegian Bokmål)
Currently translated at 92.6% (1024 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/nb_NO/
2025-06-14 00:29:22 +02:00
Arieh Kellermann
accd5d1096 Translated using Weblate (German)
Currently translated at 100.0% (1105 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/de/
2025-06-14 00:29:22 +02:00
advplyr
5025c6a3ea Merge pull request #4383 from JKubovy/improve-podcast-episode-search
Use fuse.js for podcast episode search
2025-06-13 17:29:13 -05:00
advplyr
6d0d1415e4 Add fuse.basic.min.js in libs instead of full npm package, use lower threshold for quick matching 2025-06-13 17:23:24 -05:00
advplyr
514f5c2409 Merge pull request #4394 from Vito0912/feat/addISBNAudible
Added the ISBN for Audible providers (returned data)
2025-06-13 16:21:32 -05:00
advplyr
2cc58b2c8a Merge pull request #4404 from advplyr/podcast_useragents
Update podcast episode downloads to have a fallback user agent string
2025-06-12 17:40:42 -05:00
advplyr
777a055fcd Update podcast episode downloads to have a fallback user agent string 2025-06-12 17:31:12 -05:00
advplyr
b45085d2d6 Update podcast episode download user agent to fix #4401 2025-06-12 17:19:24 -05:00
advplyr
22f6e86a12 Fix pathexists filepath back to posix 2025-06-11 16:37:07 -05:00
advplyr
dc6783ea76 Merge pull request #4398 from advplyr/pathexists_user_access
Update pathexists endpoint to check user has access to library
2025-06-11 16:31:14 -05:00
advplyr
a6f10ca48e Update upload endpoint to check user has access to library 2025-06-11 16:14:51 -05:00
advplyr
aac01d6d9a Update pathexists endpoint to check user has access to library 2025-06-11 16:04:18 -05:00
Vito0912
a617994207 added isbn 2025-06-11 08:12:23 +02:00
advplyr
7a33a412fc Merge pull request #4393 from advplyr/fix_pathexists_join
Fix filesystem pathexists path join
2025-06-10 17:20:23 -05:00
advplyr
0135b3560c Fix filesystem pathexists path join 2025-06-10 17:02:42 -05:00
advplyr
6968a5c02a Merge pull request #4378 from Vito0912/feat/PodcastNots
Notifications for failed rss feeds and disabled rss feeds
2025-06-09 16:25:19 -05:00
advplyr
5e2bb0b12c Fix notification js docs and update description/defaults 2025-06-09 16:21:05 -05:00
advplyr
7122756e58 Update notification description grammar 2025-06-09 15:51:14 -05:00
advplyr
8ecc912c2d Merge pull request #4388 from advplyr/book_author_secondary_sort
Update book library sort by author to use title as secondary sort #4380
2025-06-08 17:38:45 -05:00
advplyr
c8cea4e6af Update book library sort by author to use title as secondary sort #4380 2025-06-08 17:28:19 -05:00
advplyr
0c5d05d319 Fix chapter table on audiobook tools page uneven column widths 2025-06-07 17:10:23 -05:00
advplyr
4a3eb7727b Merge pull request #4385 from advplyr/clean_duplicate_mediaprogress
Update cleanDatabase to remove duplicate mediaProgresses
2025-06-06 17:17:43 -05:00
advplyr
81640464ba Update cleanDatabase to remove duplicate mediaProgresses 2025-06-06 17:05:07 -05:00
Jan Kubovy
eda7036f70 Use fuse.js for podcast episode search
Replace levenshtein distance with fuse.js fuzzy searching library. Search in episode's title and subtitle
2025-06-06 10:43:52 +00:00
advplyr
e669a8d378 Merge pull request #4370 from Vito0912/feat/MaxFailedEpisodeChecks-
Adds ENV for MaxFailedEpisodeChecks
2025-06-05 15:06:27 -05:00
advplyr
8e01859075 Cast PODCAST_DOWNLOAD_TIMEOUT and MAX_FAILED_EPISODE_CHECKS env vars to numbers 2025-06-05 14:31:12 -05:00
Vito0912
f0525d4f0d abc is hard 2025-06-05 14:09:35 +02:00
Vito0912
84c9c6cb50 move to global 2025-06-05 14:07:35 +02:00
Vito0912
346df3680c local strings 2025-06-05 14:02:29 +02:00
Vito0912
6aa7c8a3d8 added notification 2025-06-05 13:34:18 +02:00
advplyr
704c6f7bde Merge pull request #4374 from Vito0912/feat/allowBase64Images
Corrects removing of attachments for Trix
2025-06-04 16:36:46 -05:00
advplyr
f01055f6e6 Merge pull request #4373 from Vito0912/feat/maybeFixPodcast
Potential fix/new knowledge for hangig podcasts
2025-06-04 16:33:40 -05:00
Vito0912
759c58d3f7 remove any attachment 2025-06-04 16:38:01 +02:00
Vito0912
357176b301 catch timeout 2025-06-04 16:15:18 +02:00
Vito0912
9bb4dc3ab0 potential fix 2025-06-04 10:58:44 +02:00
Vito0912
709c33f27a ensure proper type 2025-06-04 10:05:16 +02:00
Vito0912
4d846e225a Adds ENV for MaxFailedEpisodeChecks 2025-06-04 10:02:17 +02:00
advplyr
5dc6d613bd Merge pull request #4361 from Vito0912/feat/encoderSettings
Fix: Audiobook m4b advanced encoder ignore
2025-06-02 16:53:28 -05:00
advplyr
63ccdb68f0 Fix m4b encoder backup file overwriting the encoded file when they have the same filename 2025-06-02 16:50:03 -05:00
Vito0912
424ef1aec3 prettier 2 2025-06-02 19:34:25 +02:00
Vito0912
b6995ba5d1 prettier 2025-06-02 19:33:50 +02:00
Vito0912
9968743a93 fix wrong display and ignored values 2025-06-02 19:32:52 +02:00
advplyr
c377b57601 Version bump v2.24.0 2025-06-01 16:00:16 -05:00
advplyr
262d0b46e3 Merge pull request #4350 from weblate/weblate-audiobookshelf-abs-web-client
Translations update from Hosted Weblate
2025-06-01 15:40:16 -05:00
Charlie
32fc4f6555 Translated using Weblate (French)
Currently translated at 99.9% (1104 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/fr/
2025-06-01 15:57:47 +02:00
DR
81572adab6 Translated using Weblate (Hebrew)
Currently translated at 76.4% (845 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/he/
2025-06-01 00:37:34 +02:00
kuci-JK
1ad2e71fd5 Translated using Weblate (Czech)
Currently translated at 98.9% (1093 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/cs/
2025-06-01 00:37:33 +02:00
FiendFEARing
db66b9eaeb Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1105 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-06-01 00:37:32 +02:00
Simple16
28c2e62e61 Translated using Weblate (Russian)
Currently translated at 100.0% (1105 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/ru/
2025-06-01 00:37:32 +02:00
Tommaso Bellandi
96401c377c Translated using Weblate (Italian)
Currently translated at 100.0% (1105 of 1105 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/it/
2025-06-01 00:37:31 +02:00
advplyr
9d45880b37 Merge pull request #4355 from advplyr/sanitize_html_description
Sanitize media item & episode description on update
2025-05-31 17:37:18 -05:00
mikiher
de25763a74 Add match confidence display to BookMatchCard 2025-05-21 11:16:46 +03:00
mikiher
a894ceb9cf Match confidence calculation for audible results 2025-05-21 10:25:42 +03:00
mikiher
387e58a714 Add levenshteinSimilarity function to utils 2025-05-21 09:57:44 +03:00
138 changed files with 5764 additions and 1553 deletions

View File

@@ -57,7 +57,7 @@ WORKDIR /app
# Copy compiled frontend and server from build stages
COPY --from=build-client /client/dist /app/client/dist
COPY --from=build-server /server /app
COPY --from=build-server /usr/local/lib/nusqlite3 /usr/local/lib/nusqlite3
COPY --from=build-server ${NUSQLITE3_PATH} ${NUSQLITE3_PATH}
EXPOSE 80

View File

@@ -70,6 +70,11 @@ export default {
title: this.$strings.HeaderUsers,
path: '/config/users'
},
{
id: 'config-api-keys',
title: this.$strings.HeaderApiKeys,
path: '/config/api-keys'
},
{
id: 'config-sessions',
title: this.$strings.HeaderListeningSessions,

View File

@@ -778,10 +778,6 @@ export default {
windowResize() {
this.executeRebuild()
},
socketInit() {
// Server settings are set on socket init
this.executeRebuild()
},
initListeners() {
window.addEventListener('resize', this.windowResize)
@@ -794,7 +790,6 @@ export default {
})
this.$eventBus.$on('bookshelf_clear_selection', this.clearSelectedEntities)
this.$eventBus.$on('socket_init', this.socketInit)
this.$eventBus.$on('user-settings', this.settingsUpdated)
if (this.$root.socket) {
@@ -826,7 +821,6 @@ export default {
}
this.$eventBus.$off('bookshelf_clear_selection', this.clearSelectedEntities)
this.$eventBus.$off('socket_init', this.socketInit)
this.$eventBus.$off('user-settings', this.settingsUpdated)
if (this.$root.socket) {

View File

@@ -116,7 +116,7 @@
</div>
<div class="w-full h-12 px-1 py-2 border-t border-black/20 bg-bg absolute left-0" :style="{ bottom: streamLibraryItem ? '224px' : '65px' }">
<p class="underline font-mono text-xs text-center text-gray-300 leading-3 mb-1" @click="clickChangelog">v{{ $config.version }}</p>
<p class="underline font-mono text-xs text-center text-gray-300 leading-3 mb-1 cursor-pointer" @click="clickChangelog">v{{ $config.version }}</p>
<a v-if="hasUpdate" :href="githubTagUrl" target="_blank" class="text-warning text-xxs text-center block leading-3">Update</a>
<p v-else class="text-xxs text-gray-400 leading-3 text-center italic">{{ Source }}</p>
</div>

View File

@@ -71,9 +71,6 @@ export default {
coverHeight() {
return this.cardHeight
},
userToken() {
return this.store.getters['user/getToken']
},
_author() {
return this.author || {}
},

View File

@@ -13,9 +13,17 @@
<div class="grow" />
<p class="text-sm md:text-base">{{ book.publishedYear }}</p>
</div>
<p v-if="book.author" class="text-gray-300 text-xs md:text-sm">{{ $getString('LabelByAuthor', [book.author]) }}</p>
<p v-if="book.narrator" class="text-gray-400 text-xs">{{ $strings.LabelNarrators }}: {{ book.narrator }}</p>
<p v-if="book.duration" class="text-gray-400 text-xs">{{ $strings.LabelDuration }}: {{ $elapsedPrettyExtended(bookDuration, false) }} {{ bookDurationComparison }}</p>
<div class="flex items-center">
<div>
<p v-if="book.author" class="text-gray-300 text-xs md:text-sm">{{ $getString('LabelByAuthor', [book.author]) }}</p>
<p v-if="book.narrator" class="text-gray-400 text-xs">{{ $strings.LabelNarrators }}: {{ book.narrator }}</p>
<p v-if="book.duration" class="text-gray-400 text-xs">{{ $strings.LabelDuration }}: {{ $elapsedPrettyExtended(bookDuration, false) }} {{ bookDurationComparison }}</p>
</div>
<div class="grow" />
<div v-if="book.matchConfidence" class="rounded-full px-2 py-1 text-xs whitespace-nowrap text-white" :class="book.matchConfidence > 0.95 ? 'bg-success/80' : 'bg-info/80'">{{ $strings.LabelMatchConfidence }}: {{ (book.matchConfidence * 100).toFixed(0) }}%</div>
</div>
<div v-if="book.series?.length" class="flex py-1 -mx-1">
<div v-for="(series, index) in book.series" :key="index" class="bg-white/10 rounded-full px-1 py-0.5 mx-1">
<p class="leading-3 text-xs text-gray-400">

View File

@@ -101,7 +101,8 @@
<!-- Podcast Episode # -->
<div cy-id="podcastEpisodeNumber" v-if="recentEpisodeNumber !== null && !isHovering && !isSelectionMode && !processing" class="absolute rounded-lg bg-black/90 box-shadow-md z-10" :style="{ top: 0.375 + 'em', right: 0.375 + 'em', padding: `${0.1}em ${0.25}em` }">
<p :style="{ fontSize: 0.8 + 'em' }">
Episode<span v-if="recentEpisodeNumber"> #{{ recentEpisodeNumber }}</span>
Episode
<span v-if="recentEpisodeNumber">#{{ recentEpisodeNumber }}</span>
</p>
</div>
@@ -198,7 +199,10 @@ export default {
return this.store.getters['user/getSizeMultiplier']
},
dateFormat() {
return this.store.state.serverSettings.dateFormat
return this.store.getters['getServerSetting']('dateFormat')
},
timeFormat() {
return this.store.getters['getServerSetting']('timeFormat')
},
_libraryItem() {
return this.libraryItem || {}
@@ -345,6 +349,10 @@ export default {
if (this.mediaMetadata.publishedYear) return this.$getString('LabelPublishedDate', [this.mediaMetadata.publishedYear])
return '\u00A0'
}
if (this.orderBy === 'progress') {
if (!this.userProgressLastUpdated) return '\u00A0'
return this.$getString('LabelLastProgressDate', [this.$formatDatetime(this.userProgressLastUpdated, this.dateFormat, this.timeFormat)])
}
return null
},
episodeProgress() {
@@ -377,6 +385,10 @@ export default {
let progressPercent = this.itemIsFinished ? 1 : this.booksInSeries ? this.seriesProgressPercent : this.useEBookProgress ? this.userProgress?.ebookProgress || 0 : this.userProgress?.progress || 0
return Math.max(Math.min(1, progressPercent), 0)
},
userProgressLastUpdated() {
if (!this.userProgress) return null
return this.userProgress.lastUpdate
},
itemIsFinished() {
if (this.booksInSeries) return this.seriesIsFinished
return this.userProgress ? !!this.userProgress.isFinished : false

View File

@@ -71,7 +71,7 @@ export default {
return this.height * this.sizeMultiplier
},
dateFormat() {
return this.store.state.serverSettings.dateFormat
return this.store.getters['getServerSetting']('dateFormat')
},
labelFontSize() {
if (this.width < 160) return 0.75

View File

@@ -94,6 +94,9 @@ export default {
userIsAdminOrUp() {
return this.$store.getters['user/getIsAdminOrUp']
},
userCanAccessExplicitContent() {
return this.$store.getters['user/getUserCanAccessExplicitContent']
},
libraryMediaType() {
return this.$store.getters['libraries/getCurrentLibraryMediaType']
},
@@ -239,6 +242,15 @@ export default {
sublist: false
}
]
if (this.userCanAccessExplicitContent) {
items.push({
text: this.$strings.LabelExplicit,
value: 'explicit',
sublist: false
})
}
if (this.userIsAdminOrUp) {
items.push({
text: this.$strings.LabelShareOpen,
@@ -249,7 +261,7 @@ export default {
return items
},
podcastItems() {
return [
const items = [
{
text: this.$strings.LabelAll,
value: 'all'
@@ -283,6 +295,16 @@ export default {
sublist: false
}
]
if (this.userCanAccessExplicitContent) {
items.push({
text: this.$strings.LabelExplicit,
value: 'explicit',
sublist: false
})
}
return items
},
selectItems() {
if (this.isSeries) return this.seriesItems

View File

@@ -7,7 +7,7 @@
</span>
</button>
<ul v-show="showMenu" class="absolute z-10 mt-1 w-full bg-bg border border-black-200 shadow-lg max-h-96 rounded-md py-1 ring-1 ring-black/5 overflow-auto focus:outline-hidden text-sm" role="menu">
<ul v-show="showMenu" class="librarySortMenu absolute z-10 mt-1 w-full bg-bg border border-black-200 shadow-lg max-h-96 rounded-md py-1 ring-1 ring-black/5 overflow-auto focus:outline-hidden text-sm" role="menu">
<template v-for="item in selectItems">
<li :key="item.value" class="select-none relative py-2 pr-9 cursor-pointer hover:bg-white/5" :class="item.value === selected ? 'bg-white/5 text-yellow-400' : 'text-gray-200 hover:text-white'" role="menuitem" @click="clickedOption(item.value)">
<div class="flex items-center">
@@ -130,6 +130,10 @@ export default {
text: this.$strings.LabelFileModified,
value: 'mtimeMs'
},
{
text: this.$strings.LabelLibrarySortByProgress,
value: 'progress'
},
{
text: this.$strings.LabelRandomly,
value: 'random'
@@ -191,3 +195,9 @@ export default {
}
}
</script>
<style scoped>
.librarySortMenu {
max-height: calc(100vh - 125px);
}
</style>

View File

@@ -39,9 +39,6 @@ export default {
}
},
computed: {
userToken() {
return this.$store.getters['user/getToken']
},
_author() {
return this.author || {}
},

View File

@@ -309,9 +309,9 @@ export default {
} else {
console.log('Account updated', data.user)
if (data.user.id === this.user.id && data.user.token !== this.user.token) {
console.log('Current user token was updated')
this.$store.commit('user/setUserToken', data.user.token)
if (data.user.id === this.user.id && data.user.accessToken !== this.user.accessToken) {
console.log('Current user access token was updated')
this.$store.commit('user/setAccessToken', data.user.accessToken)
}
this.$toast.success(this.$strings.ToastAccountUpdateSuccess)
@@ -351,9 +351,6 @@ export default {
this.$toast.error(errMsg || 'Failed to create account')
})
},
toggleActive() {
this.newUser.isActive = !this.newUser.isActive
},
userTypeUpdated(type) {
this.newUser.permissions = {
download: type !== 'guest',

View File

@@ -0,0 +1,60 @@
<template>
<modals-modal ref="modal" v-model="show" name="api-key-created" :width="800" :height="'unset'" persistent>
<template #outer>
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
<p class="text-3xl text-white truncate">{{ title }}</p>
</div>
</template>
<form @submit.prevent="submitForm">
<div class="px-4 w-full text-sm py-6 rounded-lg bg-bg shadow-lg border border-black-300 overflow-y-auto overflow-x-hidden" style="min-height: 200px; max-height: 80vh">
<div class="w-full p-8">
<p class="text-lg text-white mb-4">{{ $getString('LabelApiKeyCreated', [apiKeyName]) }}</p>
<p class="text-lg text-white mb-4">{{ $strings.LabelApiKeyCreatedDescription }}</p>
<ui-text-input label="API Key" :value="apiKeyKey" readonly show-copy />
<div class="flex justify-end mt-4">
<ui-btn color="bg-primary" @click="show = false">{{ $strings.ButtonClose }}</ui-btn>
</div>
</div>
</div>
</form>
</modals-modal>
</template>
<script>
export default {
props: {
value: Boolean,
apiKey: {
type: Object,
default: () => null
}
},
data() {
return {}
},
computed: {
show: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
},
title() {
return this.$strings.HeaderNewApiKey
},
apiKeyName() {
return this.apiKey?.name || ''
},
apiKeyKey() {
return this.apiKey?.apiKey || ''
}
},
methods: {},
mounted() {}
}
</script>

View File

@@ -0,0 +1,198 @@
<template>
<modals-modal ref="modal" v-model="show" name="api-key" :width="800" :height="'unset'" :processing="processing">
<template #outer>
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
<p class="text-3xl text-white truncate">{{ title }}</p>
</div>
</template>
<form @submit.prevent="submitForm">
<div class="px-4 w-full text-sm py-6 rounded-lg bg-bg shadow-lg border border-black-300 overflow-y-auto overflow-x-hidden" style="min-height: 400px; max-height: 80vh">
<div class="w-full p-8">
<div class="flex py-2">
<div class="w-1/2 px-2">
<ui-text-input-with-label v-model.trim="newApiKey.name" :readonly="!isNew" :label="$strings.LabelName" />
</div>
<div v-if="isNew" class="w-1/2 px-2">
<ui-text-input-with-label v-model.trim="newApiKey.expiresIn" :label="$strings.LabelExpiresInSeconds" type="number" :min="0" />
</div>
</div>
<div class="flex items-center pt-4 pb-2 gap-2">
<div class="flex items-center px-2">
<p class="px-3 font-semibold" id="user-enabled-toggle">{{ $strings.LabelEnable }}</p>
<ui-toggle-switch :disabled="isExpired && !apiKey.isActive" labeledBy="user-enabled-toggle" v-model="newApiKey.isActive" />
</div>
<div v-if="isExpired" class="px-2">
<p class="text-sm text-error">{{ $strings.LabelExpired }}</p>
</div>
</div>
<div class="w-full border-t border-b border-black-200 py-4 px-3 mt-4">
<p class="text-lg mb-2 font-semibold">{{ $strings.LabelApiKeyUser }}</p>
<p class="text-sm mb-2 text-gray-400">{{ $strings.LabelApiKeyUserDescription }}</p>
<ui-select-input v-model="newApiKey.userId" :disabled="isExpired && !apiKey.isActive" :items="userItems" :placeholder="$strings.LabelSelectUser" :label="$strings.LabelApiKeyUser" label-hidden />
</div>
<div class="flex pt-4 px-2">
<div class="grow" />
<ui-btn color="bg-success" type="submit">{{ $strings.ButtonSubmit }}</ui-btn>
</div>
</div>
</div>
</form>
</modals-modal>
</template>
<script>
export default {
props: {
value: Boolean,
apiKey: {
type: Object,
default: () => null
},
users: {
type: Array,
default: () => []
}
},
data() {
return {
processing: false,
newApiKey: {},
isNew: true
}
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.init()
}
}
}
},
computed: {
show: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
},
title() {
return this.isNew ? this.$strings.HeaderNewApiKey : this.$strings.HeaderUpdateApiKey
},
userItems() {
return this.users
.filter((u) => {
// Only show root user if the current user is root
return u.type !== 'root' || this.$store.getters['user/getIsRoot']
})
.map((u) => ({ text: u.username, value: u.id, subtext: u.type }))
},
isExpired() {
if (!this.apiKey || !this.apiKey.expiresAt) return false
return new Date(this.apiKey.expiresAt).getTime() < Date.now()
}
},
methods: {
submitForm() {
if (!this.newApiKey.name) {
this.$toast.error(this.$strings.ToastNameRequired)
return
}
if (!this.newApiKey.userId) {
this.$toast.error(this.$strings.ToastNewApiKeyUserError)
return
}
if (this.isNew) {
this.submitCreateApiKey()
} else {
this.submitUpdateApiKey()
}
},
submitUpdateApiKey() {
if (this.newApiKey.isActive === this.apiKey.isActive && this.newApiKey.userId === this.apiKey.userId) {
this.$toast.info(this.$strings.ToastNoUpdatesNecessary)
this.show = false
return
}
const apiKey = {
isActive: this.newApiKey.isActive,
userId: this.newApiKey.userId
}
this.processing = true
this.$axios
.$patch(`/api/api-keys/${this.apiKey.id}`, apiKey)
.then((data) => {
this.processing = false
if (data.error) {
this.$toast.error(`${this.$strings.ToastFailedToUpdate}: ${data.error}`)
} else {
this.show = false
this.$emit('updated', data.apiKey)
}
})
.catch((error) => {
this.processing = false
console.error('Failed to update apiKey', error)
var errMsg = error.response ? error.response.data || '' : ''
this.$toast.error(errMsg || this.$strings.ToastFailedToUpdate)
})
},
submitCreateApiKey() {
const apiKey = { ...this.newApiKey }
if (this.newApiKey.expiresIn) {
apiKey.expiresIn = parseInt(this.newApiKey.expiresIn)
} else {
delete apiKey.expiresIn
}
this.processing = true
this.$axios
.$post('/api/api-keys', apiKey)
.then((data) => {
this.processing = false
if (data.error) {
this.$toast.error(this.$strings.ToastFailedToCreate + ': ' + data.error)
} else {
this.show = false
this.$emit('created', data.apiKey)
}
})
.catch((error) => {
this.processing = false
console.error('Failed to create apiKey', error)
var errMsg = error.response ? error.response.data || '' : ''
this.$toast.error(errMsg || this.$strings.ToastFailedToCreate)
})
},
init() {
this.isNew = !this.apiKey
if (this.apiKey) {
this.newApiKey = {
name: this.apiKey.name,
isActive: this.apiKey.isActive,
userId: this.apiKey.userId
}
} else {
this.newApiKey = {
name: null,
expiresIn: null,
isActive: true,
userId: null
}
}
}
},
mounted() {}
}
</script>

View File

@@ -79,10 +79,10 @@ export default {
return !this.bookmarks.find((bm) => Math.abs(this.currentTime - bm.time) < 1)
},
dateFormat() {
return this.$store.state.serverSettings.dateFormat
return this.$store.getters['getServerSetting']('dateFormat')
},
timeFormat() {
return this.$store.state.serverSettings.timeFormat
return this.$store.getters['getServerSetting']('timeFormat')
}
},
methods: {

View File

@@ -81,7 +81,7 @@
</div>
<div class="w-full md:w-1/3">
<p v-if="!isMediaItemShareSession" class="font-semibold uppercase text-xs text-gray-400 tracking-wide mb-2 mt-6 md:mt-0">{{ $strings.LabelUser }}</p>
<p v-if="!isMediaItemShareSession" class="mb-1 text-xs">{{ _session.userId }}</p>
<p v-if="!isMediaItemShareSession" class="mb-1 text-xs">{{ username }}</p>
<p class="font-semibold uppercase text-xs text-gray-400 tracking-wide mt-6 mb-2">{{ $strings.LabelMediaPlayer }}</p>
<p class="mb-1">{{ playMethodName }}</p>
@@ -132,6 +132,9 @@ export default {
_session() {
return this.session || {}
},
username() {
return this._session.user?.username || this._session.userId || ''
},
deviceInfo() {
return this._session.deviceInfo || {}
},
@@ -159,10 +162,10 @@ export default {
return 'Unknown'
},
dateFormat() {
return this.$store.state.serverSettings.dateFormat
return this.$store.getters['getServerSetting']('dateFormat')
},
timeFormat() {
return this.$store.state.serverSettings.timeFormat
return this.$store.getters['getServerSetting']('timeFormat')
},
isOpenSession() {
return !!this._session.open

View File

@@ -23,7 +23,7 @@ export default {
processing: Boolean,
persistent: {
type: Boolean,
default: true
default: false
},
width: {
type: [String, Number],
@@ -99,7 +99,7 @@ export default {
this.preventClickoutside = false
return
}
if (this.processing && this.persistent) return
if (this.processing || this.persistent) return
if (ev.srcElement && ev.srcElement.classList.contains('modal-bg')) {
this.show = false
}

View File

@@ -144,7 +144,7 @@ export default {
expirationDateString() {
if (!this.expireDurationSeconds) return this.$strings.LabelPermanent
const dateMs = Date.now() + this.expireDurationSeconds * 1000
return this.$formatDatetime(dateMs, this.$store.state.serverSettings.dateFormat, this.$store.state.serverSettings.timeFormat)
return this.$formatDatetime(dateMs, this.$store.getters['getServerSetting']('dateFormat'), this.$store.getters['getServerSetting']('timeFormat'))
}
},
methods: {

View File

@@ -40,7 +40,7 @@ export default {
}
},
dateFormat() {
return this.$store.state.serverSettings.dateFormat
return this.$store.getters['getServerSetting']('dateFormat')
},
releasesToShow() {
return this.versionData?.releasesToShow || []

View File

@@ -29,9 +29,6 @@ export default {
media() {
return this.libraryItem.media || {}
},
userToken() {
return this.$store.getters['user/getToken']
},
userCanUpdate() {
return this.$store.getters['user/getUserCanUpdate']
},

View File

@@ -35,7 +35,14 @@
<widgets-podcast-type-indicator :type="episode.episodeType" />
</div>
<p v-if="episode.subtitle" class="mb-1 text-sm text-gray-300 line-clamp-2">{{ episode.subtitle }}</p>
<p class="text-xs text-gray-300">Published {{ episode.publishedAt ? $dateDistanceFromNow(episode.publishedAt) : 'Unknown' }}</p>
<div class="flex items-center space-x-2">
<!-- published -->
<p class="text-xs text-gray-300 w-40">Published {{ episode.publishedAt ? $dateDistanceFromNow(episode.publishedAt) : 'Unknown' }}</p>
<!-- duration -->
<p v-if="episode.durationSeconds && !isNaN(episode.durationSeconds)" class="text-xs text-gray-300 min-w-28">{{ $strings.LabelDuration }}: {{ $elapsedPretty(episode.durationSeconds) }}</p>
<!-- size -->
<p v-if="episode.enclosure?.length && !isNaN(episode.enclosure.length) && Number(episode.enclosure.length) > 0" class="text-xs text-gray-300">{{ $strings.LabelSize }}: {{ $bytesPretty(Number(episode.enclosure.length)) }}</p>
</div>
</div>
</div>
</div>

View File

@@ -11,7 +11,7 @@
{{ $getString('MessageConfirmRemoveEpisode', [episodeTitle]) }}
</p>
<p v-else class="text-lg text-gray-200 mb-4">{{ $getString('MessageConfirmRemoveEpisodes', [episodes.length]) }}</p>
<p class="text-xs font-semibold text-warning/90">Note: This does not delete the audio file unless toggling "Hard delete file"</p>
<p class="text-xs font-semibold text-warning/90">{{ $strings.MessageConfirmRemoveEpisodeNote }}</p>
</div>
<div class="flex justify-between items-center pt-4">
<ui-checkbox v-model="hardDeleteFile" :label="$strings.LabelHardDeleteFile" check-color="error" checkbox-bg="bg" small label-class="text-base text-gray-200 pl-3" />

View File

@@ -16,7 +16,7 @@
</div>
</div>
<p dir="auto" class="text-lg font-semibold mb-6">{{ title }}</p>
<div v-if="description" dir="auto" class="default-style less-spacing" v-html="description" />
<div v-if="description" dir="auto" class="default-style less-spacing" @click="handleDescriptionClick" v-html="description" />
<p v-else class="mb-2">{{ $strings.MessageNoDescription }}</p>
<div class="w-full h-px bg-white/5 my-4" />
@@ -34,6 +34,12 @@
{{ audioFileSize }}
</p>
</div>
<div class="grow">
<p class="font-semibold text-xs mb-1">{{ $strings.LabelDuration }}</p>
<p class="mb-2 text-xs">
{{ audioFileDuration }}
</p>
</div>
</div>
</div>
</modals-modal>
@@ -68,7 +74,7 @@ export default {
return this.episode.title || 'No Episode Title'
},
description() {
return this.episode.description || ''
return this.parseDescription(this.episode.description || '')
},
media() {
return this.libraryItem?.media || {}
@@ -90,11 +96,49 @@ export default {
return this.$bytesPretty(size)
},
audioFileDuration() {
const duration = this.episode.duration || 0
return this.$elapsedPretty(duration)
},
bookCoverAspectRatio() {
return this.$store.getters['libraries/getBookCoverAspectRatio']
}
},
methods: {},
methods: {
handleDescriptionClick(e) {
if (e.target.matches('span.time-marker')) {
const time = parseInt(e.target.dataset.time)
if (!isNaN(time)) {
this.$eventBus.$emit('play-item', {
episodeId: this.episodeId,
libraryItemId: this.libraryItem.id,
startTime: time
})
}
e.preventDefault()
}
},
parseDescription(description) {
const timeMarkerLinkRegex = /<a href="#([^"]*?\b\d{1,2}:\d{1,2}(?::\d{1,2})?)">(.*?)<\/a>/g
const timeMarkerRegex = /\b\d{1,2}:\d{1,2}(?::\d{1,2})?\b/g
function convertToSeconds(time) {
const timeParts = time.split(':').map(Number)
return timeParts.reduce((acc, part, index) => acc * 60 + part, 0)
}
return description
.replace(timeMarkerLinkRegex, (match, href, displayTime) => {
const time = displayTime.match(timeMarkerRegex)[0]
const seekTimeInSeconds = convertToSeconds(time)
return `<span class="time-marker cursor-pointer text-blue-400 hover:text-blue-300" data-time="${seekTimeInSeconds}">${displayTime}</span>`
})
.replace(timeMarkerRegex, (match) => {
const seekTimeInSeconds = convertToSeconds(match)
return `<span class="time-marker cursor-pointer text-blue-400 hover:text-blue-300" data-time="${seekTimeInSeconds}">${match}</span>`
})
}
},
mounted() {}
}
</script>

View File

@@ -129,9 +129,6 @@ export default {
return `${hoursRounded}h`
}
},
token() {
return this.$store.getters['user/getToken']
},
timeRemaining() {
if (this.useChapterTrack && this.currentChapter) {
var currChapTime = this.currentTime - this.currentChapter.start

View File

@@ -104,9 +104,6 @@ export default {
}
},
computed: {
userToken() {
return this.$store.getters['user/getToken']
},
libraryItemId() {
return this.libraryItem?.id
},
@@ -234,10 +231,7 @@ export default {
async extract() {
this.loading = true
var buff = await this.$axios.$get(this.ebookUrl, {
responseType: 'blob',
headers: {
Authorization: `Bearer ${this.userToken}`
}
responseType: 'blob'
})
const archive = await Archive.open(buff)
const originalFilesObject = await archive.getFilesObject()

View File

@@ -57,9 +57,6 @@ export default {
}
},
computed: {
userToken() {
return this.$store.getters['user/getToken']
},
/** @returns {string} */
libraryItemId() {
return this.libraryItem?.id
@@ -97,27 +94,37 @@ export default {
},
ebookUrl() {
if (this.fileId) {
return `${this.$config.routerBasePath}/api/items/${this.libraryItemId}/ebook/${this.fileId}`
return `/api/items/${this.libraryItemId}/ebook/${this.fileId}`
}
return `${this.$config.routerBasePath}/api/items/${this.libraryItemId}/ebook`
return `/api/items/${this.libraryItemId}/ebook`
},
themeRules() {
const isDark = this.ereaderSettings.theme === 'dark'
const fontColor = isDark ? '#fff' : '#000'
const backgroundColor = isDark ? 'rgb(35 35 35)' : 'rgb(255, 255, 255)'
const theme = this.ereaderSettings.theme
const isDark = theme === 'dark'
const isSepia = theme === 'sepia'
const fontColor = isDark
? '#fff'
: isSepia
? '#5b4636'
: '#000'
const backgroundColor = isDark
? 'rgb(35 35 35)'
: isSepia
? 'rgb(244, 236, 216)'
: 'rgb(255, 255, 255)'
const lineSpacing = this.ereaderSettings.lineSpacing / 100
const fontScale = this.ereaderSettings.fontScale / 100
const textStroke = this.ereaderSettings.textStroke / 100
const fontScale = this.ereaderSettings.fontScale / 100
const textStroke = this.ereaderSettings.textStroke / 100
return {
'*': {
color: `${fontColor}!important`,
'background-color': `${backgroundColor}!important`,
'line-height': lineSpacing * fontScale + 'rem!important',
'-webkit-text-stroke': textStroke + 'px ' + fontColor + '!important'
'line-height': `${lineSpacing * fontScale}rem!important`,
'-webkit-text-stroke': `${textStroke}px ${fontColor}!important`
},
a: {
color: `${fontColor}!important`
@@ -309,14 +316,24 @@ export default {
/** @type {EpubReader} */
const reader = this
// Use axios to make request because we have token refresh logic in interceptor
const customRequest = async (url) => {
try {
return this.$axios.$get(url, {
responseType: 'arraybuffer'
})
} catch (error) {
console.error('EpubReader.initEpub customRequest failed:', error)
throw error
}
}
/** @type {ePub.Book} */
reader.book = new ePub(reader.ebookUrl, {
width: this.readerWidth,
height: this.readerHeight - 50,
openAs: 'epub',
requestHeaders: {
Authorization: `Bearer ${this.userToken}`
}
requestMethod: customRequest
})
/** @type {ePub.Rendition} */
@@ -337,29 +354,33 @@ export default {
this.applyTheme()
})
reader.book.ready.then(() => {
// set up event listeners
reader.rendition.on('relocated', reader.relocated)
reader.rendition.on('keydown', reader.keyUp)
reader.book.ready
.then(() => {
// set up event listeners
reader.rendition.on('relocated', reader.relocated)
reader.rendition.on('keydown', reader.keyUp)
reader.rendition.on('touchstart', (event) => {
this.$emit('touchstart', event)
})
reader.rendition.on('touchend', (event) => {
this.$emit('touchend', event)
})
// load ebook cfi locations
const savedLocations = this.loadLocations()
if (savedLocations) {
reader.book.locations.load(savedLocations)
} else {
reader.book.locations.generate().then(() => {
this.checkSaveLocations(reader.book.locations.save())
reader.rendition.on('touchstart', (event) => {
this.$emit('touchstart', event)
})
}
this.getChapters()
})
reader.rendition.on('touchend', (event) => {
this.$emit('touchend', event)
})
// load ebook cfi locations
const savedLocations = this.loadLocations()
if (savedLocations) {
reader.book.locations.load(savedLocations)
} else {
reader.book.locations.generate().then(() => {
this.checkSaveLocations(reader.book.locations.save())
})
}
this.getChapters()
})
.catch((error) => {
console.error('EpubReader.initEpub failed:', error)
})
},
getChapters() {
// Load the list of chapters in the book. See https://github.com/futurepress/epub.js/issues/759

View File

@@ -26,9 +26,6 @@ export default {
return {}
},
computed: {
userToken() {
return this.$store.getters['user/getToken']
},
libraryItemId() {
return this.libraryItem?.id
},
@@ -96,11 +93,8 @@ export default {
},
async initMobi() {
// Fetch mobi file as blob
var buff = await this.$axios.$get(this.ebookUrl, {
responseType: 'blob',
headers: {
Authorization: `Bearer ${this.userToken}`
}
const buff = await this.$axios.$get(this.ebookUrl, {
responseType: 'blob'
})
var reader = new FileReader()
reader.onload = async (event) => {

View File

@@ -55,7 +55,8 @@ export default {
loadedRatio: 0,
page: 1,
numPages: 0,
pdfDocInitParams: null
pdfDocInitParams: null,
isRefreshing: false
}
},
computed: {
@@ -152,7 +153,34 @@ export default {
this.page++
this.updateProgress()
},
error(err) {
async refreshToken() {
if (this.isRefreshing) return
this.isRefreshing = true
const newAccessToken = await this.$store.dispatch('user/refreshToken').catch((error) => {
console.error('Failed to refresh token', error)
return null
})
if (!newAccessToken) {
// Redirect to login on failed refresh
this.$router.push('/login')
return
}
// Force Vue to re-render the PDF component by creating a new object
this.pdfDocInitParams = {
url: this.ebookUrl,
httpHeaders: {
Authorization: `Bearer ${newAccessToken}`
}
}
this.isRefreshing = false
},
async error(err) {
if (err && err.status === 401) {
console.log('Received 401 error, refreshing token')
await this.refreshToken()
return
}
console.error(err)
},
resize() {

View File

@@ -1,5 +1,5 @@
<template>
<div v-if="show" id="reader" :data-theme="ereaderTheme" class="group absolute top-0 left-0 w-full z-60 data-[theme=dark]:bg-primary data-[theme=dark]:text-white data-[theme=light]:bg-white data-[theme=light]:text-black" :class="{ 'reader-player-open': !!streamLibraryItem }">
<div v-if="show" id="reader" :data-theme="ereaderTheme" class="group absolute top-0 left-0 w-full z-60 data-[theme=dark]:bg-primary data-[theme=dark]:text-white data-[theme=light]:bg-white data-[theme=light]:text-black data-[theme=sepia]:bg-[rgb(244,236,216)] data-[theme=sepia]:text-[#5b4636]" :class="{ 'reader-player-open': !!streamLibraryItem }">
<div class="absolute top-4 left-4 z-20 flex items-center">
<button v-if="isEpub" @click="toggleToC" type="button" aria-label="Table of contents menu" class="inline-flex opacity-80 hover:opacity-100">
<span class="material-symbols text-2xl">menu</span>
@@ -27,7 +27,12 @@
<!-- TOC side nav -->
<div v-if="tocOpen" class="w-full h-full overflow-y-scroll absolute inset-0 bg-black/20 z-20" @click.stop.prevent="toggleToC"></div>
<div v-if="isEpub" class="w-96 h-full max-h-full absolute top-0 left-0 shadow-xl transition-transform z-30 group-data-[theme=dark]:bg-primary group-data-[theme=dark]:text-white group-data-[theme=light]:bg-white group-data-[theme=light]:text-black" :class="tocOpen ? 'translate-x-0' : '-translate-x-96'" @click.stop.prevent>
<div
v-if="isEpub"
class="w-96 h-full max-h-full absolute top-0 left-0 shadow-xl transition-transform z-30 group-data-[theme=dark]:bg-primary group-data-[theme=dark]:text-white group-data-[theme=light]:bg-white group-data-[theme=light]:text-black group-data-[theme=sepia]:bg-[rgb(244,236,216)] group-data-[theme=sepia]:text-[#5b4636]"
:class="tocOpen ? 'translate-x-0' : '-translate-x-96'"
@click.stop.prevent
>
<div class="flex flex-col p-4 h-full">
<div class="flex items-center mb-2">
<button @click.stop.prevent="toggleToC" type="button" aria-label="Close table of contents" class="inline-flex opacity-80 hover:opacity-100">
@@ -37,7 +42,7 @@
<p class="text-lg font-semibold ml-2">{{ $strings.HeaderTableOfContents }}</p>
</div>
<form @submit.prevent="searchBook" @click.stop.prevent>
<ui-text-input clearable ref="input" @clear="searchBook" v-model="searchQuery" :placeholder="$strings.PlaceholderSearch" class="h-8 w-full text-sm flex mb-2" />
<ui-text-input clearable ref="input" @clear="searchBook" v-model="searchQuery" :placeholder="$strings.PlaceholderSearch" custom-input-class="text-inherit !bg-inherit" class="h-8 w-full text-sm flex mb-2" />
</form>
<div class="overflow-y-auto">
@@ -181,6 +186,10 @@ export default {
text: this.$strings.LabelThemeDark,
value: 'dark'
},
{
text: this.$strings.LabelThemeSepia,
value: 'sepia'
},
{
text: this.$strings.LabelThemeLight,
value: 'light'
@@ -266,9 +275,6 @@ export default {
isComic() {
return this.ebookFormat == 'cbz' || this.ebookFormat == 'cbr'
},
userToken() {
return this.$store.getters['user/getToken']
},
keepProgress() {
return this.$store.state.ereaderKeepProgress
},

View File

@@ -152,7 +152,7 @@ export default {
this.showingTooltipIndex = index
this.tooltipEl.style.display = 'block'
this.tooltipTextEl.innerHTML = block.value ? `<strong>${this.$elapsedPretty(block.value, true)} listening</strong> on ${block.datePretty}` : `No listening sessions on ${block.datePretty}`
this.tooltipTextEl.innerHTML = block.value ? this.$getString('MessageHeatmapListeningTimeTooltip', [this.$elapsedPrettyLocalized(block.value, true), block.datePretty]) : this.$getString('MessageHeatmapNoListeningSessions', [block.datePretty])
const calculateRect = this.tooltipEl.getBoundingClientRect()

View File

@@ -0,0 +1,177 @@
<template>
<div>
<div class="text-center">
<table v-if="apiKeys.length > 0" id="api-keys">
<tr>
<th>{{ $strings.LabelName }}</th>
<th class="w-44">{{ $strings.LabelApiKeyUser }}</th>
<th class="w-32">{{ $strings.LabelExpiresAt }}</th>
<th class="w-32">{{ $strings.LabelCreatedAt }}</th>
<th class="w-32"></th>
</tr>
<tr v-for="apiKey in apiKeys" :key="apiKey.id" :class="apiKey.isActive ? '' : 'bg-error/10!'">
<td>
<div class="flex items-center">
<p class="pl-2 truncate">{{ apiKey.name }}</p>
</div>
</td>
<td class="text-xs">
<nuxt-link v-if="apiKey.user" :to="`/config/users/${apiKey.user.id}`" class="text-xs hover:underline">
{{ apiKey.user.username }}
</nuxt-link>
<p v-else class="text-xs">Error</p>
</td>
<td class="text-xs">
<p v-if="apiKey.expiresAt" class="text-xs" :title="apiKey.expiresAt">{{ getExpiresAtText(apiKey) }}</p>
<p v-else class="text-xs">{{ $strings.LabelExpiresNever }}</p>
</td>
<td class="text-xs font-mono">
<ui-tooltip direction="top" :text="$formatJsDatetime(new Date(apiKey.createdAt), dateFormat, timeFormat)">
{{ $formatJsDate(new Date(apiKey.createdAt), dateFormat) }}
</ui-tooltip>
</td>
<td class="py-0">
<div class="w-full flex justify-left">
<div class="h-8 w-8 flex items-center justify-center text-white/50 hover:text-white/100 cursor-pointer" @click.stop="editApiKey(apiKey)">
<button type="button" :aria-label="$strings.ButtonEdit" class="material-symbols text-base">edit</button>
</div>
<div class="h-8 w-8 flex items-center justify-center text-white/50 hover:text-error cursor-pointer" @click.stop="deleteApiKeyClick(apiKey)">
<button type="button" :aria-label="$strings.ButtonDelete" class="material-symbols text-base">delete</button>
</div>
</div>
</td>
</tr>
</table>
<p v-else class="text-base text-gray-300 py-4">{{ $strings.LabelNoApiKeys }}</p>
</div>
</div>
</template>
<script>
export default {
data() {
return {
apiKeys: [],
isDeletingApiKey: false
}
},
computed: {
dateFormat() {
return this.$store.state.serverSettings.dateFormat
},
timeFormat() {
return this.$store.state.serverSettings.timeFormat
}
},
methods: {
getExpiresAtText(apiKey) {
if (new Date(apiKey.expiresAt).getTime() < Date.now()) {
return this.$strings.LabelExpired
}
return this.$formatJsDatetime(new Date(apiKey.expiresAt), this.dateFormat, this.timeFormat)
},
deleteApiKeyClick(apiKey) {
if (this.isDeletingApiKey) return
const payload = {
message: this.$getString('MessageConfirmDeleteApiKey', [apiKey.name]),
callback: (confirmed) => {
if (confirmed) {
this.deleteApiKey(apiKey)
}
},
type: 'yesNo'
}
this.$store.commit('globals/setConfirmPrompt', payload)
},
deleteApiKey(apiKey) {
this.isDeletingApiKey = true
this.$axios
.$delete(`/api/api-keys/${apiKey.id}`)
.then((data) => {
if (data.error) {
this.$toast.error(data.error)
} else {
this.removeApiKey(apiKey.id)
this.$emit('numApiKeys', this.apiKeys.length)
}
})
.catch((error) => {
console.error('Failed to delete apiKey', error)
this.$toast.error(this.$strings.ToastFailedToDelete)
})
.finally(() => {
this.isDeletingApiKey = false
})
},
editApiKey(apiKey) {
this.$emit('edit', apiKey)
},
addApiKey(apiKey) {
this.apiKeys.push(apiKey)
},
removeApiKey(apiKeyId) {
this.apiKeys = this.apiKeys.filter((a) => a.id !== apiKeyId)
},
updateApiKey(apiKey) {
this.apiKeys = this.apiKeys.map((a) => (a.id === apiKey.id ? apiKey : a))
},
loadApiKeys() {
this.$axios
.$get('/api/api-keys')
.then((res) => {
this.apiKeys = res.apiKeys.sort((a, b) => {
return a.createdAt - b.createdAt
})
this.$emit('numApiKeys', this.apiKeys.length)
})
.catch((error) => {
console.error('Failed to load apiKeys', error)
})
}
},
mounted() {
this.loadApiKeys()
}
}
</script>
<style>
#api-keys {
table-layout: fixed;
border-collapse: collapse;
border: 1px solid #474747;
width: 100%;
}
#api-keys td,
#api-keys th {
/* border: 1px solid #2e2e2e; */
padding: 8px 8px;
text-align: left;
}
#api-keys td.py-0 {
padding: 0px 8px;
}
#api-keys tr:nth-child(even) {
background-color: #373838;
}
#api-keys tr:nth-child(odd) {
background-color: #2f2f2f;
}
#api-keys tr:hover {
background-color: #444;
}
#api-keys th {
font-size: 0.8rem;
font-weight: 600;
padding-top: 5px;
padding-bottom: 5px;
background-color: #272727;
}
</style>

View File

@@ -78,10 +78,10 @@ export default {
return this.$store.getters['user/getToken']
},
dateFormat() {
return this.$store.state.serverSettings.dateFormat
return this.$store.getters['getServerSetting']('dateFormat')
},
timeFormat() {
return this.$store.state.serverSettings.timeFormat
return this.$store.getters['getServerSetting']('timeFormat')
}
},
methods: {

View File

@@ -49,9 +49,6 @@ export default {
libraryItemId() {
return this.libraryItem.id
},
userToken() {
return this.$store.getters['user/getToken']
},
userCanDownload() {
return this.$store.getters['user/getUserCanDownload']
},

View File

@@ -53,9 +53,6 @@ export default {
libraryItemId() {
return this.libraryItem.id
},
userToken() {
return this.$store.getters['user/getToken']
},
userCanDownload() {
return this.$store.getters['user/getUserCanDownload']
},

View File

@@ -76,10 +76,10 @@ export default {
return usermap
},
dateFormat() {
return this.$store.state.serverSettings.dateFormat
return this.$store.getters['getServerSetting']('dateFormat')
},
timeFormat() {
return this.$store.state.serverSettings.timeFormat
return this.$store.getters['getServerSetting']('timeFormat')
}
},
methods: {

View File

@@ -112,7 +112,7 @@ export default {
return this.episode?.publishedAt
},
dateFormat() {
return this.store.state.serverSettings.dateFormat
return this.store.getters['getServerSetting']('dateFormat')
},
itemProgress() {
return this.store.getters['user/getUserMediaProgress'](this.libraryItemId, this.episodeId)

View File

@@ -239,10 +239,10 @@ export default {
})
},
dateFormat() {
return this.$store.state.serverSettings.dateFormat
return this.$store.getters['getServerSetting']('dateFormat')
},
timeFormat() {
return this.$store.state.serverSettings.timeFormat
return this.$store.getters['getServerSetting']('timeFormat')
}
},
methods: {

View File

@@ -85,9 +85,6 @@ export default {
this.$emit('input', val)
}
},
userToken() {
return this.$store.getters['user/getToken']
},
wrapperClass() {
var classes = []
if (this.disabled) classes.push('bg-black-300')

View File

@@ -1,9 +1,9 @@
<template>
<div class="relative w-full">
<p v-if="label" class="text-sm font-semibold px-1" :class="disabled ? 'text-gray-300' : ''">{{ label }}</p>
<p v-if="label && !labelHidden" class="text-sm font-semibold px-1" :class="disabled ? 'text-gray-300' : ''">{{ label }}</p>
<button ref="buttonWrapper" type="button" :aria-label="longLabel" :disabled="disabled" class="relative w-full border rounded-sm shadow-xs pl-3 pr-8 py-2 text-left sm:text-sm" :class="buttonClass" aria-haspopup="listbox" aria-expanded="true" @click.stop.prevent="clickShowMenu">
<span class="flex items-center">
<span class="block truncate font-sans" :class="{ 'font-semibold': selectedSubtext, 'text-sm': small }">{{ selectedText }}</span>
<span class="block truncate font-sans" :class="{ 'font-semibold': selectedSubtext, 'text-sm': small, 'text-gray-400': !selectedText }">{{ selectedText || placeholder }}</span>
<span v-if="selectedSubtext">:&nbsp;</span>
<span v-if="selectedSubtext" class="font-normal block truncate font-sans text-sm text-gray-400">{{ selectedSubtext }}</span>
</span>
@@ -36,10 +36,15 @@ export default {
type: String,
default: ''
},
labelHidden: Boolean,
items: {
type: Array,
default: () => []
},
placeholder: {
type: String,
default: ''
},
disabled: Boolean,
small: Boolean,
menuMaxHeight: {

View File

@@ -6,7 +6,7 @@
<em v-if="note" class="font-normal text-xs pl-2">{{ note }}</em>
</label>
</slot>
<ui-text-input :placeholder="placeholder || label" :inputId="identifier" ref="input" v-model="inputValue" :disabled="disabled" :readonly="readonly" :type="type" :show-copy="showCopy" class="w-full" :class="inputClass" :trim-whitespace="trimWhitespace" @blur="inputBlurred" />
<ui-text-input :placeholder="placeholder || label" :inputId="identifier" ref="input" v-model="inputValue" :disabled="disabled" :readonly="readonly" :type="type" :min="min" :show-copy="showCopy" class="w-full" :class="inputClass" :trim-whitespace="trimWhitespace" @blur="inputBlurred" />
</div>
</template>
@@ -21,6 +21,7 @@ export default {
type: String,
default: 'text'
},
min: [String, Number],
readonly: Boolean,
disabled: Boolean,
inputClass: String,

View File

@@ -318,10 +318,8 @@ export default {
}
},
handleAttachmentAdd(event) {
// Prevent pasting in images from the browser
if (!event.attachment.file) {
event.attachment.remove()
}
// Prevent pasting in images/any files from the browser
event.attachment.remove()
}
},
mounted() {

View File

@@ -85,7 +85,7 @@ export default {
nextRun() {
if (!this.cronExpression) return ''
const parsed = this.$getNextScheduledDate(this.cronExpression)
return this.$formatJsDatetime(parsed, this.$store.state.serverSettings.dateFormat, this.$store.state.serverSettings.timeFormat) || ''
return this.$formatJsDatetime(parsed, this.$store.getters['getServerSetting']('dateFormat'), this.$store.getters['getServerSetting']('timeFormat')) || ''
},
description() {
if ((this.selectedInterval !== 'custom' || !this.selectedWeekdays.length) && this.selectedInterval !== 'daily') return ''

View File

@@ -143,10 +143,18 @@ export default {
localStorage.setItem('embedMetadataCodec', val)
},
getEncodingOptions() {
return {
codec: this.selectedCodec || 'aac',
bitrate: this.selectedBitrate || '128k',
channels: this.selectedChannels || 2
if (this.showAdvancedView) {
return {
codec: this.customCodec || this.selectedCodec || 'aac',
bitrate: this.customBitrate || this.selectedBitrate || '128k',
channels: this.customChannels || this.selectedChannels || 2
}
} else {
return {
codec: this.selectedCodec || 'aac',
bitrate: this.selectedBitrate || '128k',
channels: this.selectedChannels || 2
}
}
},
setPreset() {

View File

@@ -248,4 +248,4 @@ export default {
transform: scale(0);
}
}
</style>
</style>

View File

@@ -109,4 +109,4 @@ export default {
}
}
}
</script>
</script>

View File

@@ -40,6 +40,7 @@ describe('LazySeriesCard', () => {
},
$store: {
getters: {
getServerSetting: () => 'MM/dd/yyyy',
'user/getUserCanUpdate': true,
'user/getUserMediaProgress': (id) => null,
'user/getSizeMultiplier': 1,

View File

@@ -33,6 +33,7 @@ export default {
return {
socket: null,
isSocketConnected: false,
isSocketAuthenticated: false,
isFirstSocketConnection: true,
socketConnectionToastId: null,
currentLang: null,
@@ -81,9 +82,28 @@ export default {
document.body.classList.add('app-bar')
}
},
tokenRefreshed(newAccessToken) {
if (this.isSocketConnected && !this.isSocketAuthenticated) {
console.log('[SOCKET] Re-authenticating socket after token refresh')
this.socket.emit('auth', newAccessToken)
}
},
updateSocketConnectionToast(content, type, timeout) {
if (this.socketConnectionToastId !== null && this.socketConnectionToastId !== undefined) {
this.$toast.update(this.socketConnectionToastId, { content: content, options: { timeout: timeout, type: type, closeButton: false, position: 'bottom-center', onClose: () => null, closeOnClick: timeout !== null } }, false)
const toastUpdateOptions = {
content: content,
options: {
timeout: timeout,
type: type,
closeButton: false,
position: 'bottom-center',
onClose: () => {
this.socketConnectionToastId = null
},
closeOnClick: timeout !== null
}
}
this.$toast.update(this.socketConnectionToastId, toastUpdateOptions, false)
} else {
this.socketConnectionToastId = this.$toast[type](content, { position: 'bottom-center', timeout: timeout, closeButton: false, closeOnClick: timeout !== null })
}
@@ -109,7 +129,7 @@ export default {
this.updateSocketConnectionToast(this.$strings.ToastSocketDisconnected, 'error', null)
},
reconnect() {
console.error('[SOCKET] reconnected')
console.log('[SOCKET] reconnected')
},
reconnectAttempt(val) {
console.log(`[SOCKET] reconnect attempt ${val}`)
@@ -120,6 +140,10 @@ export default {
reconnectFailed() {
console.error('[SOCKET] reconnect failed')
},
authFailed(payload) {
console.error('[SOCKET] auth failed', payload.message)
this.isSocketAuthenticated = false
},
init(payload) {
console.log('Init Payload', payload)
@@ -127,7 +151,7 @@ export default {
this.$store.commit('users/setUsersOnline', payload.usersOnline)
}
this.$eventBus.$emit('socket_init')
this.isSocketAuthenticated = true
},
streamOpen(stream) {
if (this.$refs.mediaPlayerContainer) this.$refs.mediaPlayerContainer.streamOpen(stream)
@@ -354,6 +378,15 @@ export default {
this.$store.commit('scanners/removeCustomMetadataProvider', provider)
},
initializeSocket() {
if (this.$root.socket) {
// Can happen in dev due to hot reload
console.warn('Socket already initialized')
this.socket = this.$root.socket
this.isSocketConnected = this.$root.socket?.connected
this.isFirstSocketConnection = false
this.socketConnectionToastId = null
return
}
this.socket = this.$nuxtSocket({
name: process.env.NODE_ENV === 'development' ? 'dev' : 'prod',
persist: 'main',
@@ -364,6 +397,7 @@ export default {
path: `${this.$config.routerBasePath}/socket.io`
})
this.$root.socket = this.socket
this.isSocketAuthenticated = false
console.log('Socket initialized')
// Pre-defined socket events
@@ -377,6 +411,7 @@ export default {
// Event received after authorizing socket
this.socket.on('init', this.init)
this.socket.on('auth_failed', this.authFailed)
// Stream Listeners
this.socket.on('stream_open', this.streamOpen)
@@ -571,6 +606,7 @@ export default {
this.updateBodyClass()
this.resize()
this.$eventBus.$on('change-lang', this.changeLanguage)
this.$eventBus.$on('token_refreshed', this.tokenRefreshed)
window.addEventListener('resize', this.resize)
window.addEventListener('keydown', this.keyDown)
@@ -594,6 +630,7 @@ export default {
},
beforeDestroy() {
this.$eventBus.$off('change-lang', this.changeLanguage)
this.$eventBus.$off('token_refreshed', this.tokenRefreshed)
window.removeEventListener('resize', this.resize)
window.removeEventListener('keydown', this.keyDown)
}

View File

@@ -73,7 +73,8 @@ module.exports = {
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
baseURL: routerBasePath
baseURL: routerBasePath,
progress: false
},
// nuxt/pwa https://pwa.nuxtjs.org

View File

@@ -1,12 +1,12 @@
{
"name": "audiobookshelf-client",
"version": "2.23.0",
"version": "2.28.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "audiobookshelf-client",
"version": "2.23.0",
"version": "2.28.0",
"license": "ISC",
"dependencies": {
"@nuxtjs/axios": "^5.13.6",

View File

@@ -1,6 +1,6 @@
{
"name": "audiobookshelf-client",
"version": "2.23.0",
"version": "2.28.0",
"buildNumber": 1,
"description": "Self-hosted audiobook and podcast client",
"main": "index.js",

View File

@@ -182,18 +182,19 @@ export default {
password: this.password,
newPassword: this.newPassword
})
.then((res) => {
if (res.success) {
this.$toast.success(this.$strings.ToastUserPasswordChangeSuccess)
this.resetForm()
} else {
this.$toast.error(res.error || this.$strings.ToastUnknownError)
}
this.changingPassword = false
.then(() => {
this.$toast.success(this.$strings.ToastUserPasswordChangeSuccess)
this.resetForm()
})
.catch((error) => {
console.error(error)
this.$toast.error(this.$strings.ToastUnknownError)
console.error('Failed to change password', error)
let errorMessage = this.$strings.ToastUnknownError
if (error.response?.data && typeof error.response.data === 'string') {
errorMessage = error.response.data
}
this.$toast.error(errorMessage)
})
.finally(() => {
this.changingPassword = false
})
},

View File

@@ -572,7 +572,7 @@ export default {
if (data.error) {
this.asinError = this.$getString(data.stringKey)
} else {
console.log('Chapter data', data)
console.log('Chapter data', { ...data })
this.chapterData = this.removeBranding ? this.removeBrandingFromData(data) : data
}
})
@@ -609,6 +609,11 @@ export default {
data.chapters.pop()
}
// Remove Branding durations from Runtime totals
data.runtimeLengthMs -= introDuration + outroDuration
data.runtimeLengthSec = Math.floor(data.runtimeLengthMs / 1000)
console.log('Brandless Chapter data', data)
return data
} catch {
return data

View File

@@ -28,14 +28,14 @@
<div class="flex justify-center flex-wrap lg:flex-nowrap gap-4">
<div class="w-full max-w-2xl border border-white/10 bg-bg">
<div class="flex py-2 px-4">
<div class="w-1/3 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelMetaTag }}</div>
<div class="w-2/3 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelValue }}</div>
<div class="w-28 min-w-28 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelMetaTag }}</div>
<div class="grow text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelValue }}</div>
</div>
<div class="w-full max-h-72 overflow-auto">
<template v-for="(value, key, index) in metadataObject">
<div :key="key" class="flex py-1 px-4 text-sm" :class="index % 2 === 0 ? 'bg-primary/25' : ''">
<div class="w-1/3 font-semibold">{{ key }}</div>
<div class="w-2/3">
<div class="w-28 min-w-28 font-semibold">{{ key }}</div>
<div class="grow">
{{ value }}
</div>
</div>
@@ -45,18 +45,18 @@
<div class="w-full max-w-2xl border border-white/10 bg-bg">
<div class="flex py-2 px-4 bg-primary/25">
<div class="grow text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelChapterTitle }}</div>
<div class="w-24 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelStart }}</div>
<div class="w-24 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelEnd }}</div>
<div class="w-16 min-w-16 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelStart }}</div>
<div class="w-16 min-w-16 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelEnd }}</div>
</div>
<div class="w-full max-h-72 overflow-auto">
<p v-if="!metadataChapters.length" class="py-5 text-center text-gray-200">{{ $strings.MessageNoChapters }}</p>
<template v-for="(chapter, index) in metadataChapters">
<div :key="index" class="flex py-1 px-4 text-sm" :class="index % 2 === 1 ? 'bg-primary/25' : ''">
<div class="grow font-semibold">{{ chapter.title }}</div>
<div class="w-24">
<div class="w-16 min-w-16">
{{ $secondsToTimestamp(chapter.start) }}
</div>
<div class="w-24">
<div class="w-16 min-w-16">
{{ $secondsToTimestamp(chapter.end) }}
</div>
</div>
@@ -356,6 +356,8 @@ export default {
const encodeOptions = this.$refs.encoderOptionsCard.getEncodingOptions()
this.encodingOptions = encodeOptions
const queryParams = new URLSearchParams(encodeOptions)
this.processing = true

View File

@@ -53,6 +53,7 @@ export default {
else if (pageName === 'sessions') return this.$strings.HeaderListeningSessions
else if (pageName === 'stats') return this.$strings.HeaderYourStats
else if (pageName === 'users') return this.$strings.HeaderUsers
else if (pageName === 'api-keys') return this.$strings.HeaderApiKeys
else if (pageName === 'item-metadata-utils') return this.$strings.HeaderItemMetadataUtils
else if (pageName === 'rss-feeds') return this.$strings.HeaderRSSFeeds
else if (pageName === 'email') return this.$strings.HeaderEmail

View File

@@ -0,0 +1,84 @@
<template>
<div>
<app-settings-content :header-text="$strings.HeaderApiKeys">
<template #header-items>
<div v-if="numApiKeys" class="mx-2 px-1.5 rounded-lg bg-primary/50 text-gray-300/90 text-sm inline-flex items-center justify-center">
<span>{{ numApiKeys }}</span>
</div>
<ui-tooltip :text="$strings.LabelClickForMoreInfo" class="inline-flex ml-2">
<a href="https://www.audiobookshelf.org/guides/api-keys" target="_blank" class="inline-flex">
<span class="material-symbols text-xl w-5 text-gray-200">help_outline</span>
</a>
</ui-tooltip>
<div class="grow" />
<ui-btn color="bg-primary" :disabled="loadingUsers || users.length === 0" small @click="setShowApiKeyModal()">{{ $strings.ButtonAddApiKey }}</ui-btn>
</template>
<tables-api-keys-table ref="apiKeysTable" class="pt-2" @edit="setShowApiKeyModal" @numApiKeys="(count) => (numApiKeys = count)" />
</app-settings-content>
<modals-api-key-modal ref="apiKeyModal" v-model="showApiKeyModal" :api-key="selectedApiKey" :users="users" @created="apiKeyCreated" @updated="apiKeyUpdated" />
<modals-api-key-created-modal ref="apiKeyCreatedModal" v-model="showApiKeyCreatedModal" :api-key="selectedApiKey" />
</div>
</template>
<script>
export default {
asyncData({ store, redirect }) {
if (!store.getters['user/getIsAdminOrUp']) {
redirect('/')
}
},
data() {
return {
loadingUsers: false,
selectedApiKey: null,
showApiKeyModal: false,
showApiKeyCreatedModal: false,
numApiKeys: 0,
users: []
}
},
methods: {
apiKeyCreated(apiKey) {
this.numApiKeys++
this.selectedApiKey = apiKey
this.showApiKeyCreatedModal = true
if (this.$refs.apiKeysTable) {
this.$refs.apiKeysTable.addApiKey(apiKey)
}
},
apiKeyUpdated(apiKey) {
if (this.$refs.apiKeysTable) {
this.$refs.apiKeysTable.updateApiKey(apiKey)
}
},
setShowApiKeyModal(selectedApiKey) {
this.selectedApiKey = selectedApiKey
this.showApiKeyModal = true
},
loadUsers() {
this.loadingUsers = true
this.$axios
.$get('/api/users')
.then((res) => {
this.users = res.users.sort((a, b) => {
return a.createdAt - b.createdAt
})
})
.catch((error) => {
console.error('Failed', error)
})
.finally(() => {
this.loadingUsers = false
})
}
},
mounted() {
this.loadUsers()
},
beforeDestroy() {}
}
</script>

View File

@@ -131,35 +131,26 @@
</div>
<div class="grow py-2">
<ui-dropdown :label="$strings.LabelSettingsDateFormat" v-model="newServerSettings.dateFormat" :items="dateFormats" small class="max-w-52" @input="(val) => updateSettingsKey('dateFormat', val)" />
<ui-dropdown :label="$strings.LabelSettingsDateFormat" v-model="newServerSettings.dateFormat" :items="dateFormats" small class="max-w-72" @input="(val) => updateSettingsKey('dateFormat', val)" />
<p class="text-xs ml-1 text-white/60">{{ $strings.LabelExample }}: {{ dateExample }}</p>
</div>
<div class="grow py-2">
<ui-dropdown :label="$strings.LabelSettingsTimeFormat" v-model="newServerSettings.timeFormat" :items="timeFormats" small class="max-w-52" @input="(val) => updateSettingsKey('timeFormat', val)" />
<ui-dropdown :label="$strings.LabelSettingsTimeFormat" v-model="newServerSettings.timeFormat" :items="timeFormats" small class="max-w-72" @input="(val) => updateSettingsKey('timeFormat', val)" />
<p class="text-xs ml-1 text-white/60">{{ $strings.LabelExample }}: {{ timeExample }}</p>
</div>
<div class="py-2">
<ui-dropdown :label="$strings.LabelLanguageDefaultServer" ref="langDropdown" v-model="newServerSettings.language" :items="$languageCodeOptions" small class="max-w-52" @input="updateServerLanguage" />
<ui-dropdown :label="$strings.LabelLanguageDefaultServer" ref="langDropdown" v-model="newServerSettings.language" :items="$languageCodeOptions" small class="max-w-72" @input="updateServerLanguage" />
</div>
<!-- old experimental features -->
<!-- <div class="pt-4">
<h2 class="font-semibold">{{ $strings.HeaderSettingsExperimental }}</h2>
<div class="pt-4">
<h2 class="font-semibold">{{ $strings.HeaderSettingsSecurity }}</h2>
</div>
<div class="flex items-center py-2">
<ui-toggle-switch labeledBy="settings-experimental-features" v-model="showExperimentalFeatures" />
<ui-tooltip :text="$strings.LabelSettingsExperimentalFeaturesHelp">
<p class="pl-4">
<span id="settings-experimental-features">{{ $strings.LabelSettingsExperimentalFeatures }}</span>
<a :aria-label="$strings.LabelSettingsExperimentalFeaturesHelp" href="https://github.com/advplyr/audiobookshelf/discussions/75" target="_blank">
<span class="material-symbols icon-text">info</span>
</a>
</p>
</ui-tooltip>
</div> -->
<div class="py-2">
<ui-multi-select v-model="newServerSettings.allowedOrigins" :items="newServerSettings.allowedOrigins" :label="$strings.LabelCorsAllowed" class="max-w-72" @input="updateCorsOrigins" />
</div>
</div>
</div>
</app-settings-content>
@@ -323,6 +314,27 @@ export default {
updateServerLanguage(val) {
this.updateSettingsKey('language', val)
},
updateCorsOrigins(val) {
const validOrigins = []
const invalidOrigins = []
val.forEach((origin) => {
const trimmedOrigin = origin.trim().toLowerCase()
try {
new URL(trimmedOrigin)
validOrigins.push(trimmedOrigin)
} catch {
invalidOrigins.push(trimmedOrigin)
}
})
if (invalidOrigins.length > 0) {
this.$toast.error(this.$strings.ToastInvalidUrls)
}
this.newServerSettings.allowedOrigins = validOrigins
this.updateSettingsKey('allowedOrigins', validOrigins)
},
updateSettingsKey(key, val) {
if (key === 'scannerDisableWatcher') {
this.newServerSettings.scannerDisableWatcher = val
@@ -352,6 +364,7 @@ export default {
initServerSettings() {
this.newServerSettings = this.serverSettings ? { ...this.serverSettings } : {}
this.newServerSettings.sortingPrefixes = [...(this.newServerSettings.sortingPrefixes || [])]
this.newServerSettings.allowedOrigins = [...(this.newServerSettings.allowedOrigins || [])]
this.scannerEnableWatcher = !this.newServerSettings.scannerDisableWatcher
this.homepageUseBookshelfView = this.newServerSettings.homeBookshelfView != this.$constants.BookshelfView.DETAIL

View File

@@ -78,10 +78,10 @@ export default {
},
computed: {
dateFormat() {
return this.$store.state.serverSettings.dateFormat
return this.$store.getters['getServerSetting']('dateFormat')
},
timeFormat() {
return this.$store.state.serverSettings.timeFormat
return this.$store.getters['getServerSetting']('timeFormat')
}
},
methods: {

View File

@@ -6,80 +6,82 @@
</div>
<div v-if="listeningSessions.length" class="block max-w-full relative">
<table class="userSessionsTable">
<tr class="bg-primary/40">
<th class="w-6 min-w-6 text-left hidden md:table-cell h-11">
<ui-checkbox v-model="isAllSelected" :partial="numSelected > 0 && !isAllSelected" small checkbox-bg="bg" />
</th>
<th v-if="numSelected" class="grow text-left" :colspan="7">
<div class="flex items-center">
<p>{{ $getString('MessageSelected', [numSelected]) }}</p>
<div class="grow" />
<ui-btn small color="bg-error" :loading="deletingSessions" @click.stop="removeSessionsClick">{{ $strings.ButtonRemove }}</ui-btn>
</div>
</th>
<th v-if="!numSelected" class="grow sm:grow-0 sm:w-48 sm:max-w-48 text-left group cursor-pointer" @click.stop="sortColumn('displayTitle')">
<div class="inline-flex items-center">
{{ $strings.LabelItem }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('displayTitle') }" class="material-symbols text-base pl-px">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
</div>
</th>
<th v-if="!numSelected" class="w-20 min-w-20 text-left hidden md:table-cell">{{ $strings.LabelUser }}</th>
<th v-if="!numSelected" class="w-26 min-w-26 text-left hidden md:table-cell group cursor-pointer" @click.stop="sortColumn('playMethod')">
<div class="inline-flex items-center">
{{ $strings.LabelPlayMethod }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('playMethod') }" class="material-symbols text-base pl-px">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
</div>
</th>
<th v-if="!numSelected" class="w-32 min-w-32 text-left hidden sm:table-cell">{{ $strings.LabelDeviceInfo }}</th>
<th v-if="!numSelected" class="w-24 min-w-24 sm:w-32 sm:min-w-32 group cursor-pointer" @click.stop="sortColumn('timeListening')">
<div class="inline-flex items-center">
{{ $strings.LabelTimeListened }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('timeListening') }" class="material-symbols text-base pl-px hidden sm:inline-block">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
</div>
</th>
<th v-if="!numSelected" class="w-24 min-w-24 group cursor-pointer" @click.stop="sortColumn('currentTime')">
<div class="inline-flex items-center">
{{ $strings.LabelLastTime }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('currentTime') }" class="material-symbols text-base pl-px hidden sm:inline-block">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
</div>
</th>
<th v-if="!numSelected" class="grow hidden sm:table-cell cursor-pointer group" @click.stop="sortColumn('updatedAt')">
<div class="inline-flex items-center">
{{ $strings.LabelLastUpdate }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('updatedAt') }" class="material-symbols text-base pl-px">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
</div>
</th>
</tr>
<div class="overflow-x-auto">
<table class="userSessionsTable">
<tr class="bg-primary/40">
<th class="w-6 min-w-6 text-left hidden md:table-cell h-11">
<ui-checkbox v-model="isAllSelected" :partial="numSelected > 0 && !isAllSelected" small checkbox-bg="bg" />
</th>
<th v-if="numSelected" class="grow text-left" :colspan="7">
<div class="flex items-center">
<p>{{ $getString('MessageSelected', [numSelected]) }}</p>
<div class="grow" />
<ui-btn small color="bg-error" :loading="deletingSessions" @click.stop="removeSessionsClick">{{ $strings.ButtonRemove }}</ui-btn>
</div>
</th>
<th v-if="!numSelected" class="grow sm:grow-0 sm:w-48 sm:max-w-48 text-left group cursor-pointer" @click.stop="sortColumn('displayTitle')">
<div class="inline-flex items-center">
{{ $strings.LabelItem }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('displayTitle') }" class="material-symbols text-base pl-px">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
</div>
</th>
<th v-if="!numSelected" class="w-20 min-w-20 text-left hidden md:table-cell">{{ $strings.LabelUser }}</th>
<th v-if="!numSelected" class="w-26 min-w-26 text-left hidden md:table-cell group cursor-pointer" @click.stop="sortColumn('playMethod')">
<div class="inline-flex items-center">
{{ $strings.LabelPlayMethod }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('playMethod') }" class="material-symbols text-base pl-px">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
</div>
</th>
<th v-if="!numSelected" class="w-32 min-w-32 text-left hidden sm:table-cell">{{ $strings.LabelDeviceInfo }}</th>
<th v-if="!numSelected" class="w-24 min-w-24 sm:w-32 sm:min-w-32 group cursor-pointer" @click.stop="sortColumn('timeListening')">
<div class="inline-flex items-center">
{{ $strings.LabelTimeListened }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('timeListening') }" class="material-symbols text-base pl-px hidden sm:inline-block">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
</div>
</th>
<th v-if="!numSelected" class="w-24 min-w-24 group cursor-pointer" @click.stop="sortColumn('currentTime')">
<div class="inline-flex items-center">
{{ $strings.LabelLastTime }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('currentTime') }" class="material-symbols text-base pl-px hidden sm:inline-block">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
</div>
</th>
<th v-if="!numSelected" class="grow hidden sm:table-cell cursor-pointer group" @click.stop="sortColumn('updatedAt')">
<div class="inline-flex items-center">
{{ $strings.LabelLastUpdate }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('updatedAt') }" class="material-symbols text-base pl-px">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
</div>
</th>
</tr>
<tr v-for="session in listeningSessions" :key="session.id" :class="{ selected: session.selected }" class="cursor-pointer" @click="clickSessionRow(session)">
<td class="hidden md:table-cell py-1 max-w-6 relative">
<ui-checkbox v-model="session.selected" small checkbox-bg="bg" />
<!-- overlay of the checkbox so that the entire box is clickable -->
<div class="absolute inset-0 w-full h-full" @click.stop="session.selected = !session.selected" />
</td>
<td class="py-1 grow sm:grow-0 sm:w-48 sm:max-w-48">
<p class="text-xs text-gray-200 truncate">{{ session.displayTitle }}</p>
<p class="text-xs text-gray-400 truncate">{{ session.displayAuthor }}</p>
</td>
<td class="hidden md:table-cell w-20 min-w-20">
<p v-if="filteredUserUsername" class="text-xs">{{ filteredUserUsername }}</p>
<p v-else class="text-xs">{{ session.user ? session.user.username : 'N/A' }}</p>
</td>
<td class="hidden md:table-cell w-26 min-w-26">
<p class="text-xs">{{ getPlayMethodName(session.playMethod) }}</p>
</td>
<td class="hidden sm:table-cell max-w-32 min-w-32">
<p class="text-xs truncate" v-html="getDeviceInfoString(session.deviceInfo)" />
</td>
<td class="text-center w-24 min-w-24 sm:w-32 sm:min-w-32">
<p class="text-xs font-mono">{{ $elapsedPretty(session.timeListening) }}</p>
</td>
<td class="text-center hover:underline w-24 min-w-24" @click.stop="clickCurrentTime(session)">
<p class="text-xs font-mono">{{ $secondsToTimestamp(session.currentTime) }}</p>
</td>
<td class="text-center hidden sm:table-cell">
<ui-tooltip v-if="session.updatedAt" direction="top" :text="$formatDatetime(session.updatedAt, dateFormat, timeFormat)">
<p class="text-xs text-gray-200">{{ $dateDistanceFromNow(session.updatedAt) }}</p>
</ui-tooltip>
</td>
</tr>
</table>
<tr v-for="session in listeningSessions" :key="session.id" :class="{ selected: session.selected }" class="cursor-pointer" @click="clickSessionRow(session)">
<td class="hidden md:table-cell py-1 max-w-6 relative">
<ui-checkbox v-model="session.selected" small checkbox-bg="bg" />
<!-- overlay of the checkbox so that the entire box is clickable -->
<div class="absolute inset-0 w-full h-full" @click.stop="session.selected = !session.selected" />
</td>
<td class="py-1 grow sm:grow-0 sm:w-48 sm:max-w-48">
<p class="text-xs text-gray-200 truncate">{{ session.displayTitle }}</p>
<p class="text-xs text-gray-400 truncate">{{ session.displayAuthor }}</p>
</td>
<td class="hidden md:table-cell w-20 min-w-20">
<p v-if="filteredUserUsername" class="text-xs">{{ filteredUserUsername }}</p>
<p v-else class="text-xs">{{ session.user ? session.user.username : 'N/A' }}</p>
</td>
<td class="hidden md:table-cell w-26 min-w-26">
<p class="text-xs">{{ getPlayMethodName(session.playMethod) }}</p>
</td>
<td class="hidden sm:table-cell max-w-32 min-w-32">
<p class="text-xs truncate" v-html="getDeviceInfoString(session.deviceInfo)" />
</td>
<td class="text-center w-24 min-w-24 sm:w-32 sm:min-w-32">
<p class="text-xs font-mono">{{ $elapsedPrettyLocalized(session.timeListening) }}</p>
</td>
<td class="text-center hover:underline w-24 min-w-24" @click.stop="clickCurrentTime(session)">
<p class="text-xs font-mono">{{ $secondsToTimestamp(session.currentTime) }}</p>
</td>
<td class="text-center hidden sm:table-cell">
<ui-tooltip v-if="session.updatedAt" direction="top" :text="$formatDatetime(session.updatedAt, dateFormat, timeFormat)">
<p class="text-xs text-gray-200">{{ $dateDistanceFromNow(session.updatedAt) }}</p>
</ui-tooltip>
</td>
</tr>
</table>
</div>
<!-- table bottom options -->
<div class="flex items-center my-2">
<div class="grow" />
@@ -250,10 +252,10 @@ export default {
return user?.username || null
},
dateFormat() {
return this.$store.state.serverSettings.dateFormat
return this.$store.getters['getServerSetting']('dateFormat')
},
timeFormat() {
return this.$store.state.serverSettings.timeFormat
return this.$store.getters['getServerSetting']('timeFormat')
},
numSelected() {
return this.listeningSessions.filter((s) => s.selected).length

View File

@@ -13,8 +13,10 @@
<widgets-online-indicator :value="!!userOnline" />
<h1 class="text-xl pl-2">{{ username }}</h1>
</div>
<div v-if="userToken" class="flex text-xs mt-4">
<ui-text-input-with-label :label="$strings.LabelApiToken" :value="userToken" readonly show-copy />
<div v-if="legacyToken" class="text-xs space-y-2 mt-4">
<ui-text-input-with-label label="Legacy API Token" :value="legacyToken" readonly show-copy />
<p class="text-warning" v-html="$strings.MessageAuthenticationLegacyTokenWarning" />
</div>
<div class="w-full h-px bg-white/10 my-2" />
<div class="py-2">
@@ -100,9 +102,12 @@ export default {
}
},
computed: {
userToken() {
legacyToken() {
return this.user.token
},
userToken() {
return this.user.accessToken
},
bookCoverAspectRatio() {
return this.$store.getters['libraries/getBookCoverAspectRatio']
},
@@ -129,10 +134,10 @@ export default {
return this.listeningSessions.sessions[0]
},
dateFormat() {
return this.$store.state.serverSettings.dateFormat
return this.$store.getters['getServerSetting']('dateFormat')
},
timeFormat() {
return this.$store.state.serverSettings.timeFormat
return this.$store.getters['getServerSetting']('timeFormat')
}
},
methods: {

View File

@@ -19,39 +19,41 @@
<div class="py-2">
<h1 class="text-lg mb-2 text-white/90 px-2 sm:px-0">{{ $strings.HeaderListeningSessions }}</h1>
<div v-if="listeningSessions.length">
<table class="userSessionsTable">
<tr class="bg-primary/40">
<th class="w-48 min-w-48 text-left">{{ $strings.LabelItem }}</th>
<th class="w-32 min-w-32 text-left hidden md:table-cell">{{ $strings.LabelPlayMethod }}</th>
<th class="w-32 min-w-32 text-left hidden sm:table-cell">{{ $strings.LabelDeviceInfo }}</th>
<th class="w-32 min-w-32">{{ $strings.LabelTimeListened }}</th>
<th class="w-16 min-w-16">{{ $strings.LabelLastTime }}</th>
<th class="grow hidden sm:table-cell">{{ $strings.LabelLastUpdate }}</th>
</tr>
<tr v-for="session in listeningSessions" :key="session.id" class="cursor-pointer" @click="showSession(session)">
<td class="py-1 max-w-48">
<p class="text-xs text-gray-200 truncate">{{ session.displayTitle }}</p>
<p class="text-xs text-gray-400 truncate">{{ session.displayAuthor }}</p>
</td>
<td class="hidden md:table-cell">
<p class="text-xs">{{ getPlayMethodName(session.playMethod) }}</p>
</td>
<td class="hidden sm:table-cell min-w-32 max-w-32">
<p class="text-xs truncate" v-html="getDeviceInfoString(session.deviceInfo)" />
</td>
<td class="text-center">
<p class="text-xs font-mono">{{ $elapsedPretty(session.timeListening) }}</p>
</td>
<td class="text-center hover:underline" @click.stop="clickCurrentTime(session)">
<p class="text-xs font-mono">{{ $secondsToTimestamp(session.currentTime) }}</p>
</td>
<td class="text-center hidden sm:table-cell">
<ui-tooltip v-if="session.updatedAt" direction="top" :text="$formatDatetime(session.updatedAt, dateFormat, timeFormat)">
<p class="text-xs text-gray-200">{{ $dateDistanceFromNow(session.updatedAt) }}</p>
</ui-tooltip>
</td>
</tr>
</table>
<div class="overflow-x-auto">
<table class="userSessionsTable">
<tr class="bg-primary/40">
<th class="w-48 min-w-48 text-left">{{ $strings.LabelItem }}</th>
<th class="w-32 min-w-32 text-left hidden md:table-cell">{{ $strings.LabelPlayMethod }}</th>
<th class="w-32 min-w-32 text-left hidden sm:table-cell">{{ $strings.LabelDeviceInfo }}</th>
<th class="w-32 min-w-32">{{ $strings.LabelTimeListened }}</th>
<th class="w-16 min-w-16">{{ $strings.LabelLastTime }}</th>
<th class="grow hidden sm:table-cell">{{ $strings.LabelLastUpdate }}</th>
</tr>
<tr v-for="session in listeningSessions" :key="session.id" class="cursor-pointer" @click="showSession(session)">
<td class="py-1 max-w-48">
<p class="text-xs text-gray-200 truncate">{{ session.displayTitle }}</p>
<p class="text-xs text-gray-400 truncate">{{ session.displayAuthor }}</p>
</td>
<td class="hidden md:table-cell">
<p class="text-xs">{{ getPlayMethodName(session.playMethod) }}</p>
</td>
<td class="hidden sm:table-cell min-w-32 max-w-32">
<p class="text-xs truncate" v-html="getDeviceInfoString(session.deviceInfo)" />
</td>
<td class="text-center">
<p class="text-xs font-mono">{{ $elapsedPrettyLocalized(session.timeListening) }}</p>
</td>
<td class="text-center hover:underline" @click.stop="clickCurrentTime(session)">
<p class="text-xs font-mono">{{ $secondsToTimestamp(session.currentTime) }}</p>
</td>
<td class="text-center hidden sm:table-cell">
<ui-tooltip v-if="session.updatedAt" direction="top" :text="$formatDatetime(session.updatedAt, dateFormat, timeFormat)">
<p class="text-xs text-gray-200">{{ $dateDistanceFromNow(session.updatedAt) }}</p>
</ui-tooltip>
</td>
</tr>
</table>
</div>
<div class="flex items-center justify-end py-1">
<ui-icon-btn icon="arrow_back_ios_new" :size="7" icon-font-size="1rem" class="mx-1" :disabled="currentPage === 0" @click="prevPage" />
<p class="text-sm mx-1">{{ $getString('LabelPaginationPageXOfY', [currentPage + 1, numPages]) }}</p>
@@ -98,10 +100,10 @@ export default {
return this.$store.getters['users/getIsUserOnline'](this.user.id)
},
dateFormat() {
return this.$store.state.serverSettings.dateFormat
return this.$store.getters['getServerSetting']('dateFormat')
},
timeFormat() {
return this.$store.state.serverSettings.timeFormat
return this.$store.getters['getServerSetting']('timeFormat')
}
},
methods: {

View File

@@ -193,7 +193,7 @@ export default {
return `${process.env.serverUrl}/api/items/${this.libraryItemId}/download?token=${this.userToken}`
},
dateFormat() {
return this.$store.state.serverSettings.dateFormat
return this.$store.getters['getServerSetting']('dateFormat')
},
userIsAdminOrUp() {
return this.$store.getters['user/getIsAdminOrUp']

View File

@@ -10,7 +10,7 @@
</tr>
<tr v-for="narrator in narrators" :key="narrator.id">
<td>
<p v-if="selectedNarrator?.id !== narrator.id" class="text-sm md:text-base text-gray-100">{{ narrator.name }}</p>
<nuxt-link v-if="selectedNarrator?.id !== narrator.id" :to="`/library/${currentLibraryId}/bookshelf?filter=narrators.${narrator.id}`" class="text-sm md:text-base text-gray-100 hover:underline">{{ narrator.name }}</nuxt-link>
<form v-else @submit.prevent="saveClick">
<ui-text-input v-model="newNarratorName" />
</form>

View File

@@ -141,7 +141,7 @@ export default {
return episodeIds
},
dateFormat() {
return this.$store.state.serverSettings.dateFormat
return this.$store.getters['getServerSetting']('dateFormat')
}
},
methods: {

View File

@@ -40,6 +40,15 @@
<p v-if="error" class="text-error text-center py-2">{{ error }}</p>
<div v-if="showNewAuthSystemMessage" class="mb-4">
<widgets-alert type="warning">
<div>
<p>{{ $strings.MessageAuthenticationSecurityMessage }}</p>
<a v-if="showNewAuthSystemAdminMessage" href="https://github.com/advplyr/audiobookshelf/discussions/4460" target="_blank" class="underline">{{ $strings.LabelMoreInfo }}</a>
</div>
</widgets-alert>
</div>
<form v-show="login_local" @submit.prevent="submitForm">
<label class="text-xs text-gray-300 uppercase">{{ $strings.LabelUsername }}</label>
<ui-text-input v-model.trim="username" :disabled="processing" class="mb-3 w-full" inputName="username" />
@@ -85,7 +94,10 @@ export default {
MetadataPath: '',
login_local: true,
login_openid: false,
authFormData: null
authFormData: null,
// New JWT auth system re-login flags
showNewAuthSystemMessage: false,
showNewAuthSystemAdminMessage: false
}
},
watch: {
@@ -179,11 +191,17 @@ export default {
this.$store.commit('libraries/setCurrentLibrary', userDefaultLibraryId)
this.$store.commit('user/setUser', user)
// Access token only returned from login, not authorize
if (user.accessToken) {
this.$store.commit('user/setAccessToken', user.accessToken)
}
this.$store.dispatch('user/loadUserSettings')
},
async submitForm() {
this.error = null
this.showNewAuthSystemMessage = false
this.showNewAuthSystemAdminMessage = false
this.processing = true
const payload = {
@@ -210,6 +228,8 @@ export default {
this.processing = true
this.$store.commit('user/setAccessToken', token)
return this.$axios
.$post('/api/authorize', null, {
headers: {
@@ -217,15 +237,25 @@ export default {
}
})
.then((res) => {
// Force re-login if user is using an old token with no expiration
if (res.user.isOldToken) {
this.username = res.user.username
this.showNewAuthSystemMessage = true
// Admin user sees link to github discussion
this.showNewAuthSystemAdminMessage = res.user.type === 'admin' || res.user.type === 'root'
return false
}
this.setUser(res)
this.processing = false
return true
})
.catch((error) => {
console.error('Authorize error', error)
this.processing = false
return false
})
.finally(() => {
this.processing = false
})
},
checkStatus() {
this.processing = true
@@ -280,8 +310,9 @@ export default {
}
},
async mounted() {
if (this.$route.query?.setToken) {
localStorage.setItem('token', this.$route.query.setToken)
// Token passed as query parameter after successful oidc login
if (this.$route.query?.accessToken) {
localStorage.setItem('token', this.$route.query.accessToken)
}
if (localStorage.getItem('token')) {
if (await this.checkAuth()) return // if valid user no need to check status

View File

@@ -1,4 +1,19 @@
export default function ({ $axios, store, $config }) {
export default function ({ $axios, store, $root, app }) {
// Track if we're currently refreshing to prevent multiple refresh attempts
let isRefreshing = false
let failedQueue = []
const processQueue = (error, token = null) => {
failedQueue.forEach(({ resolve, reject }) => {
if (error) {
reject(error)
} else {
resolve(token)
}
})
failedQueue = []
}
$axios.onRequest((config) => {
if (!config.url) {
console.error('Axios request invalid config', config)
@@ -7,7 +22,7 @@ export default function ({ $axios, store, $config }) {
if (config.url.startsWith('http:') || config.url.startsWith('https:')) {
return
}
const bearerToken = store.state.user.user?.token || null
const bearerToken = store.getters['user/getToken']
if (bearerToken) {
config.headers.common['Authorization'] = `Bearer ${bearerToken}`
}
@@ -17,9 +32,79 @@ export default function ({ $axios, store, $config }) {
}
})
$axios.onError((error) => {
$axios.onError(async (error) => {
const originalRequest = error.config
const code = parseInt(error.response && error.response.status)
const message = error.response ? error.response.data || 'Unknown Error' : 'Unknown Error'
console.error('Axios error', code, message)
// Handle 401 Unauthorized (token expired)
if (code === 401 && !originalRequest._retry) {
// Skip refresh for auth endpoints to prevent infinite loops
if (originalRequest.url === '/auth/refresh' || originalRequest.url === '/login') {
// Refresh failed or login failed, redirect to login
store.commit('user/setUser', null)
store.commit('user/setAccessToken', null)
app.router.push('/login')
return Promise.reject(error)
}
if (isRefreshing) {
// If already refreshing, queue this request
return new Promise((resolve, reject) => {
failedQueue.push({ resolve, reject })
})
.then((token) => {
if (!originalRequest.headers) {
originalRequest.headers = {}
}
originalRequest.headers['Authorization'] = `Bearer ${token}`
return $axios(originalRequest)
})
.catch((err) => {
return Promise.reject(err)
})
}
originalRequest._retry = true
isRefreshing = true
try {
// Attempt to refresh the token
// Updates store if successful, otherwise clears store and throw error
const newAccessToken = await store.dispatch('user/refreshToken')
if (!newAccessToken) {
console.error('No new access token received')
return Promise.reject(error)
}
// Update the original request with new token
if (!originalRequest.headers) {
originalRequest.headers = {}
}
originalRequest.headers['Authorization'] = `Bearer ${newAccessToken}`
// Process any queued requests
processQueue(null, newAccessToken)
// Retry the original request
return $axios(originalRequest)
} catch (refreshError) {
console.error('Token refresh failed:', refreshError)
// Process queued requests with error
processQueue(refreshError, null)
// Redirect to login
app.router.push('/login')
return Promise.reject(refreshError)
} finally {
isRefreshing = false
}
}
return Promise.reject(error)
})
}

View File

@@ -37,6 +37,48 @@ Vue.prototype.$elapsedPretty = (seconds, useFullNames = false, useMilliseconds =
return `${hours} ${useFullNames ? `hour${hours === 1 ? '' : 's'}` : 'hr'} ${minutes} ${useFullNames ? `minute${minutes === 1 ? '' : 's'}` : 'min'}`
}
Vue.prototype.$elapsedPrettyLocalized = (seconds, useFullNames = false, useMilliseconds = false) => {
if (isNaN(seconds) || seconds === null) return ''
try {
const df = new Intl.DurationFormat(Vue.prototype.$languageCodes.current, {
style: useFullNames ? 'long' : 'short'
})
const duration = {}
if (seconds < 60) {
if (useMilliseconds && seconds < 1) {
duration.milliseconds = Math.floor(seconds * 1000)
} else {
duration.seconds = Math.floor(seconds)
}
} else if (seconds < 3600) {
// 1 hour
duration.minutes = Math.floor(seconds / 60)
} else if (seconds < 86400) {
// 1 day
duration.hours = Math.floor(seconds / 3600)
const minutes = Math.floor((seconds % 3600) / 60)
if (minutes > 0) {
duration.minutes = minutes
}
} else {
duration.days = Math.floor(seconds / 86400)
const hours = Math.floor((seconds % 86400) / 3600)
if (hours > 0) {
duration.hours = hours
}
}
return df.format(duration)
} catch (error) {
// Handle not supported
console.warn('Intl.DurationFormat not supported, not localizing duration')
return Vue.prototype.$elapsedPretty(seconds, useFullNames, useMilliseconds)
}
}
Vue.prototype.$secondsToTimestamp = (seconds, includeMs = false, alwaysIncludeHours = false) => {
if (!seconds) {
return alwaysIncludeHours ? '00:00:00' : '0:00'

View File

@@ -1,5 +1,6 @@
export const state = () => ({
user: null,
accessToken: null,
settings: {
orderBy: 'media.metadata.title',
orderDesc: false,
@@ -25,19 +26,19 @@ export const getters = {
getIsRoot: (state) => state.user && state.user.type === 'root',
getIsAdminOrUp: (state) => state.user && (state.user.type === 'admin' || state.user.type === 'root'),
getToken: (state) => {
return state.user?.token || null
return state.accessToken || null
},
getUserMediaProgress:
(state) =>
(libraryItemId, episodeId = null) => {
if (!state.user.mediaProgress) return null
if (!state.user?.mediaProgress) return null
return state.user.mediaProgress.find((li) => {
if (episodeId && li.episodeId !== episodeId) return false
return li.libraryItemId == libraryItemId
})
},
getUserBookmarksForItem: (state) => (libraryItemId) => {
if (!state.user.bookmarks) return []
if (!state.user?.bookmarks) return []
return state.user.bookmarks.filter((bm) => bm.libraryItemId === libraryItemId)
},
getUserSetting: (state) => (key) => {
@@ -58,6 +59,9 @@ export const getters = {
getUserCanAccessAllLibraries: (state) => {
return !!state.user?.permissions?.accessAllLibraries
},
getUserCanAccessExplicitContent: (state) => {
return !!state.user?.permissions?.accessExplicitContent
},
getLibrariesAccessible: (state, getters) => {
if (!state.user) return []
if (getters.getUserCanAccessAllLibraries) return []
@@ -88,7 +92,7 @@ export const actions = {
if (state.settings.orderBy == 'media.duration') {
settingsUpdate.orderBy = 'media.numTracks'
}
if (state.settings.orderBy == 'media.metadata.publishedYear') {
if (state.settings.orderBy == 'media.metadata.publishedYear' || state.settings.orderBy == 'progress') {
settingsUpdate.orderBy = 'media.metadata.title'
}
const invalidFilters = ['series', 'authors', 'narrators', 'publishers', 'publishedDecades', 'languages', 'progress', 'issues', 'ebooks', 'abridged']
@@ -142,21 +146,42 @@ export const actions = {
} catch (error) {
console.error('Failed to load userSettings from local storage', error)
}
},
refreshToken({ state, commit }) {
return this.$axios
.$post('/auth/refresh')
.then(async (response) => {
const newAccessToken = response.user.accessToken
commit('setUser', response.user)
commit('setAccessToken', newAccessToken)
// Emit event used to re-authenticate socket in default.vue since $root is not available here
if (this.$eventBus) {
this.$eventBus.$emit('token_refreshed', newAccessToken)
}
return newAccessToken
})
.catch((error) => {
console.error('Failed to refresh token', error)
commit('setUser', null)
commit('setAccessToken', null)
// Calling function handles redirect to login
throw error
})
}
}
export const mutations = {
setUser(state, user) {
state.user = user
if (user) {
if (user.token) localStorage.setItem('token', user.token)
} else {
localStorage.removeItem('token')
}
},
setUserToken(state, token) {
state.user.token = token
localStorage.setItem('token', token)
setAccessToken(state, token) {
if (!token) {
localStorage.removeItem('token')
state.accessToken = null
} else {
state.accessToken = token
localStorage.setItem('token', token)
}
},
updateMediaProgress(state, { id, data }) {
if (!state.user) return

View File

@@ -514,7 +514,7 @@
"LabelPublishers": "الناشرون",
"LabelRSSFeedCustomOwnerEmail": "البريد الالكتروني المخصص للمالك",
"LabelRSSFeedCustomOwnerName": "الاسم المخصص للمالك",
"LabelRSSFeedOpen": "فتح تغذية RSS",
"LabelRSSFeedOpen": "موجز RSS مفتوح",
"LabelRSSFeedPreventIndexing": "منع الفهرسة",
"LabelRSSFeedSlug": "اسم تعريف تغذية RSS",
"LabelRSSFeedURL": "رابط تغذية RSS",
@@ -918,6 +918,8 @@
"NotificationOnBackupCompletedDescription": "يتم تشغيله عند اكتمال النسخ الاحتياطي",
"NotificationOnBackupFailedDescription": "يتم تشغيله عند فشل النسخ الاحتياطي",
"NotificationOnEpisodeDownloadedDescription": "يتم تشغيله عند تنزيل حلقة بودكاست تلقائيًا",
"NotificationOnRSSFeedDisabledDescription": "يتم تشغيله عندما يتم تعطيل تنزيلات الحلقة التلقائية بسبب الكثير من المحاولات الفاشلة",
"NotificationOnRSSFeedFailedDescription": "يتم تشغيله عند فشل طلب تغذية RSS في تنزيل حلقة تلقائية",
"NotificationOnTestDescription": "حدث لاختبار نظام الإشعارات",
"PlaceholderNewCollection": "اسم المجموعة الجديدة",
"PlaceholderNewFolderPath": "مسار المجلد الجديد",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Дадаць",
"ButtonAddApiKey": "Дадаць API-ключ",
"ButtonAddChapters": "Дадаць раздзелы",
"ButtonAddDevice": "Дадаць прыладу",
"ButtonAddLibrary": "Дадаць бібліятэку",
@@ -20,6 +21,7 @@
"ButtonChooseAFolder": "Выбраць тэчку",
"ButtonChooseFiles": "Выбраць файлы",
"ButtonClearFilter": "Ачысціць фільтр",
"ButtonClose": "Закрыць",
"ButtonCloseFeed": "Закрыць стужку",
"ButtonCloseSession": "Закрыць адкрыты сеанс",
"ButtonCollections": "Калекцыі",
@@ -69,7 +71,7 @@
"ButtonQueueAddItem": "Дадаць у чаргу",
"ButtonQueueRemoveItem": "Выдаліць з чаргі",
"ButtonQuickEmbed": "Хуткае ўбудаванне",
"ButtonQuickEmbedMetadata": "Хуткае ўбудаванне метаданых",
"ButtonQuickEmbedMetadata": "Хуткае ўбудаванне метададзеных",
"ButtonQuickMatch": "Хуткі пошук",
"ButtonReScan": "Паўторнае сканаванне",
"ButtonRead": "Чытаць",
@@ -98,8 +100,9 @@
"ButtonSetChaptersFromTracks": "Усталяваць раздзелы з трэкаў",
"ButtonShare": "Падзяліцца",
"ButtonShiftTimes": "Карэкцыя часу",
"ButtonShow": "Паказаць",
"ButtonStartM4BEncode": "Пачаць кадзіраванне ў M4B",
"ButtonStartMetadataEmbed": "Пачаць убудаванне метаданых",
"ButtonStartMetadataEmbed": "Пачаць убудаванне метададзеных",
"ButtonStats": "Статыстыка",
"ButtonSubmit": "Адправіць",
"ButtonTest": "Тэст",
@@ -116,8 +119,9 @@
"ErrorUploadFetchMetadataNoResults": "Не ўдалося атрымаць метададзеныя паспрабуйце абнавіць назву і/або аўтара",
"ErrorUploadLacksTitle": "Павінна быць назва",
"HeaderAccount": "Уліковы запіс",
"HeaderAddCustomMetadataProvider": "Дадаць карыстальніцкага пастаўшчыка метаданных",
"HeaderAddCustomMetadataProvider": "Дадаць карыстальніцкага пастаўшчыка метададзенных",
"HeaderAdvanced": "Дадаткова",
"HeaderApiKeys": "API-ключы",
"HeaderAppriseNotificationSettings": "Налады апавяшчэнняў Apprise",
"HeaderAudioTracks": "Аўдыядарожкі",
"HeaderAudiobookTools": "Сродкі кіравання файламі аўдыякніг",
@@ -157,9 +161,11 @@
"HeaderManageGenres": "Кіраванне жанрамі",
"HeaderManageTags": "Кіраванне тэгамі",
"HeaderMapDetails": "Падрабязнасці адлюстравання",
"HeaderMatch": "Супадзенне",
"HeaderMetadataOrderOfPrecedence": "Парадак прыярытэтнасці метададзеных",
"HeaderMetadataToEmbed": "Метададзеныя для ўбудавання",
"HeaderNewAccount": "Новы ўліковы запіс",
"HeaderNewApiKey": "Новы API-ключ",
"HeaderNewLibrary": "Новая бібліятэка",
"HeaderNotificationCreate": "Стварыць апавяшчэнне",
"HeaderNotificationUpdate": "Абнавіць апавяшчэнне",
@@ -175,9 +181,10 @@
"HeaderPlaylist": "Спіс прайгравання",
"HeaderPlaylistItems": "Элементы спіса прайгравання",
"HeaderPodcastsToAdd": "Падкасты для дадання",
"HeaderPresets": "Прадустаноўкі",
"HeaderPreviewCover": "Прадпрагляд вокладкі",
"HeaderRSSFeedGeneral": "Падрабязнасці RSS",
"HeaderRSSFeedIsOpen": "RSS-стужка адкрыта",
"HeaderRSSFeedIsOpen": "RSS-стужка адкрытая",
"HeaderRSSFeeds": "RSS-стужкі",
"HeaderRemoveEpisode": "Выдаліць эпізод",
"HeaderRemoveEpisodes": "Выдаліць {0} эпізодаў",
@@ -203,6 +210,7 @@
"HeaderTableOfContents": "Змест",
"HeaderTools": "Інструменты",
"HeaderUpdateAccount": "Абнавіць уліковы запіс",
"HeaderUpdateApiKey": "Абнавіць API-ключ",
"HeaderUpdateAuthor": "Абнавіць аўтара",
"HeaderUpdateDetails": "Абнавіць падрабязнасці",
"HeaderUpdateLibrary": "Абнавіць бібліятэку",
@@ -227,10 +235,15 @@
"LabelAddedDate": "Дададзена {0}",
"LabelAdminUsersOnly": "Толькі для адміністратараў",
"LabelAll": "Усе",
"LabelAllEpisodesDownloaded": "Усе эпізоды спампаваныя",
"LabelAllUsers": "Усе карыстальнікі",
"LabelAllUsersExcludingGuests": "Усе карыстальнікі, акрамя гасцей",
"LabelAllUsersIncludingGuests": "Усе карыстальнікі, уключаючы гасцей",
"LabelAlreadyInYourLibrary": "Ужо ў вашай бібліятэцы",
"LabelApiKeyCreated": "API-ключ \"{0}\" паспяхова створаны.",
"LabelApiKeyCreatedDescription": "Пераканайцеся, што вы скапіявалі API-ключ зараз, бо паўторна яго ўбачыць не атрымаецца.",
"LabelApiKeyUser": "Дзейнічаць ад імя карыстальніка",
"LabelApiKeyUserDescription": "Гэты API-ключ будзе мець тыя ж правы, што і карыстальнік, ад імя якога ён дзейнічае. У журналах гэта будзе выглядаць так, быццам запыт робіць сам карыстальнік.",
"LabelApiToken": "Токен API",
"LabelAppend": "Дадаць",
"LabelAudioBitrate": "Бітрэйт аўдыё (напрыклад, 128к)",
@@ -242,39 +255,107 @@
"LabelAuthors": "Аўтары",
"LabelAutoDownloadEpisodes": "Аўтаматычнае спампаванне эпізодаў",
"LabelAutoFetchMetadata": "Аўтаматычнае атрыманне метададзеных",
"LabelAutoFetchMetadataHelp": "Атрыманне звестак пра назву, аўтара і серыю для падыходнага фарматавання перад загрузкай. Далей можа быць неабходна дапоўніць метададзеныя.",
"LabelAutoLaunch": "Аўтазапуск",
"LabelAutoLaunchDescription": "Аўтаматычна перанакіроўваць да пастаўшчыка аўтэнтыфікацыі пры переходзе на старонку ўваходу (ручное пераключэнне праз шлях <code>/login?autoLaunch=0</code>)",
"LabelAutoRegister": "Аўтарэгістрацыя",
"LabelAutoRegisterDescription": "Аўтаматычна ствараць новых карыстальнікаў пасля ўваходу ў сістэму",
"LabelBackToUser": "Вярнуцца да карыстальніка",
"LabelBackupAudioFiles": "Рэзервовае капіраванне аўдыёфайлаў",
"LabelBackupLocation": "Месцазнаходжанне рэзервовых копій",
"LabelBackupsEnableAutomaticBackups": "Аўтаматычнае рэзервовае капіраванне",
"LabelBackupsEnableAutomaticBackupsHelp": "Рэзервовыя копіі захаваныя ў /metadata/backups",
"LabelBackupsMaxBackupSize": "Максімальны памер рэзервовай копіі (у ГБ) (0 — неабмежавана)",
"LabelBackupsMaxBackupSizeHelp": "Для таго, каб пазбегнуць няправільных налад, рэзервовыя копіі не будуць створаны, калі іх памер будзе больш за дапушчальны.",
"LabelBackupsNumberToKeep": "Колькасць захаваных рэзервовых копій",
"LabelBackupsNumberToKeepHelp": "Адначасова будзе выдаляцца толькі 1 рэзервовая копія, таму, калі ў вас іх больш, вам варта выдаліць іх уручную.",
"LabelBitrate": "Бітрэйт",
"LabelBonus": "Бонус",
"LabelBooks": "Кнігі",
"LabelButtonText": "Тэкст кнопкі",
"LabelByAuthor": "ад {0}",
"LabelChangePassword": "Змяніць пароль",
"LabelChannels": "Каналы",
"LabelChapterCount": "{0} раздзелаў",
"LabelChapterTitle": "Назва раздзела",
"LabelChapters": "Раздзелы",
"LabelChaptersFound": "раздзелаў знойдзена",
"LabelClickForMoreInfo": "Націсніце для больш падрабязнай інфармацыі",
"LabelClickToUseCurrentValue": "Націсніце, каб выкарыстоўваць бягучае значэнне",
"LabelClosePlayer": "Зачыніць прайгравальнік",
"LabelCodec": "Кодэк",
"LabelCollapseSeries": "Згарнуць серыі",
"LabelCollapseSubSeries": "Згарнуць падсерыі",
"LabelCollection": "Калекцыя",
"LabelCollections": "Калекцыі",
"LabelComplete": "Завершана",
"LabelConfirmPassword": "Пацвердзіце пароль",
"LabelContinueListening": "Працягваць слухаць",
"LabelContinueReading": "Працягнуць чытанне",
"LabelContinueSeries": "Працягнуць серыі",
"LabelCover": "Вокладка",
"LabelCoverImageURL": "URL малюнка вокладкі",
"LabelCoverProvider": "Крыніца вокладак",
"LabelCreatedAt": "Дата стварэння",
"LabelCronExpression": "Запіс Cron",
"LabelCurrent": "Бягучы",
"LabelCurrently": "Бягучы:",
"LabelCustomCronExpression": "Уласны запіс Cron:",
"LabelDatetime": "Дата і час",
"LabelDays": "Дзён",
"LabelDeleteFromFileSystemCheckbox": "Выдаліць з файлавай сістэмы (зніміце галачку, каб выдаліць толькі з базы даных)",
"LabelDescription": "Апісанне",
"LabelDeselectAll": "Скасаваць выбар усяго",
"LabelDevice": "Прылада",
"LabelDeviceInfo": "Інфармацыя пра прыладу",
"LabelDeviceIsAvailableTo": "Прылада даступная для...",
"LabelDirectory": "Каталог",
"LabelDiscFromFilename": "Дыск з імя файла",
"LabelDiscFromMetadata": "Дыск па метададзеных",
"LabelDiscover": "Знайсці",
"LabelDownload": "Спампаваць",
"LabelDownloadNEpisodes": "Спампована {0} эпізодаў",
"LabelDownloadable": "Спампоўваецца",
"LabelDuration": "Працягласць",
"LabelDurationComparisonExactMatch": "(дакладнае супадзенне)",
"LabelDurationComparisonLonger": "(на {0} даўжэй)",
"LabelDurationComparisonShorter": "(на {0} карацей)",
"LabelDurationFound": "Знойдзеная працягласць:",
"LabelEbook": "Электронная кніга",
"LabelEbooks": "Электронныя кнігі",
"LabelEdit": "Рэдагаваць",
"LabelEmail": "Электронная пошта",
"LabelEmailSettingsFromAddress": "Адрас адпраўніка",
"LabelEmailSettingsRejectUnauthorized": "Адхіляць неаўтарызаваныя сертыфікаты",
"LabelEmailSettingsRejectUnauthorizedHelp": "Адключэнне праверкі SSL-сертыфіката можа зрабіць ваша злучэнне ўразлівым перад пагрозамі бяспекі, такімі як атакі \"чалавек пасярэдзіне\". Адключайце гэтую опцыю толькі калі цалкам разумееце наступствы і ўпэўнены ў надзейнасці паштовага сервера.",
"LabelEmailSettingsSecure": "Бяспечныя",
"LabelEmailSettingsSecureHelp": "Калі ўключана, злучэнне будзе выкарыстоўваць TLS пры падключэнні да сервера. Калі выключана, TLS будзе выкарыстоўвацца толькі ў выпадку падтрымкі пашырэння STARTTLS на серверы. У большасці выпадкаў усталюйце значэнне true пры падключэнні да порта 465. Для партоў 587 або 25 не ўключайце яго. (інфармацыя з nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Тэставы адрас",
"LabelEmbeddedCover": "Убудаваная вокладка",
"LabelEnable": "Уключыць",
"LabelEncodingBackupLocation": "Рэзервовая копія вашых арыгінальных аўдыёфайлаў будзе захавана ў:",
"LabelEncodingChaptersNotEmbedded": "Раздзелы не ўбудаваны ў шматдарожкавыя аўдыякнігі.",
"LabelEncodingClearItemCache": "Пераканайцеся, што перыядычна ачышчаеце кэш элементаў.",
"LabelEncodingFinishedM4B": "Гатовы файл M4B будзе змешчаны ў вашу тэчку з аўдыякнігамі па адрасе:",
"LabelEncodingInfoEmbedded": "Метаданыя будуць убудаваны ў аўдыядарожкі ўнутры вашай тэчкі з аўдыякнігамі.",
"LabelEncodingInfoEmbedded": "Метададзеныя будуць убудаваны ў аўдыядарожкі ўнутры вашай тэчкі з аўдыякнігамі.",
"LabelEncodingStartedNavigation": "Пасля запуску задачы вы можаце перайсці на іншую старонку.",
"LabelEncodingTimeWarning": "Кадаванне можа заняць да 30 хвілін.",
"LabelEnd": "Канец",
"LabelEndOfChapter": "Канец раздзела",
"LabelEpisode": "Эпізод",
"LabelEpisodeNotLinkedToRssFeed": "Эпізод не звязаны з RSS-стужкай",
"LabelEpisodeUrlFromRssFeed": "URL эпізоду з RSS-стужкі",
"LabelEpisodic": "Эпізадычны",
"LabelExample": "Прыклад",
"LabelExpandSeries": "Разгарнуць серыю",
"LabelExpandSubSeries": "Разгарнуць падсерыі",
"LabelExpired": "Пратэрмінаваны",
"LabelExpiresAt": "Тэрмін дзеяння заканчваецца ў",
"LabelExpiresInSeconds": "Тэрмін дзеяння заканчваецца праз (секунд)",
"LabelExpiresNever": "Ніколі",
"LabelExplicit": "Відверты",
"LabelFeedURL": "URL стужкі",
"LabelFetchingMetadata": "Атрыманне метададзеных",
"LabelFile": "Файл",
"LabelFileBirthtime": "Час стварэння файла",
"LabelFileModified": "Час змянення файла",
@@ -327,6 +408,8 @@
"LabelMaxEpisodesToKeepHelp": "Значэнне 0 не ўстанаўлівае максімальнага абмежавання. Пасля аўтаматычнай спампоўкі новага эпізоду будзе выдалены самы стары эпізод, калі ў вас больш за X эпізодаў. Пры кожнай новай спампоўцы будзе выдаляцца толькі 1 эпізод.",
"LabelMediaPlayer": "Медыяпрайгравальнік",
"LabelMediaType": "Тып медыя",
"LabelMetadataOrderOfPrecedenceDescription": "Крыніцы метададзеных з вышэйшым прыярытэтам будуць замяняць крыніцы з ніжэйшым прыярытэтам",
"LabelMetadataProvider": "Пастаўшчык метададзеных",
"LabelMissing": "Адсутнічае",
"LabelMore": "Больш",
"LabelMoreInfo": "Больш інфармацыі",
@@ -335,6 +418,7 @@
"LabelNarrators": "Чытальнікі",
"LabelNewestAuthors": "Новыя аўтары",
"LabelNewestEpisodes": "Новыя эпізоды",
"LabelNoCustomMetadataProviders": "Няма карыстацкіх пастаўшчыкоў метададзеных",
"LabelNotFinished": "Не скончана",
"LabelNotStarted": "Не пачата",
"LabelNotificationsMaxFailedAttemptsHelp": "Апавяшчэнні адключаюцца пасля таго, як не ўдаецца іх адправіць гэтулькі разоў",
@@ -353,7 +437,7 @@
"LabelPublishedDate": "Апублікавана {0}",
"LabelRSSFeedCustomOwnerEmail": "Карыстальніцкая электронная пошта ўладальніка",
"LabelRSSFeedCustomOwnerName": "Карыстальніцкае імя ўладальніка",
"LabelRSSFeedOpen": "RSS-стужка адкрытая",
"LabelRSSFeedOpen": "RSS-стужка адкрыта",
"LabelRSSFeedPreventIndexing": "Прадухіліць індэксацыю",
"LabelRSSFeedSlug": "Ідэнтыфікатар RSS-стужкі",
"LabelRSSFeedURL": "URL RSS-стужкі",
@@ -392,6 +476,7 @@
"LabelSettingsAudiobooksOnly": "Толькі аўдыякнігі",
"LabelSettingsAudiobooksOnlyHelp": "Уключэнне гэтай налады будзе ігнараваць файлы электронных кніг, калі толькі яны не знаходзяцца ў тэчцы з аўдыякнігамі. У такім выпадку яны будуць пазначаны як дадатковыя электронныя кнігі.",
"LabelSettingsBookshelfViewHelp": "Рэалістычны дызайн з драўлянымі паліцамі",
"LabelSettingsEnableWatcherForLibrary": "Аўтаматычна правяраць бібліятэку на змены",
"LabelSettingsEnableWatcherHelp": "Адключае аўтаматычнае дадаванне/абнаўленне элементаў пры выяўленні змен у файлах. *Патрабуецца перазапуск сервера",
"LabelSettingsEpubsAllowScriptedContent": "Дазволіць скрыптавы кантэнт у EPUB",
"LabelSettingsEpubsAllowScriptedContentHelp": "Дазволіць EPUB-файлам выконваць скрыпты. Рэкамендуецца пакінуць гэтую наладу выключанай, калі вы не давяраеце крыніцы EPUB-файлаў.",
@@ -409,6 +494,11 @@
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Палка \"Працягнуць серыю\" на галоўнай старонцы паказвае першую не пачатую кнігу ў серыях, дзе завершана хаця б адна кніга і няма кніг у працэсе чытання. Уключэнне гэтай налады дазволіць працягваць серыю з самай апошняй завершанай кнігі замест першай не пачатай.",
"LabelSettingsParseSubtitles": "Разабраць падзагалоўкі",
"LabelSettingsParseSubtitlesHelp": "Выдзяляць падзагаловак з назваў тэчак аўдыякніг.<br>Падзагаловак павінен быць аддзелены знакам \" - \".<br>Напрыклад, \"Назва кнігі - Падзагаловак тут\" мае падзагаловак \"Падзагаловак тут\"",
"LabelSettingsPreferMatchedMetadata": "Аддаваць перавагу супадаючым метададзеным",
"LabelSettingsPreferMatchedMetadataHelp": "Супадаючыя дадзеныя будуць замяняць дэталі элемента пры выкарыстанні функцыі Хуткі пошук. Па змаўчанні Хуткі пошук запаўняе толькі адсутныя дэталі.",
"LabelSettingsStoreCoversWithItemHelp": "Па змаўчанні вокладкі захоўваюцца ў /metadata/items, уключэнне гэтай опцыі забяспечыць захоўванне вокладак у тэчцы элемента вашай бібліятэкі. Захоўвацца будзе толькі адзін файл з назвай \"cover\"",
"LabelSettingsStoreMetadataWithItem": "Захоўваць метададзеныя разам з элементам",
"LabelSettingsStoreMetadataWithItemHelp": "Па змаўчанні метададзеныя захоўваюцца ў /metadata/items. Уключэнне гэтай опцыі забяспечыць захоўванне файлаў метададзеных у тэчках элементаў вашай бібліятэкі",
"LabelSettingsTimeFormat": "Фармат часу",
"LabelShareDownloadableHelp": "Дазваляе карыстальнікам, якія маюць спасылку на доступ, спампаваць ZIP-файл элемента бібліятэкі.",
"LabelShowAll": "Паказаць усё",
@@ -438,7 +528,7 @@
"LabelTags": "Меткі",
"LabelTagsAccessibleToUser": "Меткі, даступныя карыстальніку",
"LabelTagsNotAccessibleToUser": "Меткі, недаступныя карыстальніку",
"LabelTasks": "Выконваюцца задачы",
"LabelTasks": "Запушчаныя задачы",
"LabelTextEditorBulletedList": "Маркіраваны спіс",
"LabelTextEditorLink": "Спасылка",
"LabelTextEditorNumberedList": "Нумараваны спіс",
@@ -457,11 +547,14 @@
"LabelTimeRemaining": "Засталося {0}",
"LabelTimeToShift": "Час зрушэння ў секундах",
"LabelTitle": "Назва",
"LabelToolsSplitM4bDescription": "Стварэнне MP3 з M4B, падзеленага па раздзелах, з убудаванымі метаданымі, вокладкай і раздзеламі.",
"LabelToolsEmbedMetadata": "Убудаваць метададзеныя",
"LabelToolsEmbedMetadataDescription": "Убудаваць метададзеныя ў аўдыёфайлы, уключаючы вокладку і раздзелы.",
"LabelToolsMakeM4bDescription": "Стварыць аўдыёкнігу ў фармаце .M4B з убудаванымі метададзенымі, вокладкай і раздзеламі.",
"LabelToolsSplitM4bDescription": "Стварэнне MP3 з M4B, падзеленага па раздзелах, з убудаванымі метададзенымі, вокладкай і раздзеламі.",
"LabelTotalDuration": "Агульная працягласць",
"LabelTotalTimeListened": "Агульны час праслухоўвання",
"LabelTrackFromFilename": "Дарожка з імя файла",
"LabelTrackFromMetadata": "Дарожка з метаданых",
"LabelTrackFromMetadata": "Дарожка з метададзеных",
"LabelTracks": "Дарожкі",
"LabelTracksMultiTrack": "Шматдарожкавы",
"LabelTracksNone": "Няма дарожак",
@@ -510,19 +603,27 @@
"MessageBackupsLocationPathEmpty": "Шлях да месцазнаходжання рэзервовых копій не можа быць пустым",
"MessageBatchEditPopulateMapDetailsAllHelp": "Запоўніце ўключаныя палі дадзенымі з усіх элементаў. Палі з некалькімі значэннямі будуць аб'яднаны",
"MessageBatchEditPopulateMapDetailsItemHelp": "Запоўніце ўключаныя палі падрабязнасцей карты дадзенымі з гэтага элемента",
"MessageBatchQuickMatchDescription": "Хуткі пошук паспрабуе дадаць адсутныя вокладкі і метададзеныя для выбраных элементаў. Уключыце ніжэй выкладзеныя опцыі, каб дазволіць Хуткаму пошуку замяняць існуючыя вокладкі і/або метададзеныя.",
"MessageBookshelfNoRSSFeeds": "Няма адкрытых RSS-стужак",
"MessageChapterErrorStartGteDuration": "Няправільны час пачатку: ён павінен быць меншым за працягласць аўдыякнігі",
"MessageChapterErrorStartLtPrev": "Няправільны час пачатку: ён павінен быць большым або роўным часу пачатку папярэдняга раздзела",
"MessageConfirmCloseFeed": "Вы ўпэўнены, што жадаеце закрыць гэтую стужку?",
"MessageConfirmDeleteMetadataProvider": "Ці ўпэўненыя вы, што жадаеце выдаліць карыстацкага пастаўшчыка метададзеных \"{0}\"?",
"MessageConfirmEmbedMetadataInAudioFiles": "Ці ўпэўненыя вы, што жадаеце ўбудаваць метададзеныя ў {0} аўдыёфайлаў?",
"MessageConfirmPurgeCache": "Ачышчэнне кэша выдаліць увесь каталог па адрасе <code>/metadata/cache</code>. <br /><br /> Ці сапраўды вы жадаеце выдаліць каталог кэша?",
"MessageConfirmPurgeItemsCache": "Ачышчэнне кэша элементаў выдаліць увесь каталог па адрасе <code>/metadata/cache/items</code>. <br /> Вы ўпэўнены?",
"MessageConfirmRemoveListeningSessions": "Вы ўпэўнены, што жадаеце выдаліць {0} сеансаў праслухоўвання?",
"MessageConfirmRemoveMetadataFiles": "Ці ўпэўненыя вы, што жадаеце выдаліць усе файлы метададзеных{0} у тэчках элементаў вашай бібліятэкі?",
"MessageConfirmRemovePlaylist": "Вы ўпэўненыя, што жадаеце выдаліць свой спіс прайгравання \"{0}\"?",
"MessageConfirmSendEbookToDevice": "Вы ўпэўнены, што хочаце адправіць {0} электронную кнігу \"{1}\" на прыладу \"{2}\"?",
"MessageDownloadingEpisode": "Спампоўка эпізоду",
"MessageEmbedQueue": "У чарзе на ўбудаванне метададзеных (у чарзе {0})",
"MessageEpisodesQueuedForDownload": "{0} эпізод(аў) у чарзе для спампоўкі",
"MessageEreaderDevices": "Каб забяспечыць дастаўку электронных кніг, вам можа спатрэбіцца дадаць вышэйзгаданы адрас электроннай пошты як дазволенага адпраўніка для кожнай прылады, пералічанай ніжэй.",
"MessageFeedURLWillBe": "URL стужкі будзе {0}",
"MessageFetching": "Атрыманне...",
"MessageLoading": "Загрузка...",
"MessageLogsDescription": "Журналы захоўваюцца ў каталогу <code>/metadata/logs</code> у фармаце JSON. Журналы памылак захоўваюцца ў файле <code>/metadata/logs/crashlogs.txt</code>.",
"MessageMapChapterTitles": "Супаставіць назвы раздзелаў з вашымі існуючымі раздзеламі аўдыякнігі без змянення часовых метак",
"MessageMarkAsFinished": "Пазначыць як скончана",
"MessageNoBookmarks": "Няма закладак",
@@ -536,6 +637,7 @@
"MessageNoMediaProgress": "Няма прагрэсу медыя",
"MessageNoPodcastFeed": "Няправільны падкаст: Няма стужкі",
"MessageNoPodcastsFound": "Падкасты не знойдзены",
"MessageNoTasksRunning": "Няма запушчаных задач",
"MessageNoUpdatesWereNecessary": "Абнаўленні не патрабаваліся",
"MessageNoUserPlaylists": "У вас няма спісаў прайгравання",
"MessageNoUserPlaylistsHelp": "Спісы прайгравання прыватныя. Толькі карыстальнік, які іх стварыў, можа іх бачыць.",
@@ -543,11 +645,28 @@
"MessagePlaylistCreateFromCollection": "Стварыць спіс прайгравання з калекцыі",
"MessagePodcastHasNoRSSFeedForMatching": "У падкаста няма URL RSS-стужкі для супадзення",
"MessagePodcastSearchField": "Увядзіце пошукавы запыт або URL RSS-стужкі",
"MessageQuickMatchDescription": "Запоўніць пустыя дэталі элемента і вокладку першым вынікам супадзення з '{0}'. Не замяняе дэталі, калі опцыя «Аддаваць перавагу супадаючым метададзеным» на серверы не ўключана.",
"MessageReportBugsAndContribute": "Паведамляйце пра памылкі, прапануйце новыя функцыі і ўдзельнічайце на",
"MessageRestoreBackupWarning": "Аднаўленне рэзервовай копіі перазапіша ўсю базу даных, размешчаную ў /config, а таксама вокладкі ў /metadata/items і /metadata/authors. <br /><br /> Рэзервовыя копіі не змяняюць файлы ў вашых тэчках бібліятэкі. Калі вы ўключылі наладкі сервера для захоўвання воклак і метададзеных у тэчках бібліятэкі, гэтыя файлы не будуць захаваныя ў рэзервовых копіях і не зменяцца. <br /><br /> Усе кліенты, якія карыстаюцца вашым серверам, будуць аўтаматычна абноўлены.",
"MessageScheduleRunEveryWeekdayAtTime": "Выконваць кожныя {0} у {1}",
"MessageStartPlaybackAtTime": "Пачаць прайграванне для \"{0}\" з {1}?",
"MessageTaskAudioFileNotWritable": "Аўдыёфайл \"{0}\" недаступны для запісу",
"MessageTaskCanceledByUser": "Задача скасавана карыстальнікам",
"MessageTaskDownloadingEpisodeDescription": "Спампоўка эпізоду \"{0}\"",
"MessageTaskEmbeddingMetadata": "Убудаванне метададзеных",
"MessageTaskEmbeddingMetadataDescription": "Убудаванне метададзеных у аўдыёкнігу \"{0}\"",
"MessageTaskEncodingM4b": "Кадаванне M4B",
"MessageTaskEncodingM4bDescription": "Кадаванне аўдыякнігі \"{0}\" у адзін файл m4b",
"MessageTaskFailed": "Не ўдалося",
"MessageTaskFailedToBackupAudioFile": "Не ўдалося зрабіць рэзервовую копію аўдыёфайла \"{0}\"",
"MessageTaskFailedToCreateCacheDirectory": "Не ўдалося стварыць каталог кэша",
"MessageTaskFailedToEmbedMetadataInFile": "Не ўдалося ўбудаваць метададзеныя ў файл \"{0}\"",
"MessageTaskFailedToMergeAudioFiles": "Не ўдалося аб’яднаць аўдыёфайлы",
"MessageTaskFailedToMoveM4bFile": "Не ўдалося перамясціць файл m4b",
"MessageTaskFailedToWriteMetadataFile": "Не ўдалося захаваць файл метададзеных",
"MessageTaskMatchingBooksInLibrary": "Пошук супадзенняў кніг у бібліятэцы \"{0}\"",
"MessageTaskNoFilesToScan": "Няма файлаў для сканавання",
"MessageTaskOpmlImport": "Імпарт OPML",
"MessageTaskOpmlImportDescription": "Стварэнне падкастаў з {0} RSS-стужак",
"MessageTaskOpmlImportFeed": "Імпарт стужкі з OPML",
"MessageTaskOpmlImportFeedDescription": "Імпартаванне RSS-стужкі \"{0}\"",
@@ -556,6 +675,7 @@
"MessageTaskOpmlImportFeedPodcastExists": "Падкаст ужо існуе па гэтым шляху",
"MessageTaskOpmlImportFeedPodcastFailed": "Не ўдалося стварыць падкаст",
"MessageTaskOpmlParseNoneFound": "У OPML-файле не знойдзена стужак",
"MessageTaskTargetDirectoryNotWritable": "Мэтавы каталог недаступны для запісу",
"NoteChapterEditorTimes": "Заўвага: Час пачатку першага раздзела павінен заставацца 0:00, а час пачатку апошняга раздзела не можа перавышаць працягласць гэтай аўдыякнігі.",
"NoteRSSFeedPodcastAppsHttps": "Папярэджанне: большасць праграм для падкастаў патрабуюць, каб URL RSS-стужкі выкарыстоўваў HTTPS",
"NoteRSSFeedPodcastAppsPubDate": "Папярэджанне: адзін ці больш вашых эпізодаў не маюць даты публікацыі. Некаторыя праграмы для падкастаў патрабуюць гэтага.",
@@ -602,6 +722,8 @@
"ToastPlaylistCreateSuccess": "Спіс прайгравання створаны",
"ToastPlaylistRemoveSuccess": "Спіс прайгравання выдалены",
"ToastPlaylistUpdateSuccess": "Спіс прайгравання абноўлены",
"ToastPodcastCreateFailed": "Не ўдалося стварыць падкаст",
"ToastPodcastCreateSuccess": "Падкаст паспяхова створаны",
"ToastPodcastGetFeedFailed": "Не ўдалося атрымаць стужку падкаста",
"ToastPodcastNoEpisodesInFeed": "У RSS-стужцы не знойдзена эпізодаў",
"ToastPodcastNoRssFeed": "У падкаста няма RSS-стужкі",
@@ -610,6 +732,7 @@
"ToastSendEbookToDeviceFailed": "Не ўдалося адправіць электронную кнігу на прыладу",
"ToastSendEbookToDeviceSuccess": "Электронная кніга адпраўлена на прыладу \"{0}\"",
"ToastSleepTimerDone": "Таймер сну скончыўся... Хр-р-р",
"ToastUploaderItemExistsInSubdirectoryError": "Элемент \"{0}\" выкарыстоўвае падкаталог шляху загрузкі.",
"ToastUserPasswordMustChange": "Новы пароль не можа супадаць са старым",
"ToastUserRootRequireName": "Неабходна ўвесці імя карыстальніка адміністратара"
}

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Přidat",
"ButtonAddApiKey": "Přidat API klíč",
"ButtonAddChapters": "Přidat kapitoly",
"ButtonAddDevice": "Přidat zařízení",
"ButtonAddLibrary": "Přidat knihovnu",
@@ -20,6 +21,7 @@
"ButtonChooseAFolder": "Vybrat složku",
"ButtonChooseFiles": "Vybrat soubory",
"ButtonClearFilter": "Vymazat filtr",
"ButtonClose": "Zavřít",
"ButtonCloseFeed": "Zavřít kanál",
"ButtonCloseSession": "Zavřít otevřenou relaci",
"ButtonCollections": "Kolekce",
@@ -119,6 +121,7 @@
"HeaderAccount": "Účet",
"HeaderAddCustomMetadataProvider": "Přidat vlastního poskytovatele metadat",
"HeaderAdvanced": "Pokročilé",
"HeaderApiKeys": "API klíče",
"HeaderAppriseNotificationSettings": "Nastavení oznámení Apprise",
"HeaderAudioTracks": "Zvukové stopy",
"HeaderAudiobookTools": "Nástroje pro správu souborů audioknih",
@@ -154,7 +157,7 @@
"HeaderListeningSessions": "Poslechové relace",
"HeaderListeningStats": "Statistiky poslechu",
"HeaderLogin": "Přihlásit",
"HeaderLogs": "Záznamy",
"HeaderLogs": "Logy",
"HeaderManageGenres": "Spravovat žánry",
"HeaderManageTags": "Spravovat štítky",
"HeaderMapDetails": "Podrobnosti mapování",
@@ -162,6 +165,7 @@
"HeaderMetadataOrderOfPrecedence": "Pořadí priorit metadat",
"HeaderMetadataToEmbed": "Metadata k vložení",
"HeaderNewAccount": "Nový účet",
"HeaderNewApiKey": "Nový API klíč",
"HeaderNewLibrary": "Nová knihovna",
"HeaderNotificationCreate": "Vytvořit notifikaci",
"HeaderNotificationUpdate": "Aktualizovat notifikaci",
@@ -177,6 +181,7 @@
"HeaderPlaylist": "Seznam skladeb",
"HeaderPlaylistItems": "Položky seznamu přehrávání",
"HeaderPodcastsToAdd": "Podcasty k přidání",
"HeaderPresets": "Předvolba",
"HeaderPreviewCover": "Náhled obálky",
"HeaderRSSFeedGeneral": "Podrobnosti o RSS",
"HeaderRSSFeedIsOpen": "Informační kanál RSS je otevřený",
@@ -205,6 +210,7 @@
"HeaderTableOfContents": "Obsah",
"HeaderTools": "Nástroje",
"HeaderUpdateAccount": "Aktualizovat účet",
"HeaderUpdateApiKey": "Aktualizovat API klíč",
"HeaderUpdateAuthor": "Aktualizovat autora",
"HeaderUpdateDetails": "Aktualizovat podrobnosti",
"HeaderUpdateLibrary": "Aktualizovat knihovnu",
@@ -234,6 +240,10 @@
"LabelAllUsersExcludingGuests": "Všichni uživatelé kromě hostů",
"LabelAllUsersIncludingGuests": "Všichni uživatelé včetně hostů",
"LabelAlreadyInYourLibrary": "Již ve vaší knihovně",
"LabelApiKeyCreated": "API klíč \"{0}\" byl úspěšně vytvořen.",
"LabelApiKeyCreatedDescription": "Zkopírujte si API klíč nyní, později již nebude možné jej zobrazit.",
"LabelApiKeyUser": "Vydávat se za uživatele",
"LabelApiKeyUserDescription": "Tento API klíč bude mít stejná oprávnění jako uživatel za něhož vystupuje. V protokolech to bude vypadat jako kdyby požadavky vytvářel přímo daný uživatel.",
"LabelApiToken": "API Token",
"LabelAppend": "Připojit",
"LabelAudioBitrate": "Bitový tok zvuku (např. 128k)",
@@ -345,11 +355,15 @@
"LabelExample": "Příklad",
"LabelExpandSeries": "Rozbalit série",
"LabelExpandSubSeries": "Rozbalit podsérie",
"LabelExplicit": "Explicitní",
"LabelExpired": "Expirovaný",
"LabelExpiresAt": "Expiruje v",
"LabelExpiresInSeconds": "Expiruje za (sekundy)",
"LabelExpiresNever": "Nikdy",
"LabelExplicit": "Explicitně",
"LabelExplicitChecked": "Explicitní (zaškrtnuto)",
"LabelExplicitUnchecked": "Není explicitní (nezaškrtnuto)",
"LabelExportOPML": "Export OPML",
"LabelFeedURL": "URL zdroje",
"LabelFeedURL": "URL kanálu",
"LabelFetchingMetadata": "Získávání metadat",
"LabelFile": "Soubor",
"LabelFileBirthtime": "Čas vzniku souboru",
@@ -454,6 +468,7 @@
"LabelNewestEpisodes": "Nejnovější epizody",
"LabelNextBackupDate": "Datum příští zálohy",
"LabelNextScheduledRun": "Další naplánované spuštění",
"LabelNoApiKeys": "Žádné API klíče",
"LabelNoCustomMetadataProviders": "Žádní vlastní poskytovatelé metadat",
"LabelNoEpisodesSelected": "Nebyly vybrány žádné epizody",
"LabelNotFinished": "Nedokončeno",
@@ -513,9 +528,9 @@
"LabelPublishers": "Vydavatelé",
"LabelRSSFeedCustomOwnerEmail": "Vlastní e-mail vlastníka",
"LabelRSSFeedCustomOwnerName": "Vlastní jméno vlastníka",
"LabelRSSFeedOpen": "Otevření RSS kanálu",
"LabelRSSFeedOpen": "RSS kanál otevřen",
"LabelRSSFeedPreventIndexing": "Zabránit indexování",
"LabelRSSFeedSlug": "RSS kanál Slug",
"LabelRSSFeedSlug": "Klíčové slovo kanálu RSS",
"LabelRSSFeedURL": "URL RSS kanálu",
"LabelRandomly": "Náhodně",
"LabelReAddSeriesToContinueListening": "Znovu přidat sérii k pokračování poslechu",
@@ -530,6 +545,7 @@
"LabelReleaseDate": "Datum vydání",
"LabelRemoveAllMetadataAbs": "Odebrat všechny soubory metadata.abs",
"LabelRemoveAllMetadataJson": "Smazat všechny soubory metadata.json",
"LabelRemoveAudibleBranding": "Odebrat úvod a závěr Audible z kapitol",
"LabelRemoveCover": "Odstranit obálku",
"LabelRemoveMetadataFile": "Odstranit soubory metadat ve složkách položek knihovny",
"LabelRemoveMetadataFileHelp": "Odstraníte všechny soubory metadata.json a metadata.abs ve svých složkách {0}.",
@@ -542,6 +558,7 @@
"LabelSelectAll": "Vybrat vše",
"LabelSelectAllEpisodes": "Vybrat všechny epizody",
"LabelSelectEpisodesShowing": "Vyberte {0} epizody, které se zobrazují",
"LabelSelectUser": "Vybrat uživatele",
"LabelSelectUsers": "Vybrat uživatele",
"LabelSendEbookToDevice": "Odeslat e-knihu do...",
"LabelSequence": "Sekvence",
@@ -549,7 +566,7 @@
"LabelSeries": "Série",
"LabelSeriesName": "Název série",
"LabelSeriesProgress": "Průběh série",
"LabelServerLogLevel": "Úroveň protokolu serveru",
"LabelServerLogLevel": "Úroveň Logování serveru",
"LabelServerYearReview": "Přehled roku na serveru ({0})",
"LabelSetEbookAsPrimary": "Nastavit jako primární",
"LabelSetEbookAsSupplementary": "Nastavit jako doplňkové",
@@ -705,6 +722,10 @@
"LabelYourProgress": "Váš pokrok",
"MessageAddToPlayerQueue": "Přidat do fronty přehrávače",
"MessageAppriseDescription": "Abyste mohli používat tuto funkci, musíte mít spuštěnou instanci <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> nebo API, které bude zpracovávat stejné požadavky. <br />Adresa URL API Apprise by měla být úplná URL cesta pro odeslání oznámení, např. pokud je vaše instance API obsluhována na adrese <code>http://192.168.1.1:8337</code> pak byste měli zadat <code>http://192.168.1.1:8337/notify</code>.",
"MessageAsinCheck": "Ujistěte se, že používáte ASIN ze správného regionu Audible a ne z Amazonu.",
"MessageAuthenticationLegacyTokenWarning": "Zastaralé API tokeny budou v budoucnu odstraněny. Použijte místo nich <a href=\"/config/api-keys\">API klíče</a>.",
"MessageAuthenticationOIDCChangesRestart": "Po uložení restartujte server, aby se změny OIDC použily.",
"MessageAuthenticationSecurityMessage": "Bezpečnost autentizace byla vylepšena. Všichni uživatelé se musí znovu přihlásit.",
"MessageBackupsDescription": "Zálohy zahrnují uživatele, průběh uživatele, podrobnosti o položkách knihovny, nastavení serveru a obrázky uložené v <code>/metadata/items</code> a <code>/metadata/authors</code>. Zálohy <strong>ne</strong> zahrnují všechny soubory uložené ve složkách knihovny.",
"MessageBackupsLocationEditNote": "Poznámka: Změna umístění záloh nepřesune ani nezmění existující zálohy",
"MessageBackupsLocationNoEditNote": "Poznámka: Umístění záloh je nastavené z proměnných prostředí a nelze zde změnit.",
@@ -723,8 +744,10 @@
"MessageChapterErrorStartGteDuration": "Neplatný čas začátku, musí být kratší než doba trvání audioknihy",
"MessageChapterErrorStartLtPrev": "Neplatný čas začátku, musí být větší nebo roven času začátku předchozí kapitoly",
"MessageChapterStartIsAfter": "Začátek kapitoly přesahuje konec audioknihy",
"MessageChaptersNotFound": "Kapitoly nenalezeny",
"MessageCheckingCron": "Kontrola cronu...",
"MessageConfirmCloseFeed": "Opravdu chcete zavřít tento kanál?",
"MessageConfirmDeleteApiKey": "Opravdu chcete vymazat API klíč \"{0}\"?",
"MessageConfirmDeleteBackup": "Opravdu chcete smazat zálohu pro {0}?",
"MessageConfirmDeleteDevice": "Opravdu chcete vymazat zařízení e-reader \"{0}\"?",
"MessageConfirmDeleteFile": "Tento krok smaže soubor ze souborového systému. Jsi si jisti?",
@@ -752,6 +775,7 @@
"MessageConfirmRemoveAuthor": "Opravdu chcete odstranit autora \"{0}\"?",
"MessageConfirmRemoveCollection": "Opravdu chcete odstranit kolekci \"{0}\"?",
"MessageConfirmRemoveEpisode": "Opravdu chcete odstranit epizodu \"{0}\"?",
"MessageConfirmRemoveEpisodeNote": "Poznámka: Tím se zvukový soubor neodstraní, pokud nepřepnete volbu “Tvrdé odstranění souboru“",
"MessageConfirmRemoveEpisodes": "Opravdu chcete odstranit {0} epizody?",
"MessageConfirmRemoveListeningSessions": "Opravdu chcete odebrat {0} poslechových relací?",
"MessageConfirmRemoveMetadataFiles": "Jste si jisti, že chcete odstranit všechny metadata.{0} soubory ve složkách s položkami ve vaší knihovně?",
@@ -779,12 +803,13 @@
"MessageForceReScanDescription": "znovu prohledá všechny soubory jako při novém skenování. ID3 tagy zvukových souborů OPF soubory a textové soubory budou skenovány jako nové.",
"MessageImportantNotice": "Důležité upozornění!",
"MessageInsertChapterBelow": "Vložit kapitolu níže",
"MessageInvalidAsin": "Neplatný ASIN",
"MessageItemsSelected": "{0} vybraných položek",
"MessageItemsUpdated": "{0} položky byly aktualizovány",
"MessageJoinUsOn": "Přidejte se k nám",
"MessageLoading": "Načítá se...",
"MessageLoadingFolders": "Načítám složky...",
"MessageLogsDescription": "Protokoly se ukládají do souborů JSON v <code>/metadata/logs</code>. Protokoly o pádech jsou uloženy v <code>/metadata/logs/crash_logs.txt</code>.",
"MessageLogsDescription": "Logy se ukládají do souborů JSON v <code>/metadata/logs</code>. Logy o pádech jsou uloženy v <code>/metadata/logs/crash_logs.txt</code>.",
"MessageM4BFailed": "M4B se nezdařil!",
"MessageM4BFinished": "M4B dokončen!",
"MessageMapChapterTitles": "Mapování názvů kapitol ke stávajícím kapitolám audioknihy bez úpravy časových razítek",
@@ -808,11 +833,11 @@
"MessageNoEpisodes": "Žádné epizody",
"MessageNoFoldersAvailable": "Nejsou k dispozici žádné složky",
"MessageNoGenres": "Žádné žánry",
"MessageNoIssues": "Žádné výtisk",
"MessageNoIssues": "Žádné problémy",
"MessageNoItems": "Žádné položky",
"MessageNoItemsFound": "Nebyly nalezeny žádné položky",
"MessageNoListeningSessions": "Žádné poslechové relace",
"MessageNoLogs": "Žádné protokoly",
"MessageNoLogs": "Žádné logy",
"MessageNoMediaProgress": "Žádný průběh médií",
"MessageNoNotifications": "Žádná oznámení",
"MessageNoPodcastFeed": "Neplatný podcast: Žádný kanál",
@@ -850,6 +875,7 @@
"MessageScheduleRunEveryWeekdayAtTime": "Spusť každý {0} v {1}",
"MessageSearchResultsFor": "Výsledky hledání pro",
"MessageSelected": "{0} vybráno",
"MessageSeriesSequenceCannotContainSpaces": "Sekvence série nesmí obsahovat mezery",
"MessageServerCouldNotBeReached": "Server je nedostupný",
"MessageSetChaptersFromTracksDescription": "Nastavit kapitoly jako kapitolu a název kapitoly jako název zvukového souboru",
"MessageShareExpirationWillBe": "Expiruje <strong>{0}</strong>",
@@ -911,6 +937,8 @@
"NotificationOnBackupCompletedDescription": "Spuštěno po dokončení zálohování",
"NotificationOnBackupFailedDescription": "Spuštěno pokud zálohování selže",
"NotificationOnEpisodeDownloadedDescription": "Spuštěno při automatickém stažení epizody podcastu",
"NotificationOnRSSFeedDisabledDescription": "Aktivováno když je automatické stahování pozastaveno z důvodu příliš mnoho neůspěšných pokusů",
"NotificationOnRSSFeedFailedDescription": "Aktivováno když selže RSS kanál pro stahování epizod",
"NotificationOnTestDescription": "Akce pro otestování upozorňovacího systému",
"PlaceholderNewCollection": "Nový název kolekce",
"PlaceholderNewFolderPath": "Nová cesta ke složce",
@@ -955,7 +983,7 @@
"ToastBackupRestoreFailed": "Nepodařilo se obnovit zálohu",
"ToastBackupUploadFailed": "Nepodařilo se nahrát zálohu",
"ToastBackupUploadSuccess": "Záloha nahrána",
"ToastBatchApplyDetailsToItemsSuccess": "Detaily aplikované na položky",
"ToastBatchApplyDetailsToItemsSuccess": "Detaily byly aplikované na položky",
"ToastBatchDeleteFailed": "Hromadné smazání selhalo",
"ToastBatchDeleteSuccess": "Hromadné smazání proběhlo úspěšně",
"ToastBatchQuickMatchFailed": "Rychlá schoda dávky se nezdařila!",
@@ -968,6 +996,8 @@
"ToastCachePurgeFailed": "Nepodařilo se vyčistit mezipaměť",
"ToastCachePurgeSuccess": "Vyrovnávací paměť úspěšně vyčištěna",
"ToastChaptersHaveErrors": "Kapitoly obsahují chyby",
"ToastChaptersInvalidShiftAmountLast": "Nesprávná délka posunu. Čas začátku poslední kapitoly by přesáhl dobu trvání této audioknihy.",
"ToastChaptersInvalidShiftAmountStart": "Nesprávná délka posunu. První kapitola by měla nulovou nebo zápornou délku a byla by přepsána druhou kapitolou. Zvětšete čas začátku druhé kapitoly.",
"ToastChaptersMustHaveTitles": "Kapitoly musí mít názvy",
"ToastChaptersRemoved": "Kapitoly odstraněny",
"ToastChaptersUpdated": "Kapitola aktualizována",
@@ -989,6 +1019,8 @@
"ToastEpisodeDownloadQueueClearSuccess": "Fronta stahování epizod je prázdná",
"ToastEpisodeUpdateSuccess": "{0} epizod aktualizováno",
"ToastErrorCannotShare": "Na tomto zařízení nelze nativně sdílet",
"ToastFailedToCreate": "Nepodařilo se vytvořit",
"ToastFailedToDelete": "Nepodařilo se odstranit",
"ToastFailedToLoadData": "Nepodařilo se načíst data",
"ToastFailedToMatch": "Nepodařilo se spárovat",
"ToastFailedToShare": "Sdílení selhalo",
@@ -1020,6 +1052,7 @@
"ToastMustHaveAtLeastOnePath": "Musí mít minimálně jednu cestu",
"ToastNameEmailRequired": "Jméno a email jsou vyžadovány",
"ToastNameRequired": "Jméno je vyžadováno",
"ToastNewApiKeyUserError": "Je nutné vybrat uživatele",
"ToastNewEpisodesFound": "{0} nových epizod bylo nalezeno",
"ToastNewUserCreatedFailed": "Chyba při vytváření účtu: \"{0}\"",
"ToastNewUserCreatedSuccess": "Vytvořen nový účet",
@@ -1088,7 +1121,7 @@
"ToastUnlinkOpenIdFailed": "Chyba při odpárování uživatele z OpenID",
"ToastUnlinkOpenIdSuccess": "Uživatel odpárován z uživatele z OpenID",
"ToastUploaderFilepathExistsError": "Soubor \"{0}\" na serveru již existuje",
"ToastUploaderItemExistsInSubdirectoryError": "Položka \"{0}\" používá podsložku nahrávané cesty.",
"ToastUploaderItemExistsInSubdirectoryError": "Položka \"{0}\" používá podadresář cesty pro nahrání.",
"ToastUserDeleteFailed": "Nepodařilo se smazat uživatele",
"ToastUserDeleteSuccess": "Uživatel smazán",
"ToastUserPasswordChangeSuccess": "Heslo bylo změněno úspěšně",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Tilføj",
"ButtonAddApiKey": "Tilføj API-nøgle",
"ButtonAddChapters": "Tilføj kapitler",
"ButtonAddDevice": "Tilføj enhed",
"ButtonAddLibrary": "Tilføj Bibliotek",
@@ -20,6 +21,7 @@
"ButtonChooseAFolder": "Vælg en mappe",
"ButtonChooseFiles": "Vælg filer",
"ButtonClearFilter": "Ryd filter",
"ButtonClose": "Luk",
"ButtonCloseFeed": "Luk feed",
"ButtonCloseSession": "Luk Åben Session",
"ButtonCollections": "Samlinger",
@@ -119,6 +121,7 @@
"HeaderAccount": "Konto",
"HeaderAddCustomMetadataProvider": "Tilføj Brugerdefineret Metadataudbyder",
"HeaderAdvanced": "Avanceret",
"HeaderApiKeys": "API-nøgler",
"HeaderAppriseNotificationSettings": "Apprise Notifikationsindstillinger",
"HeaderAudioTracks": "Lydspor",
"HeaderAudiobookTools": "Audiobog Filhåndteringsværktøjer",
@@ -162,6 +165,7 @@
"HeaderMetadataOrderOfPrecedence": "Metadata-prioritet",
"HeaderMetadataToEmbed": "Metadata til indlejring",
"HeaderNewAccount": "Ny Konto",
"HeaderNewApiKey": "Ny API-nøgle",
"HeaderNewLibrary": "Nyt Bibliotek",
"HeaderNotificationCreate": "Opret Notifikation",
"HeaderNotificationUpdate": "Updater Notifikation",
@@ -177,6 +181,7 @@
"HeaderPlaylist": "Afspilningsliste",
"HeaderPlaylistItems": "Afspilningsliste Elementer",
"HeaderPodcastsToAdd": "Podcasts til Tilføjelse",
"HeaderPresets": "Forudindstillinger",
"HeaderPreviewCover": "Forhåndsvis Omslag",
"HeaderRSSFeedGeneral": "RSS Detaljer",
"HeaderRSSFeedIsOpen": "RSS Feed er Åben",
@@ -205,6 +210,7 @@
"HeaderTableOfContents": "Indholdsfortegnelse",
"HeaderTools": "Værktøjer",
"HeaderUpdateAccount": "Opdater Konto",
"HeaderUpdateApiKey": "Opdater API-nøgle",
"HeaderUpdateAuthor": "Opdater Forfatter",
"HeaderUpdateDetails": "Opdater Detaljer",
"HeaderUpdateLibrary": "Opdater Bibliotek",
@@ -234,6 +240,10 @@
"LabelAllUsersExcludingGuests": "Alle bruger eksklusiv gæster",
"LabelAllUsersIncludingGuests": "Alle bruger inklusiv gæster",
"LabelAlreadyInYourLibrary": "Allerede i dit bibliotek",
"LabelApiKeyCreated": "API-nøgle\"{0}\" oprettet succesfuldt.",
"LabelApiKeyCreatedDescription": "Sørg for at kopiere API-nøglen nu, da du ikke vil kunne se den igen.",
"LabelApiKeyUser": "Ret på vegne af brugeren",
"LabelApiKeyUserDescription": "Denne API-nøgle vil have de samme tilladelser som den bruger, den handler på vegne af. Dette vil fremgå på samme måde i logfiler, som hvis brugeren foretog anmodningen.",
"LabelApiToken": "API Token",
"LabelAppend": "Tilføj",
"LabelAudioBitrate": "Lydbitrate (f.eks. 128k)",
@@ -286,7 +296,7 @@
"LabelCover": "Omslag",
"LabelCoverImageURL": "Omslagsbillede URL",
"LabelCoverProvider": "Cover billede udbyder",
"LabelCreatedAt": "Oprettet Kl.",
"LabelCreatedAt": "Oprettet d.",
"LabelCronExpression": "Cron Udtryk",
"LabelCurrent": "Aktuel",
"LabelCurrently": "Aktuelt:",
@@ -345,6 +355,10 @@
"LabelExample": "Eksempel",
"LabelExpandSeries": "Udfold serie",
"LabelExpandSubSeries": "Udfold underserie",
"LabelExpired": "Udløbet",
"LabelExpiresAt": "Udløbsdato",
"LabelExpiresInSeconds": "Udløber om (seconds)",
"LabelExpiresNever": "Aldrig",
"LabelExplicit": "Eksplisit",
"LabelExplicitChecked": "Eksplicit (markeret)",
"LabelExplicitUnchecked": "Ikke eksplicit (ikke markeret)",
@@ -454,6 +468,7 @@
"LabelNewestEpisodes": "Nyeste episoder",
"LabelNextBackupDate": "Næste sikkerhedskopi dato",
"LabelNextScheduledRun": "Næste planlagte kørsel",
"LabelNoApiKeys": "Ingen API-nøgler",
"LabelNoCustomMetadataProviders": "Ingen brugerdefinerede metadata udbydere",
"LabelNoEpisodesSelected": "Ingen episoder valgt",
"LabelNotFinished": "Ikke færdig",
@@ -513,7 +528,7 @@
"LabelPublishers": "Forlag",
"LabelRSSFeedCustomOwnerEmail": "Brugerdefineret ejerens e-mail",
"LabelRSSFeedCustomOwnerName": "Brugerdefineret ejerens navn",
"LabelRSSFeedOpen": "Åben RSS-feed",
"LabelRSSFeedOpen": "RSS-feed åbent",
"LabelRSSFeedPreventIndexing": "Forhindrer indeksering",
"LabelRSSFeedSlug": "RSS-feed-slug",
"LabelRSSFeedURL": "RSS-feed-URL",
@@ -530,6 +545,7 @@
"LabelReleaseDate": "Udgivelsesdato",
"LabelRemoveAllMetadataAbs": "Fjern alle metadata.abs filer",
"LabelRemoveAllMetadataJson": "Fjern alle metadata.json filer",
"LabelRemoveAudibleBranding": "Fjern Audible intro og outro fra kapitler",
"LabelRemoveCover": "Fjern omslag",
"LabelRemoveMetadataFile": "Fjern alle metadata filer i biblioteksmapper",
"LabelRemoveMetadataFileHelp": "Fjern alle metadata.json og metadata.abs filer i dine {0} mapper.",
@@ -542,6 +558,7 @@
"LabelSelectAll": "Vælg alle",
"LabelSelectAllEpisodes": "Vælg alle episoder",
"LabelSelectEpisodesShowing": "Vælg {0} episoder vist",
"LabelSelectUser": "Vælg bruger",
"LabelSelectUsers": "Valgte brugere",
"LabelSendEbookToDevice": "Send e-bog til...",
"LabelSequence": "Sekvens",
@@ -575,14 +592,14 @@
"LabelSettingsLibraryMarkAsFinishedPercentComplete": "Procent gennemført er større end",
"LabelSettingsLibraryMarkAsFinishedTimeRemaining": "Tid tilbage er mindre end (sekunder)",
"LabelSettingsLibraryMarkAsFinishedWhen": "Marker medie indhold som færdigt når",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Spring til tidligere bøger i Fortsæt serie",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Fortsæt Serien siden hylde viser de første bøger som ikke er startet i serier med mindst en bog som ikke er startet og ingen bøger i gang. Aktivering af denne indstilling vil fortsætte serien fra den sidst gennemførte bog modsat den først ikke startede bog.",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Spring tidligere bøger i Fortsæt serie over",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Fortsæt Serien siden viser den første bog som ikke er startet i serier med mindst en bog som ikke er startet og hvor ingen bøger i gang. Aktivering af denne indstilling vil fortsætte serien fra den sidst gennemførte bog i stedet for fra den første ikke startede bog.",
"LabelSettingsParseSubtitles": "Fortolk undertitler",
"LabelSettingsParseSubtitlesHelp": "Udtræk undertekster fra lydbogsmappenavne.<br>Undertitler skal adskilles af \" - \"<br>f.eks. \"Bogtitel - En undertitel her\" har undertitlen \"En undertitel her\"",
"LabelSettingsPreferMatchedMetadata": "Foretræk matchede metadata",
"LabelSettingsPreferMatchedMetadataHelp": "Matchede data vil tilsidesætte elementdetaljer ved brug af Hurtig Match. Som standard udfylder Hurtig Match kun manglende detaljer.",
"LabelSettingsSkipMatchingBooksWithASIN": "Spring over matchende bøger, der allerede har en ASIN",
"LabelSettingsSkipMatchingBooksWithISBN": "Spring matchende bøger over, som allerede har et ISBN-nummer",
"LabelSettingsSkipMatchingBooksWithASIN": "Ignorer matchende bøger, der allerede har en ASIN",
"LabelSettingsSkipMatchingBooksWithISBN": "Ignorer matchende bøger, som allerede har et ISBN-nummer",
"LabelSettingsSortingIgnorePrefixes": "Ignorer præfikser ved sortering",
"LabelSettingsSortingIgnorePrefixesHelp": "f.eks. for præfikset \"the\" vil bogtitlen \"The Book Title\" blive sorteret som \"Book Title, The\"",
"LabelSettingsSquareBookCovers": "Brug kvadratiske bogomslag",
@@ -604,6 +621,7 @@
"LabelSlug": "Snegl",
"LabelSortAscending": "Stigende",
"LabelSortDescending": "Faldende",
"LabelSortPubDate": "Sortér Pub Dato",
"LabelStart": "Start",
"LabelStartTime": "Starttid",
"LabelStarted": "Startet",
@@ -704,6 +722,10 @@
"LabelYourProgress": "Din fremgang",
"MessageAddToPlayerQueue": "Tilføj til afspilningskø",
"MessageAppriseDescription": "For at bruge denne funktion skal du have en instans af <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> kørende eller en API, der håndterer de samme anmodninger. <br /> Apprise API-webadressen skal være den fulde URL-sti for at sende underretningen, f.eks. hvis din API-instans er tilgængelig på <code>http://192.168.1.1:8337</code>, så skal du bruge <code>http://192.168.1.1:8337/notify</code>.",
"MessageAsinCheck": "Sikr dig at du bruger ASIN fra den korrekte Audible region, ikke Amazon.",
"MessageAuthenticationLegacyTokenWarning": "Ældre API tokens vil blive fjernet i fremtiden. Brug <a href=\"/config/api-keys\">API-nøgler</a> i stedet.",
"MessageAuthenticationOIDCChangesRestart": "Genstart sin server efter du har gemt for at bekræfte OIDC ændringer.",
"MessageAuthenticationSecurityMessage": "Autentificeringen er blevet forbedret af sikkerhedsmæssige årsager. Alle brugere skal logge ind igen.",
"MessageBackupsDescription": "Backups inkluderer brugere, brugerfremskridt, biblioteksvareoplysninger, serverindstillinger og billeder gemt i <code>/metadata/items</code> og <code>/metadata/authors</code>. Backups inkluderer <strong>ikke</strong> nogen filer gemt i dine biblioteksmapper.",
"MessageBackupsLocationEditNote": "Note: Opdatering af backup sti vil ikke fjerne eller modificere eksisterende backups",
"MessageBackupsLocationNoEditNote": "Note: Backup sti er sat igennem miljøvariabel og kan ikke ændres her.",
@@ -722,8 +744,10 @@
"MessageChapterErrorStartGteDuration": "Ugyldig starttid skal være mindre end lydbogens varighed",
"MessageChapterErrorStartLtPrev": "Ugyldig starttid skal være større end eller lig med den foregående kapitels starttid",
"MessageChapterStartIsAfter": "Kapitelstarten er efter slutningen af din lydbog",
"MessageChaptersNotFound": "Kapitler ikke fundet",
"MessageCheckingCron": "Tjekker cron...",
"MessageConfirmCloseFeed": "Er du sikker på, at du vil lukke dette feed?",
"MessageConfirmDeleteApiKey": "Er du sikker på at du vil slette API-nøglen \"{0}\"?",
"MessageConfirmDeleteBackup": "Er du sikker på, at du vil slette backup for {0}?",
"MessageConfirmDeleteDevice": "Er du sikker på at du vil fjerne elæser enhed \"{0}\"?",
"MessageConfirmDeleteFile": "Dette vil slette filen fra dit filsystem. Er du sikker?",
@@ -778,6 +802,7 @@
"MessageForceReScanDescription": "vil scanne alle filer igen som en frisk scanning. Lydfilens ID3-tags, OPF-filer og tekstfiler scannes som nye.",
"MessageImportantNotice": "Vigtig besked!",
"MessageInsertChapterBelow": "Indsæt kapitel nedenfor",
"MessageInvalidAsin": "Ugyldig ASIN",
"MessageItemsSelected": "{0} elementer valgt",
"MessageItemsUpdated": "{0} elementer opdateret",
"MessageJoinUsOn": "Deltag i os på",
@@ -849,6 +874,7 @@
"MessageScheduleRunEveryWeekdayAtTime": "Kør hvert {0} af {1}",
"MessageSearchResultsFor": "Søgeresultater for",
"MessageSelected": "{0} valgt",
"MessageSeriesSequenceCannotContainSpaces": "Serie sekvens kan ikke indeholde mellemrum",
"MessageServerCouldNotBeReached": "Serveren kunne ikke nås",
"MessageSetChaptersFromTracksDescription": "Indstil kapitler ved at bruge hver lydfil som et kapitel og kapiteloverskrift som lydfilnavn",
"MessageShareExpirationWillBe": "Udløb vil være <strong>{0}</strong>",
@@ -910,6 +936,8 @@
"NotificationOnBackupCompletedDescription": "Udløst når backup er færdig",
"NotificationOnBackupFailedDescription": "Udløst når backup fejler",
"NotificationOnEpisodeDownloadedDescription": "Udløst når et podcast afsnit er automatisk downloadet",
"NotificationOnRSSFeedDisabledDescription": "Aktiveret når automatiske episode-downloads er slået fra, på grund af for mange forsøg",
"NotificationOnRSSFeedFailedDescription": "Aktiveret når anmodning om RSS-feedet fejler for en automatisk episode-download",
"NotificationOnTestDescription": "Event for test af notifikationssystemet",
"PlaceholderNewCollection": "Nyt samlingnavn",
"PlaceholderNewFolderPath": "Ny mappes sti",
@@ -954,6 +982,7 @@
"ToastBackupRestoreFailed": "Mislykkedes gendannelse af sikkerhedskopi",
"ToastBackupUploadFailed": "Mislykkedes upload af sikkerhedskopi",
"ToastBackupUploadSuccess": "Sikkerhedskopi uploadet",
"ToastBatchApplyDetailsToItemsSuccess": "Detaljer bekræftet på element",
"ToastBatchDeleteFailed": "Batch slet fejlede",
"ToastBatchDeleteSuccess": "Batch slet succes",
"ToastBatchQuickMatchFailed": "Batch Hurtig Match fejlede!",
@@ -987,6 +1016,7 @@
"ToastEpisodeDownloadQueueClearSuccess": "Afsnit download kø renset",
"ToastEpisodeUpdateSuccess": "{0} afsnit opdateret",
"ToastErrorCannotShare": "Kan ikke dele på denne enhed",
"ToastFailedToCreate": "Oprettelsen mislykkedes",
"ToastFailedToLoadData": "Fejlede at indlæse data",
"ToastFailedToMatch": "Fejlet match",
"ToastFailedToShare": "Fejlet deling",
@@ -1003,11 +1033,11 @@
"ToastItemMarkedAsNotFinishedFailed": "Mislykkedes markering som ikke afsluttet",
"ToastItemMarkedAsNotFinishedSuccess": "Vare markeret som ikke afsluttet",
"ToastItemUpdateSuccess": "Genstand opdateret",
"ToastLibraryCreateFailed": "Mislykkedes oprettelse af bibliotek",
"ToastLibraryCreateFailed": "Oprettelse af bibliotek mislykkedes",
"ToastLibraryCreateSuccess": "Bibliotek \"{0}\" oprettet",
"ToastLibraryDeleteFailed": "Mislykkedes sletning af bibliotek",
"ToastLibraryDeleteFailed": "Sletning af bibliotek mislykkedes",
"ToastLibraryDeleteSuccess": "Bibliotek slettet",
"ToastLibraryScanFailedToStart": "Mislykkedes start af skanning",
"ToastLibraryScanFailedToStart": "Start af skanning mislykkedes",
"ToastLibraryScanStarted": "Biblioteksskanning startet",
"ToastLibraryUpdateSuccess": "Bibliotek \"{0}\" opdateret",
"ToastMatchAllAuthorsFailed": "Fejlede at matche alle forfattere",
@@ -1086,7 +1116,7 @@
"ToastUnlinkOpenIdFailed": "Fejlede i af afkoble bruger fra OpenID",
"ToastUnlinkOpenIdSuccess": "Bruger afkoblet fra OpenID",
"ToastUploaderFilepathExistsError": "Filsti \"{0}\" findes allerede på serveren",
"ToastUploaderItemExistsInSubdirectoryError": "Genstand \"{0}\" benytter en undermappe af upload stien",
"ToastUploaderItemExistsInSubdirectoryError": "Genstand \"{0}\" benytter en undermappe af upload stien.",
"ToastUserDeleteFailed": "Mislykkedes sletning af bruger",
"ToastUserDeleteSuccess": "Bruger slettet",
"ToastUserPasswordChangeSuccess": "Password ændret",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Hinzufügen",
"ButtonAddApiKey": "API-Schlüssel hinzufügen",
"ButtonAddChapters": "Kapitel hinzufügen",
"ButtonAddDevice": "Gerät hinzufügen",
"ButtonAddLibrary": "Bibliothek hinzufügen",
@@ -14,12 +15,13 @@
"ButtonBatchEditPopulateMapDetails": "Kartendetails auffüllen",
"ButtonBrowseForFolder": "Ordnersuche",
"ButtonCancel": "Abbrechen",
"ButtonCancelEncode": "Codierung abbrechen",
"ButtonCancelEncode": "Konvertierung abbrechen",
"ButtonChangeRootPassword": "Hauptpasswort ändern",
"ButtonCheckAndDownloadNewEpisodes": "Überprüfe & lade neue Episoden herunter",
"ButtonChooseAFolder": "Wähle einen Ordner",
"ButtonChooseFiles": "Wähle eine Datei",
"ButtonClearFilter": "Filter löschen",
"ButtonClose": "Schließen",
"ButtonCloseFeed": "Feed schließen",
"ButtonCloseSession": "Offene Sitzung schließen",
"ButtonCollections": "Sammlungen",
@@ -32,7 +34,7 @@
"ButtonEditChapters": "Kapitel bearbeiten",
"ButtonEditPodcast": "Podcast bearbeiten",
"ButtonEnable": "Aktivieren",
"ButtonFireAndFail": "Abfeuern und versagen",
"ButtonFireAndFail": "Abschicken und fehlschlagen",
"ButtonFireOnTest": "Test-Event abfeuern",
"ButtonForceReScan": "Komplett-Scan (alle Medien)",
"ButtonFullPath": "Vollständiger Pfad",
@@ -53,7 +55,7 @@
"ButtonNext": "Vor",
"ButtonNextChapter": "Nächstes Kapitel",
"ButtonNextItemInQueue": "Das nächste Element in der Warteschlange",
"ButtonOk": "Einverstanden",
"ButtonOk": "Ok",
"ButtonOpenFeed": "Feed öffnen",
"ButtonOpenManager": "Manager öffnen",
"ButtonPause": "Pausieren",
@@ -119,6 +121,7 @@
"HeaderAccount": "Konto",
"HeaderAddCustomMetadataProvider": "Benutzerdefinierten Metadatenanbieter hinzufügen",
"HeaderAdvanced": "Erweitert",
"HeaderApiKeys": "API-Schlüssel",
"HeaderAppriseNotificationSettings": "Apprise Benachrichtigungseinstellungen",
"HeaderAudioTracks": "Audiodateien",
"HeaderAudiobookTools": "Hörbuch-Dateiverwaltungswerkzeuge",
@@ -162,6 +165,7 @@
"HeaderMetadataOrderOfPrecedence": "Metadaten Rangfolge",
"HeaderMetadataToEmbed": "Einzubettende Metadaten",
"HeaderNewAccount": "Neues Konto",
"HeaderNewApiKey": "Neuen API-Schlüssel erstellen",
"HeaderNewLibrary": "Neue Bibliothek",
"HeaderNotificationCreate": "Benachrichtigung erstellen",
"HeaderNotificationUpdate": "Benachrichtigung bearbeiten",
@@ -195,6 +199,7 @@
"HeaderSettingsExperimental": "Experimentelle Funktionen",
"HeaderSettingsGeneral": "Allgemein",
"HeaderSettingsScanner": "Scanner",
"HeaderSettingsSecurity": "Sicherheit",
"HeaderSettingsWebClient": "Web-Client",
"HeaderSleepTimer": "Sleep-Timer",
"HeaderStatsLargestItems": "Größte Medien",
@@ -206,6 +211,7 @@
"HeaderTableOfContents": "Inhaltsverzeichnis",
"HeaderTools": "Werkzeuge",
"HeaderUpdateAccount": "Konto aktualisieren",
"HeaderUpdateApiKey": "API-Schlüssel aktualisieren",
"HeaderUpdateAuthor": "Autor aktualisieren",
"HeaderUpdateDetails": "Details aktualisieren",
"HeaderUpdateLibrary": "Bibliothek aktualisieren",
@@ -235,6 +241,10 @@
"LabelAllUsersExcludingGuests": "Alle Benutzer außer Gästen",
"LabelAllUsersIncludingGuests": "Alle Benutzer und Gäste",
"LabelAlreadyInYourLibrary": "Bereits in der Bibliothek",
"LabelApiKeyCreated": "API-Schlüssel \"{0}\" erfolgreich erstellt.",
"LabelApiKeyCreatedDescription": "Speichere den API-Schlüssel an einem sicheren Ort, du wirst ihn später nicht mehr abrufen können.",
"LabelApiKeyUser": "Im Kontext eines Nutzers agieren",
"LabelApiKeyUserDescription": "Dieser API-Schlüssel hat die gleichen Berechtigungen wie der Benutzer, in dessen Namen er erstellt wurde .In den Protokollen wird es aussehen, als ob der Benutzer die Anfrage durchführte.",
"LabelApiToken": "API Schlüssel",
"LabelAppend": "Anhängen",
"LabelAudioBitrate": "Audiobitrate (z. B. 128 kbit/s)",
@@ -284,6 +294,7 @@
"LabelContinueListening": "Weiterhören",
"LabelContinueReading": "Weiterlesen",
"LabelContinueSeries": "Serien fortsetzen",
"LabelCorsAllowed": "Erlaubte CORS Quellen",
"LabelCover": "Titelbild",
"LabelCoverImageURL": "URL des Titelbildes",
"LabelCoverProvider": "Titelbildanbieter",
@@ -346,7 +357,11 @@
"LabelExample": "Beispiel",
"LabelExpandSeries": "Serie ausklappen",
"LabelExpandSubSeries": "Unterserie ausklappen",
"LabelExplicit": "Explizit (Altersbeschränkung)",
"LabelExpired": "Abgelaufen",
"LabelExpiresAt": "Läuft ab am",
"LabelExpiresInSeconds": "Ablauf in (seconds) Sekunden",
"LabelExpiresNever": "Niemals",
"LabelExplicit": "Explizit",
"LabelExplicitChecked": "Explicit (Altersbeschränkung) (angehakt)",
"LabelExplicitUnchecked": "Not Explicit (Altersbeschränkung) (nicht angehakt)",
"LabelExportOPML": "OPML exportieren",
@@ -405,6 +420,7 @@
"LabelLanguages": "Sprachen",
"LabelLastBookAdded": "Zuletzt hinzugefügtes Buch",
"LabelLastBookUpdated": "Zuletzt aktualisiertes Buch",
"LabelLastProgressDate": "Letzter Fortschritt: {0}",
"LabelLastSeen": "Zuletzt gesehen",
"LabelLastTime": "Letztes Mal",
"LabelLastUpdate": "Letzte Aktualisierung",
@@ -417,6 +433,7 @@
"LabelLibraryFilterSublistEmpty": "Keine {0}",
"LabelLibraryItem": "Bibliothekseintrag",
"LabelLibraryName": "Bibliotheksname",
"LabelLibrarySortByProgress": "Fortschritt aktualisiert",
"LabelLimit": "Begrenzung",
"LabelLineSpacing": "Zeilenabstand",
"LabelListenAgain": "Erneut anhören",
@@ -425,6 +442,7 @@
"LabelLogLevelWarn": "Warnungen",
"LabelLookForNewEpisodesAfterDate": "Suche nach neuen Episoden nach diesem Datum",
"LabelLowestPriority": "Niedrigste Priorität",
"LabelMatchConfidence": "Vertrauenswert",
"LabelMatchExistingUsersBy": "Zuordnen existierender Benutzer mit",
"LabelMatchExistingUsersByDescription": "Wird zum Verbinden vorhandener Benutzer verwendet. Sobald die Verbindung hergestellt ist, wird den Benutzern eine eindeutige ID vom SSO-Anbieter zugeordnet",
"LabelMaxEpisodesToDownload": "Max. Anzahl an Episoden zum Herunterladen, 0 für unbegrenzte Episoden.",
@@ -433,7 +451,7 @@
"LabelMaxEpisodesToKeepHelp": "0 setzt keine Begrenzung. Wenn eine neue Episode automatisch heruntergeladen wird, wird die älteste Episode gelöscht, wenn du mehr als X Episoden gespeichert hast. Es wird nur eine Episode pro neuem Download gelöscht.",
"LabelMediaPlayer": "Mediaplayer",
"LabelMediaType": "Medientyp",
"LabelMetaTag": "Meta Schlagwort",
"LabelMetaTag": "Meta Tag",
"LabelMetaTags": "Meta Tags",
"LabelMetadataOrderOfPrecedenceDescription": "Höher priorisierte Quellen für Metadaten überschreiben Metadaten aus Quellen mit niedrigerer Priorität",
"LabelMetadataProvider": "Metadatenanbieter",
@@ -455,6 +473,7 @@
"LabelNewestEpisodes": "Neueste Episoden",
"LabelNextBackupDate": "Nächstes Sicherungsdatum",
"LabelNextScheduledRun": "Nächster planmäßiger Durchlauf",
"LabelNoApiKeys": "Keine API-Schlüssel vorhanden",
"LabelNoCustomMetadataProviders": "Keine benutzerdefinierten Metadata Anbieter",
"LabelNoEpisodesSelected": "Keine Episoden ausgewählt",
"LabelNotFinished": "Nicht beendet",
@@ -514,7 +533,7 @@
"LabelPublishers": "Herausgeber",
"LabelRSSFeedCustomOwnerEmail": "Benutzerdefinierte Eigentümer-E-Mail",
"LabelRSSFeedCustomOwnerName": "Benutzerdefinierter Name des Eigentümers",
"LabelRSSFeedOpen": "RSS Feed offen",
"LabelRSSFeedOpen": "RSS-Feed offen",
"LabelRSSFeedPreventIndexing": "Indizierung verhindern",
"LabelRSSFeedSlug": "RSS-Feed-Schlagwort",
"LabelRSSFeedURL": "RSS-Feed-URL",
@@ -544,6 +563,7 @@
"LabelSelectAll": "Alles auswählen",
"LabelSelectAllEpisodes": "Alle Episoden auswählen",
"LabelSelectEpisodesShowing": "{0} ausgewählte Episoden werden angezeigt",
"LabelSelectUser": "Ausgewählter Benutzer",
"LabelSelectUsers": "Benutzer auswählen",
"LabelSendEbookToDevice": "E-Buch senden an …",
"LabelSequence": "Reihenfolge",
@@ -640,6 +660,7 @@
"LabelTheme": "Farbschema",
"LabelThemeDark": "Dunkel",
"LabelThemeLight": "Hell",
"LabelThemeSepia": "Sepia",
"LabelTimeBase": "Basiszeit",
"LabelTimeDurationXHours": "{0} Stunden",
"LabelTimeDurationXMinutes": "{0} Minuten",
@@ -708,7 +729,9 @@
"MessageAddToPlayerQueue": "Zur Abspielwarteliste hinzufügen",
"MessageAppriseDescription": "Um diese Funktion nutzen zu können, musst du eine Instanz von <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> laufen haben oder eine API verwenden welche dieselbe Anfragen bearbeiten kann. <br />Die Apprise API Url muss der vollständige URL-Pfad sein, an den die Benachrichtigung gesendet werden soll, z.B. wenn Ihre API-Instanz unter <code>http://192.168.1.1:8337</code> läuft, würdest du <code>http://192.168.1.1:8337/notify</code> eingeben.",
"MessageAsinCheck": "Stellen Sie sicher, dass Sie die ASIN aus der richtigen Audible Region verwenden, nicht Amazon.",
"MessageAuthenticationOIDCChangesRestart": "Nach dem Speichern muß der Server neugestartet werden um die OIDC Änderungen zu übernehmen.",
"MessageAuthenticationLegacyTokenWarning": "Alte API tokens werden in Zukunft entfernt. Benutze stattdessen <a href=\"/config/api-keys\">API Keys</a>.",
"MessageAuthenticationOIDCChangesRestart": "Nach dem Speichern muss der Server neugestartet werden um die OIDC Änderungen zu übernehmen.",
"MessageAuthenticationSecurityMessage": "Die Anmeldung wurde abgesichert. Benutzersitzungen werden getrennt, alle Benutzer müssen sich erneut anmelden.",
"MessageBackupsDescription": "In einer Sicherung werden Benutzer, Benutzerfortschritte, Details zu den Bibliotheksobjekten, Servereinstellungen und Bilder welche in <code>/metadata/items</code> & <code>/metadata/authors</code> gespeichert sind gespeichert. Sicherungen enthalten keine Dateien welche in den einzelnen Bibliotheksordnern (Medien-Ordnern) gespeichert sind.",
"MessageBackupsLocationEditNote": "Hinweis: Durch das Aktualisieren des Backup-Speicherorts werden vorhandene Sicherungen nicht verschoben oder geändert",
"MessageBackupsLocationNoEditNote": "Hinweis: Der Sicherungsspeicherort wird über eine Umgebungsvariable festgelegt und kann hier nicht geändert werden.",
@@ -730,6 +753,7 @@
"MessageChaptersNotFound": "Kapitel gefunden nicht",
"MessageCheckingCron": "Überprüfe Cron...",
"MessageConfirmCloseFeed": "Feed wird geschlossen! Bist du dir sicher?",
"MessageConfirmDeleteApiKey": "Möchtest du den API-Schlüssel \"{0}\" wirklich entfernen ?",
"MessageConfirmDeleteBackup": "Sicherung für {0} wird gelöscht! Bist du dir sicher?",
"MessageConfirmDeleteDevice": "Möchtest du das Lesegerät „{0}“ wirklich löschen?",
"MessageConfirmDeleteFile": "Datei wird vom System gelöscht! Bist du dir sicher?",
@@ -757,6 +781,7 @@
"MessageConfirmRemoveAuthor": "Autor \"{0}\" wird enfernt! Bist du dir sicher?",
"MessageConfirmRemoveCollection": "Sammlung \"{0}\" wird entfernt! Bist du dir sicher?",
"MessageConfirmRemoveEpisode": "Episode \"{0}\" wird entfernt! Bist du dir sicher?",
"MessageConfirmRemoveEpisodeNote": "Hinweis: Die Audiodatei wird nicht gelöscht, es sei denn \"Datei dauerhaft löschen\" ist aktiviert",
"MessageConfirmRemoveEpisodes": "{0} Episoden werden entfernt! Bist du dir sicher?",
"MessageConfirmRemoveListeningSessions": "Bist du dir sicher, dass du {0} Hörsitzungen enfernen möchtest?",
"MessageConfirmRemoveMetadataFiles": "Bist du sicher, dass du alle metadata.{0} Dateien in deinen Bibliotheksordnern löschen willst?",
@@ -782,6 +807,7 @@
"MessageFeedURLWillBe": "Feed-URL wird {0} sein",
"MessageFetching": "Wird abgerufen …",
"MessageForceReScanDescription": "Durchsucht alle Dateien erneut, wie bei einem frischen Scan. ID3-Tags von Audiodateien, OPF-Dateien und Textdateien werden neu durchsucht.",
"MessageHeatmapNoListeningSessions": "Keine Hörsitzungen am {0}",
"MessageImportantNotice": "Wichtiger Hinweis!",
"MessageInsertChapterBelow": "Kapitel unten einfügen",
"MessageInvalidAsin": "Ungültige ASIN",
@@ -852,13 +878,13 @@
"MessageResetChaptersConfirm": "Kapitel und vorgenommenen Änderungen werden zurückgesetzt und rückgängig gemacht! Bist du dir sicher?",
"MessageRestoreBackupConfirm": "Bist du dir sicher, dass du die Sicherung wiederherstellen willst, welche am",
"MessageRestoreBackupWarning": "Bei der Wiederherstellung einer Sicherung wird die gesamte Datenbank unter /config und die Titelbilder in /metadata/items und /metadata/authors überschrieben.<br /><br />Bei der Sicherung werden keine Dateien in deinen Bibliotheksordnern verändert. Wenn du die Servereinstellungen aktiviert hast, um Cover und Metadaten in deinen Bibliotheksordnern zu speichern, werden diese nicht gesichert oder überschrieben.<br /><br />Alle Clients, die Ihren Server nutzen, werden automatisch aktualisiert.",
"MessageScheduleLibraryScanNote": "Für die meisten Nutzer wird empfohlen, diese Funktion deaktiviert zu lassen und stattdessen die Ordnerüberwachung aktiviert zu lassen. Die Ordnerüberwachung erkennt automatisch Änderungen in deinen Bibliotheksordnern. Da die Ordnerüberwachung jedoch nicht mit jedem Dateisystem (z.B. NFS) funktioniert, können alternativ hier geplante Bibliotheks-Scans aktiviert werden.",
"MessageScheduleLibraryScanNote": "Für die meisten Anwender wird empfohlen, diese Funktion deaktiviert und die Ordnerüberwachung aktiviert zu lassen. Die Ordnerüberwachung wird Änderungen in den Bibliotheksordnern automatisch erkennen. Die Ordnerüberwachung funktioniert nicht mit allen Dateisystemen (wie NFS), hier kann stattdessen die automatischen Bibliothekssuchen verwendet werden.",
"MessageScheduleRunEveryWeekdayAtTime": "Immer {0} um {1} ausführen",
"MessageSearchResultsFor": "Suchergebnisse für",
"MessageSelected": "{0} ausgewählt",
"MessageSeriesSequenceCannotContainSpaces": "Serie Abfolge kann keine Leerzeichen enthalten",
"MessageServerCouldNotBeReached": "Server kann nicht erreicht werden",
"MessageSetChaptersFromTracksDescription": "Kaitelerstellung basiert auf den existierenden einzelnen Audiodateien. Pro existierende Audiodatei wird 1 Kapitel erstellt, wobei deren Kapitelname aus dem Audiodateinamen extrahiert wird",
"MessageSetChaptersFromTracksDescription": "Kapitelerstellung basiert auf den existierenden einzelnen Audiodateien. Pro existierende Audiodatei wird 1 Kapitel erstellt, wobei deren Kapitelname aus dem Audiodateinamen extrahiert wird",
"MessageShareExpirationWillBe": "Läuft am <strong>{0}</strong> ab",
"MessageShareExpiresIn": "Läuft in {0} ab",
"MessageShareURLWillBe": "Der Freigabe Link wird <strong>{0}</strong> sein",
@@ -918,6 +944,8 @@
"NotificationOnBackupCompletedDescription": "Wird ausgeführt wenn ein Backup erstellt wurde",
"NotificationOnBackupFailedDescription": "Wird ausgeführt wenn ein Backup fehlgeschlagen ist",
"NotificationOnEpisodeDownloadedDescription": "Wird ausgeführt wenn eine Podcast Folge automatisch heruntergeladen wird",
"NotificationOnRSSFeedDisabledDescription": "Wird ausgeführt wenn automatische Downloads von Episoden wegen zu vielen fehlgeschlagenen Versuchen deaktiviert sind",
"NotificationOnRSSFeedFailedDescription": "Wird ausgelöst, wenn die RSS-Feed-Anforderung für einen automatischen Episoden-Download fehlschlägt",
"NotificationOnTestDescription": "Wird ausgeführt wenn das Benachrichtigungssystem getestet wird",
"PlaceholderNewCollection": "Neuer Sammlungsname",
"PlaceholderNewFolderPath": "Neuer Ordnerpfad",
@@ -998,13 +1026,16 @@
"ToastEpisodeDownloadQueueClearSuccess": "Warteschlange für Episoden-Downloads gelöscht",
"ToastEpisodeUpdateSuccess": "{0} Episoden aktualisiert",
"ToastErrorCannotShare": "Das kann nicht nativ auf diesem Gerät freigegeben werden",
"ToastFailedToLoadData": "Daten laden fehlgeschlagen",
"ToastFailedToCreate": "Fehler beim Erzeugen",
"ToastFailedToDelete": "Fehler beim Löschen",
"ToastFailedToLoadData": "Fehler beim laden der Daten",
"ToastFailedToMatch": "Fehler beim Abgleich",
"ToastFailedToShare": "Fehler beim Teilen",
"ToastFailedToUpdate": "Aktualisierung ist fehlgeschlagen",
"ToastInvalidImageUrl": "Ungültiger Bild URL",
"ToastInvalidMaxEpisodesToDownload": "Ungültige Max. Anzahl an Episoden zum Herunterladen",
"ToastInvalidUrl": "Ungültiger URL",
"ToastInvalidUrls": "Eine oder mehrere URLs sind in einem falschen Format",
"ToastItemCoverUpdateSuccess": "Titelbild aktualisiert",
"ToastItemDeletedFailed": "Fehler beim löschen des Artikels",
"ToastItemDeletedSuccess": "Artikel gelöscht",
@@ -1029,6 +1060,7 @@
"ToastMustHaveAtLeastOnePath": "Es muss mindestens ein Pfad angegeben werden",
"ToastNameEmailRequired": "Name und E-Mail sind erforderlich",
"ToastNameRequired": "Name ist erforderlich",
"ToastNewApiKeyUserError": "Bitte wähle einen Benutzer aus (Pflichtfeld)",
"ToastNewEpisodesFound": "{0} neue Episoden gefunden",
"ToastNewUserCreatedFailed": "Fehler beim erstellen des Accounts: \"{ 0}\"",
"ToastNewUserCreatedSuccess": "Neuer Account erstellt",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Add",
"ButtonAddApiKey": "Add API Key",
"ButtonAddChapters": "Add Chapters",
"ButtonAddDevice": "Add Device",
"ButtonAddLibrary": "Add Library",
@@ -20,6 +21,7 @@
"ButtonChooseAFolder": "Choose a folder",
"ButtonChooseFiles": "Choose files",
"ButtonClearFilter": "Clear Filter",
"ButtonClose": "Close",
"ButtonCloseFeed": "Close Feed",
"ButtonCloseSession": "Close Open Session",
"ButtonCollections": "Collections",
@@ -119,6 +121,7 @@
"HeaderAccount": "Account",
"HeaderAddCustomMetadataProvider": "Add Custom Metadata Provider",
"HeaderAdvanced": "Advanced",
"HeaderApiKeys": "API Keys",
"HeaderAppriseNotificationSettings": "Apprise Notification Settings",
"HeaderAudioTracks": "Audio Tracks",
"HeaderAudiobookTools": "Audiobook File Management Tools",
@@ -162,6 +165,7 @@
"HeaderMetadataOrderOfPrecedence": "Metadata order of precedence",
"HeaderMetadataToEmbed": "Metadata to embed",
"HeaderNewAccount": "New Account",
"HeaderNewApiKey": "New API Key",
"HeaderNewLibrary": "New Library",
"HeaderNotificationCreate": "Create Notification",
"HeaderNotificationUpdate": "Update Notification",
@@ -195,6 +199,7 @@
"HeaderSettingsExperimental": "Experimental Features",
"HeaderSettingsGeneral": "General",
"HeaderSettingsScanner": "Scanner",
"HeaderSettingsSecurity": "Security",
"HeaderSettingsWebClient": "Web Client",
"HeaderSleepTimer": "Sleep Timer",
"HeaderStatsLargestItems": "Largest Items",
@@ -206,6 +211,7 @@
"HeaderTableOfContents": "Table of Contents",
"HeaderTools": "Tools",
"HeaderUpdateAccount": "Update Account",
"HeaderUpdateApiKey": "Update API Key",
"HeaderUpdateAuthor": "Update Author",
"HeaderUpdateDetails": "Update Details",
"HeaderUpdateLibrary": "Update Library",
@@ -235,6 +241,10 @@
"LabelAllUsersExcludingGuests": "All users excluding guests",
"LabelAllUsersIncludingGuests": "All users including guests",
"LabelAlreadyInYourLibrary": "Already in your library",
"LabelApiKeyCreated": "API Key \"{0}\" created successfully.",
"LabelApiKeyCreatedDescription": "Make sure to copy the API key now as you will not be able to see this again.",
"LabelApiKeyUser": "Act on behalf of user",
"LabelApiKeyUserDescription": "This API key will have the same permissions as the user it is acting on behalf of. This will appear the same in logs as if the user was making the request.",
"LabelApiToken": "API Token",
"LabelAppend": "Append",
"LabelAudioBitrate": "Audio Bitrate (e.g. 128k)",
@@ -284,6 +294,7 @@
"LabelContinueListening": "Continue Listening",
"LabelContinueReading": "Continue Reading",
"LabelContinueSeries": "Continue Series",
"LabelCorsAllowed": "Allowed CORS Origins",
"LabelCover": "Cover",
"LabelCoverImageURL": "Cover Image URL",
"LabelCoverProvider": "Cover Provider",
@@ -346,6 +357,10 @@
"LabelExample": "Example",
"LabelExpandSeries": "Expand Series",
"LabelExpandSubSeries": "Expand Sub Series",
"LabelExpired": "Expired",
"LabelExpiresAt": "Expires At",
"LabelExpiresInSeconds": "Expires in (seconds)",
"LabelExpiresNever": "Never",
"LabelExplicit": "Explicit",
"LabelExplicitChecked": "Explicit (checked)",
"LabelExplicitUnchecked": "Not Explicit (unchecked)",
@@ -405,6 +420,7 @@
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Last Book Added",
"LabelLastBookUpdated": "Last Book Updated",
"LabelLastProgressDate": "Last progress: {0}",
"LabelLastSeen": "Last Seen",
"LabelLastTime": "Last Time",
"LabelLastUpdate": "Last Update",
@@ -417,6 +433,7 @@
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Library Item",
"LabelLibraryName": "Library Name",
"LabelLibrarySortByProgress": "Progress Updated",
"LabelLimit": "Limit",
"LabelLineSpacing": "Line spacing",
"LabelListenAgain": "Listen Again",
@@ -425,6 +442,7 @@
"LabelLogLevelWarn": "Warn",
"LabelLookForNewEpisodesAfterDate": "Look for new episodes after this date",
"LabelLowestPriority": "Lowest Priority",
"LabelMatchConfidence": "Confidence",
"LabelMatchExistingUsersBy": "Match existing users by",
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
"LabelMaxEpisodesToDownload": "Max # of episodes to download. Use 0 for unlimited.",
@@ -455,6 +473,7 @@
"LabelNewestEpisodes": "Newest Episodes",
"LabelNextBackupDate": "Next backup date",
"LabelNextScheduledRun": "Next scheduled run",
"LabelNoApiKeys": "No API keys",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "No episodes selected",
"LabelNotFinished": "Not Finished",
@@ -544,6 +563,7 @@
"LabelSelectAll": "Select all",
"LabelSelectAllEpisodes": "Select all episodes",
"LabelSelectEpisodesShowing": "Select {0} episodes showing",
"LabelSelectUser": "Select user",
"LabelSelectUsers": "Select users",
"LabelSendEbookToDevice": "Send Ebook to...",
"LabelSequence": "Sequence",
@@ -640,6 +660,7 @@
"LabelTheme": "Theme",
"LabelThemeDark": "Dark",
"LabelThemeLight": "Light",
"LabelThemeSepia": "Sepia",
"LabelTimeBase": "Time Base",
"LabelTimeDurationXHours": "{0} hours",
"LabelTimeDurationXMinutes": "{0} minutes",
@@ -708,7 +729,9 @@
"MessageAddToPlayerQueue": "Add to player queue",
"MessageAppriseDescription": "To use this feature you will need to have an instance of <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> running or an api that will handle those same requests. <br />The Apprise API Url should be the full URL path to send the notification, e.g., if your API instance is served at <code>http://192.168.1.1:8337</code> then you would put <code>http://192.168.1.1:8337/notify</code>.",
"MessageAsinCheck": "Ensure you are using the ASIN from the correct Audible region, not Amazon.",
"MessageAuthenticationLegacyTokenWarning": "Legacy API tokens will be removed in the future. Use <a href=\"/config/api-keys\">API Keys</a> instead.",
"MessageAuthenticationOIDCChangesRestart": "Restart your server after saving to apply OIDC changes.",
"MessageAuthenticationSecurityMessage": "Authentication has been improved for security. All users are required to re-login.",
"MessageBackupsDescription": "Backups include users, user progress, library item details, server settings, and images stored in <code>/metadata/items</code> & <code>/metadata/authors</code>. Backups <strong>do not</strong> include any files stored in your library folders.",
"MessageBackupsLocationEditNote": "Note: Updating the backup location will not move or modify existing backups",
"MessageBackupsLocationNoEditNote": "Note: The backup location is set through an environment variable and cannot be changed here.",
@@ -730,6 +753,7 @@
"MessageChaptersNotFound": "Chapters not found",
"MessageCheckingCron": "Checking cron...",
"MessageConfirmCloseFeed": "Are you sure you want to close this feed?",
"MessageConfirmDeleteApiKey": "Are you sure you want to delete API key \"{0}\"?",
"MessageConfirmDeleteBackup": "Are you sure you want to delete backup for {0}?",
"MessageConfirmDeleteDevice": "Are you sure you want to delete e-reader device \"{0}\"?",
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
@@ -757,6 +781,7 @@
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Are you sure you want to remove collection \"{0}\"?",
"MessageConfirmRemoveEpisode": "Are you sure you want to remove episode \"{0}\"?",
"MessageConfirmRemoveEpisodeNote": "Note: This does not delete the audio file unless toggling \"Hard delete file\"",
"MessageConfirmRemoveEpisodes": "Are you sure you want to remove {0} episodes?",
"MessageConfirmRemoveListeningSessions": "Are you sure you want to remove {0} listening sessions?",
"MessageConfirmRemoveMetadataFiles": "Are you sure you want to remove all metadata.{0} files in your library item folders?",
@@ -782,6 +807,8 @@
"MessageFeedURLWillBe": "Feed URL will be {0}",
"MessageFetching": "Fetching...",
"MessageForceReScanDescription": "will scan all files again like a fresh scan. Audio file ID3 tags, OPF files, and text files will be scanned as new.",
"MessageHeatmapListeningTimeTooltip": "<strong>{0} listening</strong> on {1}",
"MessageHeatmapNoListeningSessions": "No listening sessions on {0}",
"MessageImportantNotice": "Important Notice!",
"MessageInsertChapterBelow": "Insert chapter below",
"MessageInvalidAsin": "Invalid ASIN",
@@ -918,6 +945,8 @@
"NotificationOnBackupCompletedDescription": "Triggered when a backup is completed",
"NotificationOnBackupFailedDescription": "Triggered when a backup fails",
"NotificationOnEpisodeDownloadedDescription": "Triggered when a podcast episode is auto-downloaded",
"NotificationOnRSSFeedDisabledDescription": "Triggered when automatic episode downloads are disabled due to too many failed attempts",
"NotificationOnRSSFeedFailedDescription": "Triggered when the RSS feed request fails for an automatic episode download",
"NotificationOnTestDescription": "Event for testing the notification system",
"PlaceholderNewCollection": "New collection name",
"PlaceholderNewFolderPath": "New folder path",
@@ -998,6 +1027,8 @@
"ToastEpisodeDownloadQueueClearSuccess": "Episode download queue cleared",
"ToastEpisodeUpdateSuccess": "{0} episodes updated",
"ToastErrorCannotShare": "Cannot share natively on this device",
"ToastFailedToCreate": "Failed to create",
"ToastFailedToDelete": "Failed to delete",
"ToastFailedToLoadData": "Failed to load data",
"ToastFailedToMatch": "Failed to match",
"ToastFailedToShare": "Failed to share",
@@ -1005,6 +1036,7 @@
"ToastInvalidImageUrl": "Invalid image URL",
"ToastInvalidMaxEpisodesToDownload": "Invalid max episodes to download",
"ToastInvalidUrl": "Invalid URL",
"ToastInvalidUrls": "One or more URLs are invalid",
"ToastItemCoverUpdateSuccess": "Item cover updated",
"ToastItemDeletedFailed": "Failed to delete item",
"ToastItemDeletedSuccess": "Deleted item",
@@ -1029,6 +1061,7 @@
"ToastMustHaveAtLeastOnePath": "Must have at least one path",
"ToastNameEmailRequired": "Name and email are required",
"ToastNameRequired": "Name is required",
"ToastNewApiKeyUserError": "Must select a user",
"ToastNewEpisodesFound": "{0} new episodes found",
"ToastNewUserCreatedFailed": "Failed to create account: \"{0}\"",
"ToastNewUserCreatedSuccess": "New account created",

View File

@@ -11,7 +11,7 @@
"ButtonAuthors": "Autorid",
"ButtonBack": "Tagasi",
"ButtonBrowseForFolder": "Sirvi kausta",
"ButtonCancel": "Tühista",
"ButtonCancel": "Katkesta",
"ButtonCancelEncode": "Tühista kodeerimine",
"ButtonChangeRootPassword": "Muuda põhiparooli",
"ButtonCheckAndDownloadNewEpisodes": "Kontrolli ja laadi alla uued episoodid",
@@ -20,9 +20,9 @@
"ButtonClearFilter": "Tühista filter",
"ButtonCloseFeed": "Sulge voog",
"ButtonCloseSession": "Sulge avatud sessioon",
"ButtonCollections": "Kogud",
"ButtonCollections": "Kollektsioonid",
"ButtonConfigureScanner": "Konfigureeri skanner",
"ButtonCreate": "Loo",
"ButtonCreate": "Loo uus",
"ButtonCreateBackup": "Loo varundus",
"ButtonDelete": "Kustuta",
"ButtonDownloadQueue": "Järjekord",
@@ -37,7 +37,7 @@
"ButtonIssues": "Probleemid",
"ButtonJumpBackward": "Hüppa tagasi",
"ButtonJumpForward": "Hüppa edasi",
"ButtonLatest": "Uusim",
"ButtonLatest": "Viimased",
"ButtonLibrary": "Raamatukogu",
"ButtonLogout": "Logi välja",
"ButtonLookup": "Otsi",
@@ -52,11 +52,11 @@
"ButtonOk": "Ok",
"ButtonOpenFeed": "Ava voog",
"ButtonOpenManager": "Ava haldur",
"ButtonPause": "Peata",
"ButtonPlay": "Mängi",
"ButtonPause": "Paus",
"ButtonPlay": "Play",
"ButtonPlayAll": "Mängi kõik",
"ButtonPlaying": "Mängib",
"ButtonPlaylists": "Esitusloendid",
"ButtonPlaylists": "Playlist",
"ButtonPrevious": "Eelmine",
"ButtonPreviousChapter": "Eelmine peatükk",
"ButtonPurgeAllCache": "Tühjenda kogu vahemälu",
@@ -69,7 +69,7 @@
"ButtonReadLess": "Loe vähem",
"ButtonReadMore": "Loe rohkem",
"ButtonRefresh": "Värskenda",
"ButtonRemove": "Eemalda",
"ButtonRemove": "Kustuta",
"ButtonRemoveAll": "Eemalda kõik",
"ButtonRemoveAllLibraryItems": "Eemalda kõik raamatukogu esemed",
"ButtonRemoveFromContinueListening": "Eemalda jätkake kuulamisest",
@@ -120,12 +120,12 @@
"HeaderCustomMetadataProviders": "Kohandatud metaandmete pakkujad",
"HeaderDetails": "Detailid",
"HeaderDownloadQueue": "Allalaadimise järjekord",
"HeaderEbookFiles": "E-raamatute failid",
"HeaderEbookFiles": "E-raamatu failid",
"HeaderEmail": "E-post",
"HeaderEmailSettings": "E-posti seaded",
"HeaderEpisodes": "Episoodid",
"HeaderEreaderDevices": "E-lugerite seadmed",
"HeaderEreaderSettings": "E-lugerite seadistused",
"HeaderEreaderSettings": "E-lugeja sätted",
"HeaderFiles": "Failid",
"HeaderFindChapters": "Leia peatükid",
"HeaderIgnoredFiles": "Ignoreeritud failid",
@@ -155,8 +155,8 @@
"HeaderPasswordAuthentication": "Parooli autentimine",
"HeaderPermissions": "Õigused",
"HeaderPlayerQueue": "Mängija järjekord",
"HeaderPlaylist": "Mänguloend",
"HeaderPlaylistItems": "Mänguloendi esemed",
"HeaderPlaylist": "Playlist",
"HeaderPlaylistItems": "Playlisti esemed",
"HeaderPodcastsToAdd": "Lisatavad podcastid",
"HeaderPreviewCover": "Eelvaate kaas",
"HeaderRSSFeedGeneral": "RSS-i üksikasjad",
@@ -174,7 +174,7 @@
"HeaderSettingsExperimental": "Katsetusfunktsioonid",
"HeaderSettingsGeneral": "Üldised",
"HeaderSettingsScanner": "Skanner",
"HeaderSleepTimer": "Uinaku taimer",
"HeaderSleepTimer": "Unetaimer",
"HeaderStatsLargestItems": "Suurimad esemed",
"HeaderStatsLongestItems": "Kõige pikemad esemed (tunnid)",
"HeaderStatsMinutesListeningChart": "Kuulamise minutid (viimased 7 päeva)",
@@ -197,9 +197,10 @@
"LabelActivity": "Tegevus",
"LabelAddToCollection": "Lisa kogusse",
"LabelAddToCollectionBatch": "Lisa {0} raamatut kogusse",
"LabelAddToPlaylist": "Lisa mänguloendisse",
"LabelAddToPlaylist": "Lisa playlisti",
"LabelAddToPlaylistBatch": "Lisa {0} eset mänguloendisse",
"LabelAddedAt": "Lisatud",
"LabelAddedDate": "Lisatud {0}",
"LabelAdminUsersOnly": "Ainult administraatorid",
"LabelAll": "Kõik",
"LabelAllUsers": "Kõik kasutajad",
@@ -208,10 +209,10 @@
"LabelAlreadyInYourLibrary": "Juba teie raamatukogus",
"LabelAppend": "Lisa",
"LabelAuthor": "Autor",
"LabelAuthorFirstLast": "Autor (Eesnimi Perekonnanimi)",
"LabelAuthorLastFirst": "Autor (Perekonnanimi, Eesnimi)",
"LabelAuthorFirstLast": "Autor (eesnimi perekonnanimi)",
"LabelAuthorLastFirst": "Autor (perekonnanimi, eesnimi)",
"LabelAuthors": "Autorid",
"LabelAutoDownloadEpisodes": "Automaatne episoodide allalaadimine",
"LabelAutoDownloadEpisodes": "Episoodide automaatne allalaadimine",
"LabelAutoFetchMetadata": "Automaatne metaandmete hankimine",
"LabelAutoFetchMetadataHelp": "Toob tiitli, autori ja seeria metaandmed üleslaadimise hõlbustamiseks. Lisametaandmed võivad pärast üleslaadimist vajada vastavust.",
"LabelAutoLaunch": "Automaatne käivitamine",
@@ -265,7 +266,7 @@
"LabelDiscover": "Avasta",
"LabelDownload": "Lae alla",
"LabelDownloadNEpisodes": "Lae alla {0} episoodi",
"LabelDuration": "Kestus",
"LabelDuration": "Kestvus",
"LabelDurationFound": "Leitud kestus:",
"LabelEbook": "E-raamat",
"LabelEbooks": "E-raamatud",
@@ -278,6 +279,7 @@
"LabelEmbeddedCover": "Manustatud kaas",
"LabelEnable": "Luba",
"LabelEnd": "Lõpp",
"LabelEndOfChapter": "Peatükki lõpp",
"LabelEpisode": "Episood",
"LabelEpisodeTitle": "Episoodi pealkiri",
"LabelEpisodeType": "Episoodi tüüp",
@@ -288,13 +290,14 @@
"LabelFile": "Fail",
"LabelFileBirthtime": "Faili sünniaeg",
"LabelFileModified": "Faili muudetud",
"LabelFilename": "Failinimi",
"LabelFilename": "Faili nimi",
"LabelFilterByUser": "Filtri alusel kasutaja järgi",
"LabelFindEpisodes": "Otsi episoodid",
"LabelFinished": "Lõpetatud",
"LabelFolder": "Kaust",
"LabelFolders": "Kataloogid",
"LabelFontBold": "Paks",
"LabelFontBoldness": "Fondi paksus",
"LabelFontFamily": "Fondi pere",
"LabelFontItalic": "Kaldkiri",
"LabelFontScale": "Fondi suurus",
@@ -303,7 +306,7 @@
"LabelGenre": "Žanr",
"LabelGenres": "Žanrid",
"LabelHardDeleteFile": "Faili lõplik kustutamine",
"LabelHasEbook": "On e-raamat",
"LabelHasEbook": "E-raamat olemas",
"LabelHasSupplementaryEbook": "On täiendav e-raamat",
"LabelHighestPriority": "Kõrgeim prioriteet",
"LabelHour": "Tund",
@@ -311,7 +314,7 @@
"LabelImageURLFromTheWeb": "Pildi URL veebist",
"LabelInProgress": "Pooleli",
"LabelIncludeInTracklist": "Kaasa jälgimisloendis",
"LabelIncomplete": "Puudulik",
"LabelIncomplete": "Lõpetamata",
"LabelInterval": "Intervall",
"LabelIntervalCustomDailyWeekly": "Kohandatud päevane/nädalane",
"LabelIntervalEvery12Hours": "Iga 12 tunni tagant",
@@ -365,12 +368,12 @@
"LabelNarrators": "Jutustajad",
"LabelNew": "Uus",
"LabelNewPassword": "Uus parool",
"LabelNewestAuthors": "Uusimad autorid",
"LabelNewestEpisodes": "Uusimad episoodid",
"LabelNewestAuthors": "Uuemad autorid",
"LabelNewestEpisodes": "Uuemad episoodid",
"LabelNextBackupDate": "Järgmine varukoopia kuupäev",
"LabelNextScheduledRun": "Järgmine ajakava järgmine",
"LabelNoEpisodesSelected": "Episoodid pole valitud",
"LabelNotFinished": "Ei ole lõpetatud",
"LabelNotFinished": "Lõpetamata",
"LabelNotStarted": "Pole alustatud",
"LabelNotes": "Märkused",
"LabelNotificationAppriseURL": "Apprise URL-id",
@@ -383,7 +386,7 @@
"LabelNotificationsMaxQueueSize": "Teavituste sündmuste maksimaalne järjekorra suurus",
"LabelNotificationsMaxQueueSizeHelp": "Sündmused on piiratud 1 sekundiga. Sündmusi ignoreeritakse, kui järjekord on maksimumsuuruses. See takistab teavituste rämpsposti.",
"LabelNumberOfBooks": "Raamatute arv",
"LabelNumberOfEpisodes": "Episoodide arv",
"LabelNumberOfEpisodes": "# episoode",
"LabelOpenRSSFeed": "Ava RSS voog",
"LabelOverwrite": "Kirjuta üle",
"LabelPassword": "Parool",
@@ -398,16 +401,18 @@
"LabelPhotoPathURL": "Foto tee/URL",
"LabelPlayMethod": "Esitusmeetod",
"LabelPlaylists": "Mänguloendid",
"LabelPodcast": "Podcast",
"LabelPodcastSearchRegion": "Podcasti otsingu piirkond",
"LabelPodcastType": "Podcasti tüüp",
"LabelPodcasts": "Podcastid",
"LabelPrefixesToIgnore": "Eiramiseks eesliited (tõstutundetu)",
"LabelPreventIndexing": "Vältige oma voogu indekseerimist iTunes'i ja Google podcasti kataloogides",
"LabelPrimaryEbook": "Esmane e-raamat",
"LabelProgress": "Edenemine",
"LabelProgress": "Progress",
"LabelProvider": "Pakkuja",
"LabelPubDate": "Avaldamise kuupäev",
"LabelPublishYear": "Aasta avaldamine",
"LabelPubDate": "Publitseerimise kuupäev",
"LabelPublishYear": "Publitseerimise aasta",
"LabelPublishedDate": "Publitseeritud {0}",
"LabelPublisher": "Kirjastaja",
"LabelRSSFeedCustomOwnerEmail": "Kohandatud omaniku e-post",
"LabelRSSFeedCustomOwnerName": "Kohandatud omaniku nimi",
@@ -415,7 +420,8 @@
"LabelRSSFeedPreventIndexing": "Vältige indekseerimist",
"LabelRSSFeedSlug": "RSS voog Slug",
"LabelRSSFeedURL": "RSS voog URL",
"LabelRead": "Lugenud",
"LabelRandomly": "Juhuslikus järjekorras",
"LabelRead": "Loetud läbi",
"LabelReadAgain": "Loe uuesti",
"LabelReadEbookWithoutProgress": "Lugege e-raamatut ilma edenemist säilitamata",
"LabelRecentSeries": "Hiljutised seeriad",
@@ -469,9 +475,9 @@
"LabelSettingsStoreMetadataWithItem": "Salvesta metaandmed üksusega",
"LabelSettingsStoreMetadataWithItemHelp": "Vaikimisi salvestatakse metaandmed /metadata/items kausta. Selle seadistuse lubamine salvestab metaandmed teie raamatukogu üksuse kaustadesse",
"LabelSettingsTimeFormat": "Kellaaja vorming",
"LabelShowAll": "Näita kõiki",
"LabelShowAll": "Näita kõik",
"LabelSize": "Suurus",
"LabelSleepTimer": "Uinaku taimer",
"LabelSleepTimer": "Unetaimer",
"LabelStart": "Alusta",
"LabelStartTime": "Alustamise aeg",
"LabelStarted": "Alustatud",
@@ -480,13 +486,13 @@
"LabelStatsAuthors": "Autorid",
"LabelStatsBestDay": "Parim päev",
"LabelStatsDailyAverage": "Päevane keskmine",
"LabelStatsDays": "Päevad",
"LabelStatsDays": "Päevi",
"LabelStatsDaysListened": "Kuulatud päevad",
"LabelStatsHours": "Tunnid",
"LabelStatsInARow": "järjest",
"LabelStatsItemsFinished": "Lõpetatud üksused",
"LabelStatsItemsInLibrary": "Üksused raamatukogus",
"LabelStatsMinutes": "minutit",
"LabelStatsMinutes": "minuteid",
"LabelStatsMinutesListening": "Kuulamise minutid",
"LabelStatsOverallDays": "Kokku päevad",
"LabelStatsOverallHours": "Kokku tunnid",
@@ -502,7 +508,7 @@
"LabelTextEditorNumberedList": "Numberloend",
"LabelTextEditorUnlink": "Eemalda link",
"LabelTheme": "Teema",
"LabelThemeDark": "Tume",
"LabelThemeDark": "Pime",
"LabelThemeLight": "Hele",
"LabelTimeBase": "Aja alus",
"LabelTimeListened": "Kuulatud aeg",
@@ -527,7 +533,7 @@
"LabelType": "Tüüp",
"LabelUnabridged": "Täismahus",
"LabelUndo": "Võta tagasi",
"LabelUnknown": "Tundmatu",
"LabelUnknown": "Teadmata",
"LabelUpdateCover": "Uuenda kaant",
"LabelUpdateCoverHelp": "Luba üle kirjutamine olemasolevate kaante jaoks valitud raamatutele, kui leitakse sobivus",
"LabelUpdateDetails": "Uuenda üksikasju",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Ajouter",
"ButtonAddApiKey": "Ajouter une clé API",
"ButtonAddChapters": "Ajouter des chapitres",
"ButtonAddDevice": "Ajouter un appareil",
"ButtonAddLibrary": "Ajouter une bibliothèque",
@@ -20,6 +21,7 @@
"ButtonChooseAFolder": "Sélectionner un dossier",
"ButtonChooseFiles": "Sélectionner des fichiers",
"ButtonClearFilter": "Effacer le filtre",
"ButtonClose": "Fermer",
"ButtonCloseFeed": "Fermer le flux",
"ButtonCloseSession": "Fermer la session",
"ButtonCollections": "Collections",
@@ -119,6 +121,7 @@
"HeaderAccount": "Compte",
"HeaderAddCustomMetadataProvider": "Ajouter un fournisseur de métadonnées personnalisé",
"HeaderAdvanced": "Avancé",
"HeaderApiKeys": "Clés API",
"HeaderAppriseNotificationSettings": "Configuration des notifications Apprise",
"HeaderAudioTracks": "Pistes audio",
"HeaderAudiobookTools": "Outils de gestion de fichiers de livres audio",
@@ -162,6 +165,7 @@
"HeaderMetadataOrderOfPrecedence": "Ordre de priorité des métadonnées",
"HeaderMetadataToEmbed": "Métadonnées à intégrer",
"HeaderNewAccount": "Nouveau compte",
"HeaderNewApiKey": "Nouvelle clé API",
"HeaderNewLibrary": "Nouvelle bibliothèque",
"HeaderNotificationCreate": "Créer une notification",
"HeaderNotificationUpdate": "Mise à jour de la notification",
@@ -177,6 +181,7 @@
"HeaderPlaylist": "Liste de lecture",
"HeaderPlaylistItems": "Éléments de la liste de lecture",
"HeaderPodcastsToAdd": "Podcasts à ajouter",
"HeaderPresets": "Préréglages",
"HeaderPreviewCover": "Prévisualiser la couverture",
"HeaderRSSFeedGeneral": "Détails du flux RSS",
"HeaderRSSFeedIsOpen": "Le flux RSS est actif",
@@ -194,6 +199,7 @@
"HeaderSettingsExperimental": "Fonctionnalités expérimentales",
"HeaderSettingsGeneral": "Général",
"HeaderSettingsScanner": "Analyseur",
"HeaderSettingsSecurity": "Sécurité",
"HeaderSettingsWebClient": "Client Web",
"HeaderSleepTimer": "Minuterie",
"HeaderStatsLargestItems": "Éléments les plus grands",
@@ -201,10 +207,11 @@
"HeaderStatsMinutesListeningChart": "Minutes découte (7 derniers jours)",
"HeaderStatsRecentSessions": "Sessions récentes",
"HeaderStatsTop10Authors": "Top 10 Auteurs",
"HeaderStatsTop5Genres": "Top 5 Genres",
"HeaderStatsTop5Genres": "Top 5 des genres",
"HeaderTableOfContents": "Table des matières",
"HeaderTools": "Outils",
"HeaderUpdateAccount": "Mettre à jour le compte",
"HeaderUpdateApiKey": "Mettre à jour la clé API",
"HeaderUpdateAuthor": "Mettre à jour lauteur",
"HeaderUpdateDetails": "Mettre à jour les détails",
"HeaderUpdateLibrary": "Mettre à jour la bibliothèque",
@@ -234,6 +241,10 @@
"LabelAllUsersExcludingGuests": "Tous les utilisateurs à lexception des invités",
"LabelAllUsersIncludingGuests": "Tous les utilisateurs, y compris les invités",
"LabelAlreadyInYourLibrary": "Déjà dans la bibliothèque",
"LabelApiKeyCreated": "La clé API « {0} » a été créée avec succès.",
"LabelApiKeyCreatedDescription": "Assurez-vous de copier la clé API maintenant car vous ne pourrez plus la voir.",
"LabelApiKeyUser": "Agir au nom de lutilisateur",
"LabelApiKeyUserDescription": "Cette clé API disposera des mêmes autorisations que lutilisateur pour lequel elle agit. Elle apparaîtra dans les journaux comme si cétait lutilisateur qui effectuait la requête.",
"LabelApiToken": "Token API",
"LabelAppend": "Ajouter",
"LabelAudioBitrate": "Débit audio (par exemple 128k)",
@@ -283,6 +294,7 @@
"LabelContinueListening": "Continuer l'écoute",
"LabelContinueReading": "Continuer la lecture",
"LabelContinueSeries": "Continuer les séries",
"LabelCorsAllowed": "Origines autorisées pour les requêtes CORS",
"LabelCover": "Couverture",
"LabelCoverImageURL": "URL vers limage de couverture",
"LabelCoverProvider": "Source des couvertures",
@@ -345,7 +357,11 @@
"LabelExample": "Exemple",
"LabelExpandSeries": "Développer la série",
"LabelExpandSubSeries": "Développer les sous-séries",
"LabelExplicit": "Restriction",
"LabelExpired": "Expiré",
"LabelExpiresAt": "Expire à",
"LabelExpiresInSeconds": "Expire dans (secondes)",
"LabelExpiresNever": "Jamais",
"LabelExplicit": "Contenu explicite",
"LabelExplicitChecked": "Explicite (vérifié)",
"LabelExplicitUnchecked": "Non explicite (non vérifié)",
"LabelExportOPML": "Exporter OPML",
@@ -404,6 +420,7 @@
"LabelLanguages": "Langues",
"LabelLastBookAdded": "Dernier livre ajouté",
"LabelLastBookUpdated": "Dernier livre mis à jour",
"LabelLastProgressDate": "Dernière position : {0}",
"LabelLastSeen": "Vu dernièrement",
"LabelLastTime": "Progression",
"LabelLastUpdate": "Dernière mise à jour",
@@ -416,14 +433,16 @@
"LabelLibraryFilterSublistEmpty": "Aucun {0}",
"LabelLibraryItem": "Élément de bibliothèque",
"LabelLibraryName": "Nom de la bibliothèque",
"LabelLibrarySortByProgress": "Progression mise à jour",
"LabelLimit": "Limite",
"LabelLineSpacing": "Espacement des lignes",
"LabelListenAgain": "Écouter à nouveau",
"LabelLogLevelDebug": "Débogage",
"LabelLogLevelInfo": "Info",
"LabelLogLevelWarn": "Warn",
"LabelLogLevelWarn": "Attention",
"LabelLookForNewEpisodesAfterDate": "Rechercher les nouveaux épisodes après cette date",
"LabelLowestPriority": "Priorité la plus basse",
"LabelMatchConfidence": "Confiance",
"LabelMatchExistingUsersBy": "Correspondance avec les utilisateurs existants",
"LabelMatchExistingUsersByDescription": "Utilisé pour connecter les utilisateurs existants. Une fois connectés, les utilisateurs seront associés à un identifiant unique provenant de votre fournisseur SSO",
"LabelMaxEpisodesToDownload": "Nombre maximum dépisodes à télécharger. 0 pour illimité.",
@@ -454,6 +473,7 @@
"LabelNewestEpisodes": "Épisodes récents",
"LabelNextBackupDate": "Date de la prochaine sauvegarde",
"LabelNextScheduledRun": "Prochain lancement prévu",
"LabelNoApiKeys": "Aucune clé API",
"LabelNoCustomMetadataProviders": "Aucun fournisseurs de métadonnées personnalisés",
"LabelNoEpisodesSelected": "Aucun épisode sélectionné",
"LabelNotFinished": "Non terminé",
@@ -530,6 +550,7 @@
"LabelReleaseDate": "Date de parution",
"LabelRemoveAllMetadataAbs": "Supprimer tous les fichiers metadata.abs",
"LabelRemoveAllMetadataJson": "Supprimer tous les fichiers metadata.json",
"LabelRemoveAudibleBranding": "Supprimer lintro et la fin Audible des chapitres",
"LabelRemoveCover": "Supprimer la couverture",
"LabelRemoveMetadataFile": "Supprimer les fichiers de métadonnées dans les dossiers des éléments de la bibliothèque",
"LabelRemoveMetadataFileHelp": "Supprimer tous les fichiers metadata.json et metadata.abs de vos dossiers {0}.",
@@ -542,6 +563,7 @@
"LabelSelectAll": "Tout sélectionner",
"LabelSelectAllEpisodes": "Sélectionner tous les épisodes",
"LabelSelectEpisodesShowing": "Sélectionner {0} épisode(s) en cours",
"LabelSelectUser": "Sélectionner lutilisateur",
"LabelSelectUsers": "Sélectionner les utilisateurs",
"LabelSendEbookToDevice": "Envoyer le livre numérique à…",
"LabelSequence": "Séquence",
@@ -597,7 +619,7 @@
"LabelShareOpen": "Ouvrir le partage",
"LabelShareURL": "Partager lURL",
"LabelShowAll": "Tout afficher",
"LabelShowSeconds": "Afficher les seondes",
"LabelShowSeconds": "Afficher les secondes",
"LabelShowSubtitles": "Afficher les sous-titres",
"LabelSize": "Taille",
"LabelSleepTimer": "Minuterie de mise en veille",
@@ -638,6 +660,7 @@
"LabelTheme": "Thème",
"LabelThemeDark": "Sombre",
"LabelThemeLight": "Clair",
"LabelThemeSepia": "Sépia",
"LabelTimeBase": "Base de temps",
"LabelTimeDurationXHours": "{0} heures",
"LabelTimeDurationXMinutes": "{0} minutes",
@@ -705,6 +728,10 @@
"LabelYourProgress": "Votre progression",
"MessageAddToPlayerQueue": "Ajouter en file dattente",
"MessageAppriseDescription": "Nécessite une instance d<a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">API Apprise</a> pour utiliser cette fonctionnalité ou une api qui prend en charge les mêmes requêtes.<br />LURL de lAPI Apprise doit comprendre le chemin complet pour envoyer la notification. Par exemple, si votre instance écoute sur <code>http://192.168.1.1:8337</code> alors vous devez mettre <code>http://192.168.1.1:8337/notify</code>.",
"MessageAsinCheck": "Assurez-vous dutiliser lASIN de la bonne région Audible, et non dAmazon.",
"MessageAuthenticationLegacyTokenWarning": "Les jetons dAPI hérités seront supprimés à lavenir. Utilisez plutôt les <a href=\"/config/api-keys\">clés API</a>.",
"MessageAuthenticationOIDCChangesRestart": "Redémarrez votre serveur après avoir enregistré pour appliquer les modifications OIDC.",
"MessageAuthenticationSecurityMessage": "Lauthentification a été améliorée pour plus de sécurité. Tous les utilisateurs doivent se reconnecter.",
"MessageBackupsDescription": "Les sauvegardes incluent les utilisateurs, la progression des utilisateurs, les détails des éléments de la bibliothèque, les paramètres du serveur et les images stockées dans <code>/metadata/items</code> & <code>/metadata/authors</code>. Les sauvegardes <strong>nincluent pas</strong> les fichiers stockés dans les dossiers de votre bibliothèque.",
"MessageBackupsLocationEditNote": "Remarque: Mettre à jour l'emplacement de sauvegarde ne déplacera pas ou ne modifiera pas les sauvegardes existantes",
"MessageBackupsLocationNoEditNote": "Remarque: lemplacement de sauvegarde est défini via une variable denvironnement et ne peut pas être modifié ici.",
@@ -723,8 +750,10 @@
"MessageChapterErrorStartGteDuration": "Horodatage invalide car il doit débuter avant la fin du livre",
"MessageChapterErrorStartLtPrev": "Horodatage invalide car il doit débuter au moins après le précédent chapitre",
"MessageChapterStartIsAfter": "Le premier chapitre est situé au début de votre livre audio",
"MessageChaptersNotFound": "Chapitres non trouvés",
"MessageCheckingCron": "Vérification du cron…",
"MessageConfirmCloseFeed": "Êtes-vous sûr·e de vouloir fermer ce flux?",
"MessageConfirmDeleteApiKey": "Êtes-vous sûr de vouloir supprimer la clé API « {0} » ?",
"MessageConfirmDeleteBackup": "Êtes-vous sûr·e de vouloir supprimer la sauvegarde de « {0} » ?",
"MessageConfirmDeleteDevice": "Êtes-vous sûr·e de vouloir supprimer la liseuse « {0} » ?",
"MessageConfirmDeleteFile": "Cela supprimera le fichier de votre système de fichiers. Êtes-vous sûr ?",
@@ -752,6 +781,7 @@
"MessageConfirmRemoveAuthor": "Êtes-vous sûr·e de vouloir supprimer lauteur « {0} » ?",
"MessageConfirmRemoveCollection": "Êtes-vous sûr·e de vouloir supprimer la collection « {0} » ?",
"MessageConfirmRemoveEpisode": "Êtes-vous sûr·e de vouloir supprimer lépisode « {0} » ?",
"MessageConfirmRemoveEpisodeNote": "Remarque : cela ne supprime pas le fichier audio, sauf si vous activez « Supprimer définitivement le fichier »",
"MessageConfirmRemoveEpisodes": "Êtes-vous sûr·e de vouloir supprimer {0} épisodes?",
"MessageConfirmRemoveListeningSessions": "Êtes-vous sûr·e de vouloir supprimer {0} sessions découte?",
"MessageConfirmRemoveMetadataFiles": "Êtes-vous sûr·e de vouloir supprimer tous les fichiers « metatadata.{0} » des dossiers déléments de votre bibliothèque?",
@@ -777,8 +807,11 @@
"MessageFeedURLWillBe": "LURL du flux sera {0}",
"MessageFetching": "Récupération…",
"MessageForceReScanDescription": "analysera de nouveau tous les fichiers. Les étiquettes ID3 des fichiers audio, les fichiers OPF et les fichiers texte seront analysés comme sils étaient nouveaux.",
"MessageHeatmapListeningTimeTooltip": "<strong>{0} À lécoute</strong> sur {1}",
"MessageHeatmapNoListeningSessions": "Aucune session en cours sur {0}",
"MessageImportantNotice": "Information importante !",
"MessageInsertChapterBelow": "Insérer le chapitre ci-dessous",
"MessageInvalidAsin": "ASIN invalide",
"MessageItemsSelected": "{0} éléments sélectionnés",
"MessageItemsUpdated": "{0} éléments mis à jour",
"MessageJoinUsOn": "Rejoignez-nous sur",
@@ -812,7 +845,7 @@
"MessageNoItems": "Aucun élément",
"MessageNoItemsFound": "Aucun élément trouvé",
"MessageNoListeningSessions": "Aucune session découte en cours",
"MessageNoLogs": "Aucun journaux",
"MessageNoLogs": "Aucun journal",
"MessageNoMediaProgress": "Aucun média en cours",
"MessageNoNotifications": "Aucune notification",
"MessageNoPodcastFeed": "Podcast invalide : pas de flux",
@@ -850,6 +883,7 @@
"MessageScheduleRunEveryWeekdayAtTime": "Exécuté tous les {0} à {1}",
"MessageSearchResultsFor": "Résultats de recherche pour",
"MessageSelected": "{0} sélectionnés",
"MessageSeriesSequenceCannotContainSpaces": "La séquence de séries ne peut pas contenir despaces",
"MessageServerCouldNotBeReached": "Serveur inaccessible",
"MessageSetChaptersFromTracksDescription": "Positionne un chapitre par fichier audio, avec le titre du fichier comme titre de chapitre",
"MessageShareExpirationWillBe": "Expire le <strong>{0}</strong>",
@@ -911,12 +945,14 @@
"NotificationOnBackupCompletedDescription": "Déclenché lorsquune sauvegarde est terminée",
"NotificationOnBackupFailedDescription": "Déclenché lorsqu'une sauvegarde échoue",
"NotificationOnEpisodeDownloadedDescription": "Déclenché lorsquun épisode de podcast est téléchargé automatiquement",
"NotificationOnRSSFeedDisabledDescription": "Déclenché lorsque les téléchargements automatiques dépisodes sont désactivés en raison dun trop grand nombre de tentatives infructueuses",
"NotificationOnRSSFeedFailedDescription": "Déclenché lorsque la demande de flux RSS échoue pour un téléchargement automatique dépisode",
"NotificationOnTestDescription": "Événement pour tester le système de notification",
"PlaceholderNewCollection": "Nom de la nouvelle collection",
"PlaceholderNewFolderPath": "Nouveau chemin de dossier",
"PlaceholderNewPlaylist": "Nouveau nom de liste de lecture",
"PlaceholderSearch": "Recherche…",
"PlaceholderSearchEpisode": "Recherche dépisode…",
"PlaceholderSearchEpisode": "Rechercher un épisode…",
"StatsAuthorsAdded": "auteurs ajoutés",
"StatsBooksAdded": "livres ajoutés",
"StatsBooksAdditional": "Les ajouts comprennent…",
@@ -968,6 +1004,8 @@
"ToastCachePurgeFailed": "Échec de la purge du cache",
"ToastCachePurgeSuccess": "Cache purgé avec succès",
"ToastChaptersHaveErrors": "Les chapitres contiennent des erreurs",
"ToastChaptersInvalidShiftAmountLast": "Durée de décalage non valide. Lheure de début du dernier chapitre pourrait dépasser la durée de ce livre audio.",
"ToastChaptersInvalidShiftAmountStart": "Durée de décalage non valide. Le premier chapitre aurait une longueur nulle ou négative et serait écrasé par le second. Augmentez la durée de début du second chapitre.",
"ToastChaptersMustHaveTitles": "Les chapitre doivent avoir un titre",
"ToastChaptersRemoved": "Chapitres supprimés",
"ToastChaptersUpdated": "Chapitres mis à jour",
@@ -989,6 +1027,8 @@
"ToastEpisodeDownloadQueueClearSuccess": "File dattente de téléchargement des épisodes effacée",
"ToastEpisodeUpdateSuccess": "{0} épisodes mis à jour",
"ToastErrorCannotShare": "Impossible de partager nativement sur cet appareil",
"ToastFailedToCreate": "Échec de la création",
"ToastFailedToDelete": "Échec de la suppression",
"ToastFailedToLoadData": "Échec du chargement des données",
"ToastFailedToMatch": "Échec de la correspondance",
"ToastFailedToShare": "Échec du partage",
@@ -996,6 +1036,7 @@
"ToastInvalidImageUrl": "URL de l'image invalide",
"ToastInvalidMaxEpisodesToDownload": "Nombre maximum dépisodes à télécharger non valide",
"ToastInvalidUrl": "URL invalide",
"ToastInvalidUrls": "Une ou plusieurs URL sont invalides",
"ToastItemCoverUpdateSuccess": "Couverture mise à jour",
"ToastItemDeletedFailed": "La suppression de l'élément à échouée",
"ToastItemDeletedSuccess": "Élément supprimé",
@@ -1020,6 +1061,7 @@
"ToastMustHaveAtLeastOnePath": "Doit avoir au moins un chemin",
"ToastNameEmailRequired": "Le nom et le courriel sont requis",
"ToastNameRequired": "Le nom est requis",
"ToastNewApiKeyUserError": "Vous devez sélectionner un utilisateur",
"ToastNewEpisodesFound": "{0} nouveaux épisodes trouvés",
"ToastNewUserCreatedFailed": "La création du compte à échouée: « {0} »",
"ToastNewUserCreatedSuccess": "Nouveau compte créé",

View File

@@ -9,6 +9,9 @@
"ButtonApply": "લાગુ કરો",
"ButtonApplyChapters": "પ્રકરણો લાગુ કરો",
"ButtonAuthors": "લેખકો",
"ButtonBack": "પાછા",
"ButtonBatchEditPopulateFromExisting": "હાલની માહિતીમાંથી ભરો",
"ButtonBatchEditPopulateMapDetails": "નકશાની વિગત ભરો",
"ButtonBrowseForFolder": "ફોલ્ડર માટે જુઓ",
"ButtonCancel": "રદ કરો",
"ButtonCancelEncode": "એન્કોડ રદ કરો",
@@ -27,11 +30,14 @@
"ButtonEdit": "સંપાદિત કરો",
"ButtonEditChapters": "પ્રકરણો સંપાદિત કરો",
"ButtonEditPodcast": "પોડકાસ્ટ સંપાદિત કરો",
"ButtonEnable": "સક્રિય કરો",
"ButtonForceReScan": "બળપૂર્વક ફરીથી સ્કેન કરો",
"ButtonFullPath": "સંપૂર્ણ પથ",
"ButtonHide": "છુપાવો",
"ButtonHome": "ઘર",
"ButtonIssues": "સમસ્યાઓ",
"ButtonJumpBackward": "પાછળ જાવો",
"ButtonJumpForward": "આગળ જાવો",
"ButtonLatest": "નવીનતમ",
"ButtonLibrary": "પુસ્તકાલય",
"ButtonLogout": "લૉગ આઉટ",
@@ -41,19 +47,32 @@
"ButtonMatchAllAuthors": "બધા મેળ ખાતા લેખકો શોધો",
"ButtonMatchBooks": "મેળ ખાતી પુસ્તકો શોધો",
"ButtonNevermind": "કંઈ વાંધો નહીં",
"ButtonNext": "આગળ જાઓ",
"ButtonNextChapter": "આગળનું અધ્યાય",
"ButtonNextItemInQueue": "કતારમાં આવતું આગળનું અધ્યાય",
"ButtonOk": "ઓકે",
"ButtonOpenFeed": "ફીડ ખોલો",
"ButtonOpenManager": "મેનેજર ખોલો",
"ButtonPause": "વિરામ",
"ButtonPlay": "ચલાવો",
"ButtonPlayAll": "બધું ચલાવો",
"ButtonPlaying": "ચલાવી રહ્યું છે",
"ButtonPlaylists": "પ્લેલિસ્ટ",
"ButtonPrevious": "પાછળનું",
"ButtonPreviousChapter": "પાછળનું અધ્યાય",
"ButtonProbeAudioFile": "ઑડિયો ફાઇલ તપાસો",
"ButtonPurgeAllCache": "બધો Cache કાઢી નાખો",
"ButtonPurgeItemsCache": "વસ્તુઓનો Cache કાઢી નાખો",
"ButtonQueueAddItem": "કતારમાં ઉમેરો",
"ButtonQueueRemoveItem": "કતારથી કાઢી નાખો",
"ButtonQuickEmbed": "ઝડપથી સમાવેશ કરો",
"ButtonQuickEmbedMetadata": "ઝડપથી મેટાડેટા સમાવવો",
"ButtonQuickMatch": "ઝડપી મેળ ખવડાવો",
"ButtonReScan": "ફરીથી સ્કેન કરો",
"ButtonRead": "વાંચો",
"ButtonReadLess": "ઓછું વાંચો",
"ButtonReadMore": "વધારે વાંચો",
"ButtonRefresh": "તાજું કરો",
"ButtonRemove": "કાઢી નાખો",
"ButtonRemoveAll": "બધું કાઢી નાખો",
"ButtonRemoveAllLibraryItems": "બધું પુસ્તકાલય વસ્તુઓ કાઢી નાખો",
@@ -68,16 +87,21 @@
"ButtonSaveTracklist": "ટ્રેક યાદી સાચવો",
"ButtonScan": "સ્કેન કરો",
"ButtonScanLibrary": "પુસ્તકાલય સ્કેન કરો",
"ButtonScrollLeft": "ડાબે",
"ButtonScrollRight": "જમણે",
"ButtonSearch": "શોધો",
"ButtonSelectFolderPath": "ફોલ્ડર પથ પસંદ કરો",
"ButtonSeries": "સિરીઝ",
"ButtonSetChaptersFromTracks": "ટ્રેક્સથી પ્રકરણો સેટ કરો",
"ButtonShare": "શેર કરો",
"ButtonShiftTimes": "સમય શિફ્ટ કરો",
"ButtonShow": "બતાવો",
"ButtonStartM4BEncode": "M4B એન્કોડ શરૂ કરો",
"ButtonStartMetadataEmbed": "મેટાડેટા એમ્બેડ શરૂ કરો",
"ButtonStats": "આંકડા",
"ButtonSubmit": "સબમિટ કરો",
"ButtonTest": "પરખ કરો",
"ButtonUnlinkOpenId": "OpenID દૂર કરો",
"ButtonUpload": "અપલોડ કરો",
"ButtonUploadBackup": "બેકઅપ અપલોડ કરો",
"ButtonUploadCover": "કવર અપલોડ કરો",
@@ -86,11 +110,16 @@
"ButtonUserEdit": "વપરાશકર્તા {0} સંપાદિત કરો",
"ButtonViewAll": "બધું જુઓ",
"ButtonYes": "હા",
"ErrorUploadFetchMetadataAPI": "મેટાડેટા મેળવવામાં તકલીફ આવી",
"ErrorUploadFetchMetadataNoResults": "મેટાડેટા મેળવી શક્યા નહીં કૃપા કરીને શીર્ષક અને/અથવા લેખકનું નામ અપડેટ કરવાનો પ્રયત્ન કરો",
"ErrorUploadLacksTitle": "શીર્ષક હોવું આવશ્યક છે",
"HeaderAccount": "એકાઉન્ટ",
"HeaderAddCustomMetadataProvider": "કસ્ટમ મેટાડેટા પ્રોવાઇડર ઉમેરો",
"HeaderAdvanced": "અડ્વાન્સડ",
"HeaderAppriseNotificationSettings": "Apprise સૂચના સેટિંગ્સ",
"HeaderAudioTracks": "ઓડિયો ટ્રેક્સ",
"HeaderAudiobookTools": "ઓડિયોબુક ફાઇલ વ્યવસ્થાપન ટૂલ્સ",
"HeaderAuthentication": "પ્રમાણીકરણ",
"HeaderBackups": "બેકઅપ્સ",
"HeaderChangePassword": "પાસવર્ડ બદલો",
"HeaderChapters": "પ્રકરણો",
@@ -99,6 +128,7 @@
"HeaderCollectionItems": "સંગ્રહ વસ્તુઓ",
"HeaderCover": "આવરણ",
"HeaderCurrentDownloads": "વર્તમાન ડાઉનલોડ્સ",
"HeaderCustomMetadataProviders": "કસ્ટમ મેટાડેટા પ્રોવાઇડર્સ",
"HeaderDetails": "વિગતો",
"HeaderDownloadQueue": "ડાઉનલોડ કતાર",
"HeaderEbookFiles": "ઇબુક ફાઇલો",
@@ -129,6 +159,7 @@
"HeaderMetadataToEmbed": "એમ્બેડ કરવા માટે મેટાડેટા",
"HeaderNewAccount": "નવું એકાઉન્ટ",
"HeaderNewLibrary": "નવી પુસ્તકાલય",
"HeaderNotificationCreate": "સૂચના બનાવો",
"HeaderNotifications": "સૂચનાઓ",
"HeaderOpenRSSFeed": "RSS ફીડ ખોલો",
"HeaderOtherFiles": "અન્ય ફાઇલો",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "הוסף",
"ButtonAddApiKey": "הוסף מפתח ממשק תכנות (API)",
"ButtonAddChapters": "הוסף פרקים",
"ButtonAddDevice": "הוסף התקן",
"ButtonAddLibrary": "הוסף ספרייה",
@@ -10,6 +11,8 @@
"ButtonApplyChapters": "החל פרקים",
"ButtonAuthors": "סופרים",
"ButtonBack": "חזור",
"ButtonBatchEditPopulateFromExisting": "מלא משדות קיימים",
"ButtonBatchEditPopulateMapDetails": "מלא פרטי מפה",
"ButtonBrowseForFolder": "עיין בתיקייה",
"ButtonCancel": "ביטול",
"ButtonCancelEncode": "בטל קידוד",
@@ -18,6 +21,7 @@
"ButtonChooseAFolder": "בחר תיקייה",
"ButtonChooseFiles": "בחר קבצים",
"ButtonClearFilter": "נקה סינון",
"ButtonClose": "סגור",
"ButtonCloseFeed": "סגור ערוץ",
"ButtonCloseSession": "סגור סשן פתוח",
"ButtonCollections": "אוספים",
@@ -29,7 +33,9 @@
"ButtonEdit": "ערוך",
"ButtonEditChapters": "ערוך פרקים",
"ButtonEditPodcast": "ערוך פודקאסט",
"ButtonEnable": "הפעל",
"ButtonEnable": "אפשר",
"ButtonFireAndFail": "שלח בכישלון",
"ButtonFireOnTest": "שלח באירוע בדיקה",
"ButtonForceReScan": "סרוק מחדש בכוח",
"ButtonFullPath": "נתיב מלא",
"ButtonHide": "הסתר",
@@ -37,7 +43,7 @@
"ButtonIssues": "תקלות",
"ButtonJumpBackward": "דלג אחורה",
"ButtonJumpForward": "דלג קדימה",
"ButtonLatest": "חדש ביותר",
"ButtonLatest": "אחרון",
"ButtonLibrary": "ספרייה",
"ButtonLogout": "התנתק",
"ButtonLookup": "חפש",
@@ -70,7 +76,7 @@
"ButtonReScan": "סרוק מחדש",
"ButtonRead": "קרא",
"ButtonReadLess": "קרא פחות",
"ButtonReadMore": "קרא יותר",
"ButtonReadMore": "קרא עוד",
"ButtonRefresh": "רענן",
"ButtonRemove": "הסר",
"ButtonRemoveAll": "הסר הכל",
@@ -86,7 +92,9 @@
"ButtonSaveTracklist": "שמור רשימת רצועות",
"ButtonScan": "סרוק",
"ButtonScanLibrary": "סרוק ספרייה",
"ButtonSearch": "חפש",
"ButtonScrollLeft": "גלול שמאלה",
"ButtonScrollRight": "גלול ימינה",
"ButtonSearch": "חיפוש",
"ButtonSelectFolderPath": "בחר נתיב לתיקייה",
"ButtonSeries": "סדרה",
"ButtonSetChaptersFromTracks": "קבע פרקים לפי הרצועות",
@@ -96,7 +104,7 @@
"ButtonStartM4BEncode": "התחל קידוד M4B",
"ButtonStartMetadataEmbed": "התחל הטמעת מטא-נתונים",
"ButtonStats": "סטטיסטיקות",
"ButtonSubmit": "שלח",
"ButtonSubmit": "שליחה",
"ButtonTest": "בדיקה",
"ButtonUnlinkOpenId": "נתק OpenID",
"ButtonUpload": "העלה",
@@ -122,26 +130,26 @@
"HeaderChapters": "פרקים",
"HeaderChooseAFolder": "בחר תיקייה",
"HeaderCollection": "אוסף",
"HeaderCollectionItems": "פריטי אוסף",
"HeaderCollectionItems": "פרטי אוסף",
"HeaderCover": "כריכה",
"HeaderCurrentDownloads": "הורדות נוכחיות",
"HeaderCustomMessageOnLogin": "הודעה מותאמת אישית בהתחברות",
"HeaderCustomMetadataProviders": "ספקי מטא-נתונים מותאמים אישית",
"HeaderDetails": "פרטים",
"HeaderDownloadQueue": "תור הורדה",
"HeaderEbookFiles": "קבצי ספר אלקטרוני",
"HeaderEbookFiles": "קבצי Ebook",
"HeaderEmail": "אימייל",
"HeaderEmailSettings": "הגדרות אימייל",
"HeaderEpisodes": "פרקים",
"HeaderEreaderDevices": "התקני קריאה דיגיטליים",
"HeaderEreaderSettings": "הגדרות התקני קריאה דיגיטליים",
"HeaderEreaderSettings": "הגדרות קורא אלקטרוני",
"HeaderFiles": "קבצים",
"HeaderFindChapters": "מצא פרקים",
"HeaderIgnoredFiles": "קבצים שנתעלמו",
"HeaderItemFiles": "קבצי פריט",
"HeaderItemMetadataUtils": "כלי מטא-נתונים",
"HeaderLastListeningSession": "הפעלת האזנה אחרונה",
"HeaderLatestEpisodes": "הפרקים העדכניים ביותר",
"HeaderLatestEpisodes": "פרקים אחרונים",
"HeaderLibraries": "ספריות",
"HeaderLibraryFiles": "קבצי ספרייה",
"HeaderLibraryStats": "סטטיסטיקות ספרייה",
@@ -171,8 +179,9 @@
"HeaderPlaylist": "רשימת השמעה",
"HeaderPlaylistItems": "פריטי רשימת השמעה",
"HeaderPodcastsToAdd": "פודקאסטים להוספה",
"HeaderPresets": "קביעות מוגדרות מראש",
"HeaderPreviewCover": "תצוגה מקדימה של כריכה",
"HeaderRSSFeedGeneral": "פרטי ערוץ RSS",
"HeaderRSSFeedGeneral": "פרטי RSS",
"HeaderRSSFeedIsOpen": "ערוץ RSS פתוח",
"HeaderRSSFeeds": "ערוצי RSS",
"HeaderRemoveEpisode": "הסר פרק",
@@ -188,14 +197,15 @@
"HeaderSettingsExperimental": "תכונות ניסיוניות",
"HeaderSettingsGeneral": "כללי",
"HeaderSettingsScanner": "סורק",
"HeaderSettingsWebClient": "מערך",
"HeaderSleepTimer": "טיימר שינה",
"HeaderStatsLargestItems": "הפריטים הגדולים ביותר",
"HeaderStatsLongestItems": "הפריטים הארוכים ביותר (בשעות)",
"HeaderStatsMinutesListeningChart": "דקות האזנה (בימים האחרונים)",
"HeaderStatsRecentSessions": פעלות אחרונות",
"HeaderStatsMinutesListeningChart": "דקות האזנה (7 ימים אחרונים)",
"HeaderStatsRecentSessions": אזנות אחרונות",
"HeaderStatsTop10Authors": "10 היוצרים המובילים",
"HeaderStatsTop5Genres": "הז'אנרים המובילים 5",
"HeaderTableOfContents": "תוכן העניינים",
"HeaderTableOfContents": "תוכן עניינים",
"HeaderTools": "כלים",
"HeaderUpdateAccount": "עדכן חשבון",
"HeaderUpdateAuthor": "עדכן יוצר",
@@ -212,15 +222,17 @@
"LabelAccountTypeAdmin": "מנהל",
"LabelAccountTypeGuest": "אורח",
"LabelAccountTypeUser": "משתמש",
"LabelActivities": "פעילויות",
"LabelActivity": "פעילות",
"LabelAddToCollection": "הוסף לאוסף",
"LabelAddToCollectionBatch": "הוסף {0} ספרים לאוסף",
"LabelAddToPlaylist": "הוסף לרשימת השמעה",
"LabelAddToPlaylistBatch": "הוסף {0} פריטים לרשימת השמעה",
"LabelAddedAt": "נוסף בתאריך",
"LabelAddedAt": "נוסף ב-",
"LabelAddedDate": "נוסף ב-{0}",
"LabelAdminUsersOnly": "רק מנהלים",
"LabelAll": "הכל",
"LabelAllEpisodesDownloaded": "כל הפרקים הורדו",
"LabelAllUsers": "כל המשתמשים",
"LabelAllUsersExcludingGuests": "כל המשתמשים, ללא אורחים",
"LabelAllUsersIncludingGuests": "כל המשתמשים כולל אורחים",
@@ -230,10 +242,10 @@
"LabelAudioBitrate": "קצב סיביות (לדוגמא 128k)",
"LabelAudioChannels": "ערוצי קול (1 או 2)",
"LabelAudioCodec": "קידוד קול",
"LabelAuthor": "יוצר",
"LabelAuthorFirstLast": "יוצר (שם פרטי שם משפחה)",
"LabelAuthorLastFirst": "יוצר (שם משפחה, שם פרטי)",
"LabelAuthors": "יוצרים",
"LabelAuthor": "סופר",
"LabelAuthorFirstLast": "סופר (שם, משפחה)",
"LabelAuthorLastFirst": "סופר (משפחה, שם)",
"LabelAuthors": "סופרים",
"LabelAutoDownloadEpisodes": "הורד פרקים באופן אוטומטי",
"LabelAutoFetchMetadata": "חפש והורד מטא-נתונים באופן אוטומטי",
"LabelAutoFetchMetadataHelp": "מחפש ומוריד מטא-נתונים לשדות כותרת, יוצר וסדרה כדי לשפר את תהליך ההעלאה. ייתכן שיהיה צורך להתאים מטא-נתונים נוסף לאחר ההעלאה.",
@@ -242,36 +254,48 @@
"LabelAutoRegister": "הרשמה אוטומטית",
"LabelAutoRegisterDescription": "יצירת משתמשים חדשים אוטומטית לאחר התחברות",
"LabelBackToUser": "חזרה למשתמש",
"LabelBackupAudioFiles": "גיבוי קבצי שמע",
"LabelBackupLocation": "מיקום גיבוי",
"LabelBackupsEnableAutomaticBackups": "הפעל גיבויים אוטומטיים",
"LabelBackupsEnableAutomaticBackups": "גיבויים אוטומטיים",
"LabelBackupsEnableAutomaticBackupsHelp": "גיבויים שמורים ב /metadata/backups",
"LabelBackupsMaxBackupSize": "גודל הגיבוי המרבי (בג'יגה-בייט)",
"LabelBackupsMaxBackupSize": "גודל הגיבוי המרבי (בג'יגה-בייט) (0 - ללא הגבלה)",
"LabelBackupsMaxBackupSizeHelp": "כהגנה על עצמך מפני תצורה שגויה, הגיבויים ייכשלו אם הם יעברו את הגודל שהוגדר.",
"LabelBackupsNumberToKeep": "מספר הגיבויים לשמירה",
"LabelBackupsNumberToKeepHelp": "רק גיבוי אחד יוסר בכל פעם, לכן אם יש לך כבר יותר מגיבוי אחד יש להסיר אותם באופן ידני.",
"LabelBitrate": "קצב סיביות",
"LabelBonus": "בונוס",
"LabelBooks": "ספרים",
"LabelButtonText": "טקסט לחצן",
"LabelByAuthor": "על ידי {0}",
"LabelChangePassword": "שינוי סיסמה",
"LabelChannels": "ערוצים",
"LabelChapterCount": "{0} פרקים",
"LabelChapterTitle": "כותרת הפרק",
"LabelChapters": "פרקים",
"LabelChaptersFound": "פרקים שנמצאו",
"LabelClickForMoreInfo": "לחץ למידע נוסף",
"LabelClickToUseCurrentValue": "לחץ לשימוש בערך הנוכחי",
"LabelClosePlayer": "סגור נגן",
"LabelCollapseSeries": "צמצום סדרה",
"LabelCodec": "Coded",
"LabelCollapseSeries": "הסתר סדרה",
"LabelCollapseSubSeries": "הסתר תת סדרה",
"LabelCollection": "אוסף",
"LabelCollections": "אוספים",
"LabelComplete": "מלא",
"LabelComplete": "הושלם",
"LabelConfirmPassword": "אישור סיסמה",
"LabelContinueListening": "המשך האזנה",
"LabelContinueReading": "המשך קריאה",
"LabelContinueSeries": "המשך סדרה",
"LabelCover": "כריכה",
"LabelCoverImageURL": "כתובת התמונה ברשת",
"LabelCoverProvider": "ספק כריכה",
"LabelCreatedAt": "נוצר בתאריך",
"LabelCronExpression": "ביטוי cron",
"LabelCurrent": "נוכחי",
"LabelCurrently": "כעת:",
"LabelCustomCronExpression": "ביטוי cron מותאם אישית:",
"LabelDatetime": "Datetime",
"LabelDays": "ימים",
"LabelDeleteFromFileSystemCheckbox": "מחיקה מהמערכת הקבצים (הסר סימון למחיקה רק ממסד הנתונים)",
"LabelDescription": "תיאור",
"LabelDeselectAll": "הסר בחירת כל הפריטים",
@@ -282,51 +306,83 @@
"LabelDiscFromFilename": "דיסק משם הקובץ",
"LabelDiscFromMetadata": "דיסק מהמטא-נתונים",
"LabelDiscover": "גלה",
"LabelDownload": "הורד",
"LabelDownload": "הורדה",
"LabelDownloadNEpisodes": "הורד {0} פרקים",
"LabelDownloadable": "ניתן להורדה",
"LabelDuration": "משך",
"LabelDurationComparisonExactMatch": "(התאמה מדוייקת)",
"LabelDurationComparisonLonger": "({0} ארוך יותר)",
"LabelDurationComparisonShorter": "({0} קצר יותר)",
"LabelDurationFound": "משך נמצא:",
"LabelEbook": "ספר אלקטרוני",
"LabelEbooks": "ספרים אלקטרוניים",
"LabelEdit": "עריכה",
"LabelEmail": "דואר אלקטרוני",
"LabelEmailSettingsFromAddress": "מאת",
"LabelEmailSettingsRejectUnauthorized": "דחה תעודות לא מאושרות",
"LabelEmailSettingsRejectUnauthorizedHelp": "השבתת אימות תעודת SSL עלולה לחשוף את החיבור שלך לסיכוני אבטחה, כגון התקפות \"אדם באמצע\". השבת אפשרות זו רק אם אתה מבין את ההשלכות ובוטח בשרת הדואר שאליו אתה מתחבר.",
"LabelEmailSettingsSecure": "מאובטח",
"LabelEmailSettingsSecureHelp": "אם מופעל, החיבור ישתמש ב-TLS בעת ההתחברות לשרת. אם לא, אז TLS יהיה בשימוש אם השרת תומך בהרחבת STARTTLS. ברוב המקרים מומלץ להפעיל את הגדרה זו אם אתה מתחבר לפורט 465. לפורט 587 או 25, השאר כבוי. (from nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "כתובת לבדיקה",
"LabelEmbeddedCover": "כריכה מוטמעת",
"LabelEnable": "הפעל",
"LabelEnd": "סיום",
"LabelEnable": "אפשר",
"LabelEncodingBackupLocation": "גיבוי של קבצי אודיו מקוריים יישמר ב:",
"LabelEncodingChaptersNotEmbedded": "פרקים אינם מוטבעים בספרי אודיו מרובי רצועות.",
"LabelEncodingClearItemCache": "הקפד לנקות מטמון פריטים מעת לעת.",
"LabelEncodingFinishedM4B": "קובץ M4B סופי יישמר בתיקייה ה-audiobook ב:",
"LabelEncodingInfoEmbedded": "מטה דאטה יוטמע ברצועות השמע בתוך תיקיית ה-audiobook.",
"LabelEncodingStartedNavigation": "לאחר שהמשימה תתחיל אפשר לנווט לדף אחר.",
"LabelEncodingTimeWarning": "קידוד יכול להימשך עד 30 דקות.",
"LabelEncodingWarningAdvancedSettings": "אזהרה: אל תעדכן את ההגדרות האלה אלא אם כן אתה מכיר את אפשרויות קידוד ffmpeg.",
"LabelEncodingWatcherDisabled": "אם ה-watcher כבוי, יש לסרוק את הספר מחדש לאחר מכן.",
"LabelEnd": "סוף",
"LabelEndOfChapter": "סוף הפרק",
"LabelEpisode": "פרק",
"LabelEpisodeNotLinkedToRssFeed": "פרק לא מקושר לערוץ RSS",
"LabelEpisodeNumber": "פרק #{0}",
"LabelEpisodeTitle": "כותרת הפרק",
"LabelEpisodeType": "סוג הפרק",
"LabelEpisodeUrlFromRssFeed": "קישור פרק מערוץ RSS",
"LabelEpisodes": "פרקים",
"LabelEpisodic": "ארעי",
"LabelExample": "דוגמה",
"LabelExpandSeries": "הרחב סדרה",
"LabelExpandSubSeries": "הרחב תת סדרה",
"LabelExplicit": "בוטה",
"LabelExplicitChecked": "בוטה (מסומן)",
"LabelExplicitUnchecked": "לא בוטה (לא מסומן)",
"LabelExportOPML": "ייצוא OPML",
"LabelFeedURL": "כתובת ערוץ",
"LabelFetchingMetadata": "מושך מטא-נתונים",
"LabelFile": "קובץ",
"LabelFileBirthtime": "זמן יצירת הקובץ",
"LabelFileModified": "הקובץ שונה",
"LabelFilename": "שם הקובץ",
"LabelFileBornDate": "נוצר {0}",
"LabelFileModified": "קובץ נערך",
"LabelFileModifiedDate": "שונה {0}",
"LabelFilename": "שם קובץ",
"LabelFilterByUser": "סינון לפי משתמש",
"LabelFindEpisodes": "מצא פרקים",
"LabelFinished": "הושלם",
"LabelFolder": "תיקייה",
"LabelFolders": "תיקיות",
"LabelFontBold": "מודגש",
"LabelFontBoldness": "עובי פונט",
"LabelFontFamily": "משפחת הפונטים",
"LabelFontItalic": "נטוי",
"LabelFontScale": "קנה מידה של הפונט",
"LabelFontScale": "גודל פונט",
"LabelFontStrikethrough": "קו חוצה",
"LabelFormat": "תבנית",
"LabelGenre": "ז'אנר",
"LabelGenres": "ז'אנרים",
"LabelFull": "מלא",
"LabelGenre": "סגנון",
"LabelGenres": "סגנונות",
"LabelHardDeleteFile": "מחיקה חזקה של הקובץ",
"LabelHasEbook": "ספר אלקטרוני קיים",
"LabelHasSupplementaryEbook": "קיים ספר אלקטרוני נלווה",
"LabelHasEbook": "קיים ספר אלקטרוני",
"LabelHasSupplementaryEbook": "קיים ספר אלקטרוני משלים",
"LabelHideSubtitles": "הסתר תת כותרות",
"LabelHighestPriority": "העדיפות הגבוהה ביותר",
"LabelHost": "מארח",
"LabelHour": "שעה",
"LabelHours": "שעות",
"LabelIcon": "סמל",
"LabelImageURLFromTheWeb": "כתובת התמונה מהרשת",
"LabelInProgress": "בתהליך",
@@ -341,25 +397,30 @@
"LabelIntervalEvery6Hours": "כל 6 שעות",
"LabelIntervalEveryDay": "כל יום",
"LabelIntervalEveryHour": "כל שעה",
"LabelIntervalEveryMinute": "כל דקה",
"LabelInvert": "הפוך",
"LabelItem": "פריט",
"LabelJumpBackwardAmount": "כמות הרצה לאחור",
"LabelJumpForwardAmount": "כמות הרצה קדימה",
"LabelLanguage": "שפה",
"LabelLanguageDefaultServer": "שפת ברירת המחדל של השרת",
"LabelLanguages": "שפות",
"LabelLastBookAdded": "הספר האחרון שנוסף",
"LabelLastBookUpdated": "הספר האחרון שעודכן",
"LabelLastSeen": "נראה לאחרונה",
"LabelLastTime": "הזמן האחרון",
"LabelLastUpdate": "עדכון אחרון",
"LabelLayout": "פריסה",
"LabelLayoutSinglePage": "דף בודד",
"LabelLayout": "Layout",
"LabelLayoutSinglePage": "עמוד יחיד",
"LabelLayoutSplitPage": "פיצול הדף",
"LabelLess": "פחות",
"LabelLibrariesAccessibleToUser": "ספריות נגישות למשתמש",
"LabelLibrary": "ספרייה",
"LabelLibraryFilterSublistEmpty": "לא {0}",
"LabelLibraryItem": "פריט ספרייה",
"LabelLibraryName": "שם הספרייה",
"LabelLimit": "מגבלה",
"LabelLineSpacing": יווח שורות",
"LabelLineSpacing": "מרווח שורה",
"LabelListenAgain": "האזן שוב",
"LabelLogLevelDebug": "דיבוג",
"LabelLogLevelInfo": "מידע",
@@ -368,6 +429,10 @@
"LabelLowestPriority": "העדיפות הנמוכה ביותר",
"LabelMatchExistingUsersBy": "התאם משתמשים קיימים לפי",
"LabelMatchExistingUsersByDescription": "משמש לחיבור משתמשים קיימים. לאחר החיבור, המשתמשים יותאמו לפי זיהוי ייחודי מספק ה-SSO שלך",
"LabelMaxEpisodesToDownload": "מספר פרקים מקסימלי להורדה. 0 - ללא הגבלה.",
"LabelMaxEpisodesToDownloadPerCheck": "מספר פרקים חדשים מקסימלי להורדה בכל בדיקה",
"LabelMaxEpisodesToKeep": "מספר פרקים מקסימלי לשמור",
"LabelMaxEpisodesToKeepHelp": "ערך של 0 קובע ללא מגבלה. לאחר הורדה אוטומטית של פרק חדש יימחק את הפרק הישן ביותר אם יש לך יותר מ-X פרקים. פעולה זו תמחק רק פרק אחד לכל הורדה חדשה.",
"LabelMediaPlayer": "נגן מדיה",
"LabelMediaType": "סוג מדיה",
"LabelMetaTag": "תג מטא",
@@ -375,6 +440,7 @@
"LabelMetadataOrderOfPrecedenceDescription": "מקורות המטא-נתונים עם עדיפות גבוהה יחליפו מקורות עם עדיפות נמוכה יותר",
"LabelMetadataProvider": "ספק מטא-נתונים",
"LabelMinute": "דקה",
"LabelMinutes": "דקות",
"LabelMissing": "חסר",
"LabelMissingEbook": "אין ספר אלקטרוני",
"LabelMissingSupplementaryEbook": "אין ספר אלקטרוני נלווה",
@@ -387,10 +453,11 @@
"LabelNarrators": "מספרים",
"LabelNew": "חדש",
"LabelNewPassword": "סיסמה חדשה",
"LabelNewestAuthors": "הסופרים החדשים ביותר",
"LabelNewestAuthors": "הסופרים האחרונים",
"LabelNewestEpisodes": "הפרקים החדשים ביותר",
"LabelNextBackupDate": "תאריך הגיבוי הבא",
"LabelNextScheduledRun": "הרצה מתוזמנת הבאה",
"LabelNoCustomMetadataProviders": "אין ספקי מטא-נתונים מותאמים אישית",
"LabelNoEpisodesSelected": "לא נבחרו פרקים",
"LabelNotFinished": "לא הושלם",
"LabelNotStarted": "לא התחיל",
@@ -405,7 +472,9 @@
"LabelNotificationsMaxQueueSize": "גודל התור המרבי לאירועי התראה",
"LabelNotificationsMaxQueueSizeHelp": "האירועים מוגבלים לשליחה אחת לשנייה. האירועים יתעלמו אם התור מלא. הגדרה זו נועדה למנוע ספאם התראות.",
"LabelNumberOfBooks": "מספר הספרים",
"LabelNumberOfEpisodes": "מספר הפרקים",
"LabelNumberOfEpisodes": "# פרקים",
"LabelOpenIDAdvancedPermsClaimDescription": "שם OpenID claim המכילה הרשאות מתקדמות לפעולות משתמש בתוך האפליקציה, אשר יחולו על תפקידים שאינם מנהלי מערכת (<b>אם הוגדרה</b>). אם התביעה חסרה בתגובה, הגישה ל-ABS תידחה. אם אפשרות אחת חסרה, היא תטופל כ-<code>false</code> יש לוודא שטענת ספק הזהויות תואמת את המבנה הצפוי:",
"LabelOpenIDClaims": "השאר את האפשרויות הבאות ריקות כדי להשבית הקצאת קבוצות והרשאות מתקדמת, ולאחר מכן להקצות אוטומטית את קבוצת 'משתמש'.",
"LabelOpenRSSFeed": "פתח ערוץ RSS",
"LabelOverwrite": "לשכפל",
"LabelPassword": "סיסמה",
@@ -433,13 +502,15 @@
"LabelProvider": "ספק",
"LabelPubDate": "תאריך פרסום",
"LabelPublishYear": "שנת הפרסום",
"LabelPublishedDate": "פורסם {0}",
"LabelPublisher": "מוציא לאור",
"LabelRSSFeedCustomOwnerEmail": "אימייל בעלים מותאם אישית",
"LabelRSSFeedCustomOwnerName": "שם בעלים מותאם אישית",
"LabelRSSFeedOpen": "פתח ערוץ RSS",
"LabelRSSFeedOpen": "ערוץ RSS פתוח",
"LabelRSSFeedPreventIndexing": "מנע רישום",
"LabelRSSFeedSlug": "Slug של ערוץ ה-RSS",
"LabelRSSFeedURL": "כתובת ערוץ ה-RSS",
"LabelRandomly": "באופן אקראי",
"LabelRead": "קריאה",
"LabelReadAgain": "קרא שוב",
"LabelReadEbookWithoutProgress": "קרא/י ספר אלקטרוני ללא שמירת התקדמות",
@@ -465,7 +536,7 @@
"LabelSeriesProgress": "התקדמות בסדרה",
"LabelServerYearReview": "השנה בסקירה של השרת ({0})",
"LabelSetEbookAsPrimary": "קבע כראשי",
"LabelSetEbookAsSupplementary": "קבע כספר אלקטרוני נלווה",
"LabelSetEbookAsSupplementary": "קבע כמשלים",
"LabelSettingsAudiobooksOnly": "רק ספרי קול",
"LabelSettingsAudiobooksOnlyHelp": "הפעלת ההגדרה הזו תתעלם מקבצי ספרים אלקטרוניים אלא אם כן הם נמצאים בתיקיית ספרי קול, שבמקרה זה יקבעו כספרים אלקטרוניים נלווים",
"LabelSettingsBookshelfViewHelp": "עיצוב סקאומורפי עם מדפי עץ",
@@ -500,7 +571,7 @@
"LabelShowAll": "הצג הכל",
"LabelSize": "גודל",
"LabelSleepTimer": "טיימר שינה",
"LabelStart": "התחלה",
"LabelStart": "התחל",
"LabelStartTime": "זמן התחלה",
"LabelStarted": "התחיל",
"LabelStartedAt": "התחיל ב",
@@ -576,8 +647,8 @@
"LabelViewQueue": "הצג תור נגן",
"LabelVolume": "עוצמת קול",
"LabelWeekdaysToRun": "ימי השבוע להרצה",
"LabelYearReviewHide": "הסתר שנת סקירה",
"LabelYearReviewShow": "הצג שנת סקירה",
"LabelYearReviewHide": "הסתר סקירת שנה",
"LabelYearReviewShow": "הצג סקירת שנה",
"LabelYourAudiobookDuration": "משך הספר הקולי שלך",
"LabelYourBookmarks": "הסימניות שלך",
"LabelYourPlaylists": "הפלייליסטים שלך",
@@ -628,8 +699,8 @@
"MessageDownloadingEpisode": "מוריד פרק",
"MessageDragFilesIntoTrackOrder": "גרור קבצים לסדר ההשמעה נכון",
"MessageEmbedFinished": "ההטמעה הושלמה!",
"MessageEpisodesQueuedForDownload": "{0} פרקים בתור להורדה",
"MessageFeedURLWillBe": "כתובת URL של העדכון תהיה {0}",
"MessageEpisodesQueuedForDownload": "{0} פרק/ים בתור להורדה",
"MessageFeedURLWillBe": "כתובת ה- URL של הערוץ תהיה {0}",
"MessageFetching": "מושך...",
"MessageForceReScanDescription": "תבוצע סריקה מחדש כמו סריקה חדש מאפס, תגי ID3 של קבצי קול, קבצי OPF, וקבצי טקסט ייסרקו כחדשים.",
"MessageImportantNotice": "הודעה חשובה!",
@@ -644,7 +715,7 @@
"MessageMapChapterTitles": "מפה שמות פרקים לפרקי הספר השמורים שלך ללא שינוי תגי זמן",
"MessageMarkAllEpisodesFinished": "סמן את כל הפרקים כהסתיימו",
"MessageMarkAllEpisodesNotFinished": "סמן את כל הפרקים כלא הסתיימו",
"MessageMarkAsFinished": "סמן כהסתיים",
"MessageMarkAsFinished": "סמן כהושלם",
"MessageMarkAsNotFinished": "סמן כלא הסתיים",
"MessageMatchBooksDescription": "ינסה להתאים ספרים בספריית הספרים שלך עם ספר מספק החיפוש הנבחר וימלא פרטים ריקים ותמונות כריכה. לא יחליף פרטים קיימים.",
"MessageNoAudioTracks": "אין רצועות שמע",
@@ -674,7 +745,7 @@
"MessageNoSeries": "אין סדרות",
"MessageNoTags": "אין תגיות",
"MessageNoTasksRunning": "אין משימות פעילות",
"MessageNoUpdatesWereNecessary": "לא היה צורך בעדכונים",
"MessageNoUpdatesWereNecessary": "לא נדרש עדכון",
"MessageNoUserPlaylists": "אין לך רשימות השמעה",
"MessageNotYetImplemented": "עדיין לא מיושם",
"MessageOr": "או",
@@ -682,6 +753,7 @@
"MessagePlayChapter": "הקשב לתחילת הפרק",
"MessagePlaylistCreateFromCollection": "צור רשימת השמעה מאוסף",
"MessagePodcastHasNoRSSFeedForMatching": "לפודקאסט אין כתובת URL של ערוץ RSS להתאמה",
"MessagePodcastSearchField": "הזן מונח חיפוש או כתובת URL של ערוץ RSS",
"MessageQuickMatchDescription": "ממלא פרטים ריקים וכריכות עם התוצאה הראשונה מ '{0}'. לא ימחק פרטים אלא אם הגדרת השרת 'העדף מטה-נתונים מותאמים' מופעלת.",
"MessageRemoveChapter": "הסר פרק",
"MessageRemoveEpisodes": "הסר {0} פרקים",
@@ -708,7 +780,7 @@
"NoteChangeRootPassword": "המשתמש root הוא המשתמש היחיד שיכולה להיות לו סיסמה ריקה",
"NoteChapterEditorTimes": "הערה: זמן ההתחלה של הפרק הראשון חייב להישאר 0:00 וזמן ההתחלה של הפרק האחרון לא יכול לחרוג מהזמן של ספר השמע.",
"NoteFolderPicker": "הערה: תיקיות שכבר מופו לא יוצגו",
"NoteRSSFeedPodcastAppsHttps": "אזהרה: רוב יישומי הפודקאסט דורשים שכתובת ה-URL ערוץ ה-RSS תשתמש ב-HTTPS",
"NoteRSSFeedPodcastAppsHttps": "אזהרה: רוב אפליקציות הפודקאסטים ידרשו שכתובת האתר של ערוץ ה-RSS תשתמש ב-HTTPS",
"NoteRSSFeedPodcastAppsPubDate": "אזהרה: פרק אחד או יותר לא מכילים תאריך פרסום. חלק מיישומי הפודקאסט דורשים זאת.",
"NoteUploaderFoldersWithMediaFiles": "תיקיות עם קבצי מדיה יעובדו כפריטי ספריה נפרדים.",
"NoteUploaderOnlyAudioFiles": "אם מועלים רק קבצי שמע, כל קובץ שמע יעובד כספר שמע נפרד.",
@@ -741,7 +813,7 @@
"ToastCollectionUpdateSuccess": "האוסף עודכן בהצלחה",
"ToastItemCoverUpdateSuccess": "כריכת הפריט עודכנה בהצלחה",
"ToastItemDetailsUpdateSuccess": "פרטי הפריט עודכנו בהצלחה",
"ToastItemMarkedAsFinishedFailed": "סימון כפריט כהושלם נכשל",
"ToastItemMarkedAsFinishedFailed": "סימון כפריט שהושלם נכשל",
"ToastItemMarkedAsFinishedSuccess": "הפריט סומן כהושלם בהצלחה",
"ToastItemMarkedAsNotFinishedFailed": "סימון כפריט שלא הושלם נכשל",
"ToastItemMarkedAsNotFinishedSuccess": "הפריט סומן כלא הושלם בהצלחה",

View File

@@ -1,12 +1,18 @@
{
"ButtonAdd": "जोड़ें",
"ButtonAddApiKey": "एपीआई कुंजी जोड़ें",
"ButtonAddChapters": "अध्याय जोड़ें",
"ButtonAddDevice": "उपकरण जोड़ें",
"ButtonAddLibrary": "संग्रह जोड़ें",
"ButtonAddPodcasts": "पॉडकास्ट जोड़ें",
"ButtonAddUser": "उपयोगकर्ता जोड़ें",
"ButtonAddYourFirstLibrary": "अपनी पहली पुस्तकालय जोड़ें",
"ButtonApply": "लागू करें",
"ButtonApplyChapters": "अध्यायों में परिवर्तन लागू करें",
"ButtonAuthors": "लेखक",
"ButtonBack": "पीछे",
"ButtonBatchEditPopulateFromExisting": "मौजूदा से आबाद करें",
"ButtonBatchEditPopulateMapDetails": "मानचित्र विवरण भरें",
"ButtonBrowseForFolder": "फ़ोल्डर खोजें",
"ButtonCancel": "रद्द करें",
"ButtonCancelEncode": "एनकोड रद्द करें",
@@ -15,7 +21,9 @@
"ButtonChooseAFolder": "एक फ़ोल्डर चुनें",
"ButtonChooseFiles": "फ़ाइलें चुनें",
"ButtonClearFilter": "लागू फ़िल्टर साफ़ करें",
"ButtonClose": "बंद करें",
"ButtonCloseFeed": "फ़ीड बंद करें",
"ButtonCloseSession": "वर्तमान सत्र बंद करें",
"ButtonCollections": "संग्रह",
"ButtonConfigureScanner": "स्कैनर सेटिंग्स बदलें",
"ButtonCreate": "बनाएं",
@@ -25,6 +33,7 @@
"ButtonEdit": "संपादित करें",
"ButtonEditChapters": "अध्याय संपादित करें",
"ButtonEditPodcast": "पॉडकास्ट संपादित करें",
"ButtonEnable": "सक्षम करें",
"ButtonForceReScan": "बलपूर्वक पुन: स्कैन करें",
"ButtonFullPath": "पूर्ण पथ",
"ButtonHide": "छुपाएं",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Dodaj",
"ButtonAddApiKey": "Dodaj API ključ",
"ButtonAddChapters": "Dodaj poglavlja",
"ButtonAddDevice": "Dodaj uređaj",
"ButtonAddLibrary": "Dodaj knjižnicu",
@@ -20,6 +21,7 @@
"ButtonChooseAFolder": "Odaberi mapu",
"ButtonChooseFiles": "Odaberi datoteke",
"ButtonClearFilter": "Poništi filter",
"ButtonClose": "Zatvori",
"ButtonCloseFeed": "Zatvori izvor",
"ButtonCloseSession": "Zatvori otvorenu sesiju",
"ButtonCollections": "Zbirke",
@@ -119,6 +121,7 @@
"HeaderAccount": "Korisnički račun",
"HeaderAddCustomMetadataProvider": "Dodaj prilagođenog pružatelja meta-podataka",
"HeaderAdvanced": "Napredno",
"HeaderApiKeys": "API ključevi",
"HeaderAppriseNotificationSettings": "Postavke obavijesti Apprise",
"HeaderAudioTracks": "Zvučni zapisi",
"HeaderAudiobookTools": "Alati za upravljanje datotekama zvučnih knjiga",
@@ -162,6 +165,7 @@
"HeaderMetadataOrderOfPrecedence": "Redoslijed prihvaćanja meta-podataka",
"HeaderMetadataToEmbed": "Meta-podatci za ugradnju",
"HeaderNewAccount": "Novi korisnički račun",
"HeaderNewApiKey": "Novi API ključ",
"HeaderNewLibrary": "Nova knjižnica",
"HeaderNotificationCreate": "Izradi obavijest",
"HeaderNotificationUpdate": "Ažuriraj obavijest",
@@ -195,6 +199,7 @@
"HeaderSettingsExperimental": "Eksperimentalne značajke",
"HeaderSettingsGeneral": "Općenito",
"HeaderSettingsScanner": "Skener",
"HeaderSettingsSecurity": "Sigurnost",
"HeaderSettingsWebClient": "Web klijent",
"HeaderSleepTimer": "Timer za spavanje",
"HeaderStatsLargestItems": "Najveće stavke",
@@ -206,6 +211,7 @@
"HeaderTableOfContents": "Sadržaj",
"HeaderTools": "Alati",
"HeaderUpdateAccount": "Ažuriraj korisnički račun",
"HeaderUpdateApiKey": "Ažuriraj API ključ",
"HeaderUpdateAuthor": "Ažuriraj autora",
"HeaderUpdateDetails": "Ažuriraj pojedinosti",
"HeaderUpdateLibrary": "Ažuriraj knjižnicu",
@@ -235,6 +241,10 @@
"LabelAllUsersExcludingGuests": "Svi korisnici osim gostiju",
"LabelAllUsersIncludingGuests": "Svi korisnici uključujući i goste",
"LabelAlreadyInYourLibrary": "Već u vašoj knjižnici",
"LabelApiKeyCreated": "API ključ \"{0}\" uspješno izrađen.",
"LabelApiKeyCreatedDescription": "Ne zaboravite odmah kopirati API ključ jer ga više nećete moći vidjeti.",
"LabelApiKeyUser": "Izvršavaj u ime korisnika",
"LabelApiKeyUserDescription": "Ovaj API ključ imat će iste dozvole kao i korisnik u čije ime djeluje. U zapisnicima će biti zabilježeno da je korisnik slao zahtjeve.",
"LabelApiToken": "API Token",
"LabelAppend": "Pridodaj",
"LabelAudioBitrate": "Kvaliteta zvučnog zapisa (npr. 128k)",
@@ -284,6 +294,7 @@
"LabelContinueListening": "Nastavi slušati",
"LabelContinueReading": "Nastavi čitati",
"LabelContinueSeries": "Nastavi serijal",
"LabelCorsAllowed": "Dozvoljena CORS ishodišta",
"LabelCover": "Naslovnica",
"LabelCoverImageURL": "URL naslovnice",
"LabelCoverProvider": "Pružatelj naslovnica",
@@ -346,7 +357,11 @@
"LabelExample": "Primjer",
"LabelExpandSeries": "Serijal prikaži prošireno",
"LabelExpandSubSeries": "Podserijal prikaži prošireno",
"LabelExplicit": "Eksplicitni sadržaj",
"LabelExpired": "Istekao",
"LabelExpiresAt": "Istječe",
"LabelExpiresInSeconds": "Istječe za (sekundi)",
"LabelExpiresNever": "Nikada",
"LabelExplicit": "Eksplicitno",
"LabelExplicitChecked": "Eksplicitni sadržaj (označeno)",
"LabelExplicitUnchecked": "Nije eksplicitni sadržaj (odznačeno)",
"LabelExportOPML": "Izvoz OPML-a",
@@ -405,6 +420,7 @@
"LabelLanguages": "Jezici",
"LabelLastBookAdded": "Zadnja dodana knjiga",
"LabelLastBookUpdated": "Zadnja ažurirana knjiga",
"LabelLastProgressDate": "Zadnji napredak: {0}",
"LabelLastSeen": "Zadnji puta viđen",
"LabelLastTime": "Zadnje doslušano vrijeme",
"LabelLastUpdate": "Zadnje ažuriranje",
@@ -417,6 +433,7 @@
"LabelLibraryFilterSublistEmpty": "Br {0}",
"LabelLibraryItem": "Stavka knjižnice",
"LabelLibraryName": "Ime knjižnice",
"LabelLibrarySortByProgress": "Napredak ažuriran",
"LabelLimit": "Ograničenje",
"LabelLineSpacing": "Razmak između redaka",
"LabelListenAgain": "Ponovno poslušaj",
@@ -425,6 +442,7 @@
"LabelLogLevelWarn": "Warn",
"LabelLookForNewEpisodesAfterDate": "Traži nove nastavke nakon ovog datuma",
"LabelLowestPriority": "Najniži prioritet",
"LabelMatchConfidence": "Pouzdanost",
"LabelMatchExistingUsersBy": "Prepoznaj postojeće korisnike pomoću",
"LabelMatchExistingUsersByDescription": "Rabi se za povezivanje postojećih korisnika. Nakon što se spoje, korisnike se prepoznaje temeljem jedinstvene oznake vašeg pružatelja SSO usluga",
"LabelMaxEpisodesToDownload": "Najveći broj nastavaka za preuzimanje. 0 za neograničeno.",
@@ -455,6 +473,7 @@
"LabelNewestEpisodes": "Najnoviji nastavci",
"LabelNextBackupDate": "Sljedeća izrada sigurnosne kopije",
"LabelNextScheduledRun": "Sljedeće zakazano izvođenje",
"LabelNoApiKeys": "Nema API ključeva",
"LabelNoCustomMetadataProviders": "Nema prilagođenih pružatelja meta-podataka",
"LabelNoEpisodesSelected": "Nema odabranih nastavaka",
"LabelNotFinished": "Nije dovršeno",
@@ -544,6 +563,7 @@
"LabelSelectAll": "Označi sve",
"LabelSelectAllEpisodes": "Označi sve nastavke",
"LabelSelectEpisodesShowing": "Prikazujem {0} odabranih nastavaka",
"LabelSelectUser": "Odaberite korisnika",
"LabelSelectUsers": "Označi korisnike",
"LabelSendEbookToDevice": "Pošalji e-knjigu …",
"LabelSequence": "Slijed",
@@ -640,6 +660,7 @@
"LabelTheme": "Tema",
"LabelThemeDark": "Tamna",
"LabelThemeLight": "Svijetla",
"LabelThemeSepia": "Sepija",
"LabelTimeBase": "Baza vremena",
"LabelTimeDurationXHours": "{0} sati",
"LabelTimeDurationXMinutes": "{0} minuta",
@@ -708,7 +729,9 @@
"MessageAddToPlayerQueue": "Dodaj u redoslijed izvođenja",
"MessageAppriseDescription": "Da biste se koristili ovom značajkom, treba vam instanca <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API-ja</a> ili API koji može rukovati istom vrstom zahtjeva.<br />The Adresa Apprise API-ja treba biti puna URL putanja za slanje obavijesti, npr. ako vam se API instanca poslužuje na adresi <code>http://192.168.1.1:8337</code> trebate upisati <code>http://192.168.1.1:8337/notify</code>.",
"MessageAsinCheck": "Upišite ASIN iz odgovarajuće Audibleove regije, ne s Amazonov.",
"MessageAuthenticationLegacyTokenWarning": "Starije API tokene ćemo ukloniti. Umjesto njih, koristite se <a href=\"/config/api-keys\">API ključevima</a> .",
"MessageAuthenticationOIDCChangesRestart": "Ponovno pokrenite poslužitelj da biste primijenili OIDC promjene.",
"MessageAuthenticationSecurityMessage": "Provjera autentičnosti poboljšana je radi sigurnosti. Svi se korisnici moraju ponovno prijaviti.",
"MessageBackupsDescription": "Sigurnosne kopije sadrže korisnike, korisnikov napredak medija, pojedinosti knjižničke građe, postavke poslužitelja i slike koje se spremaju u <code>/metadata/items</code> & <code>/metadata/authors</code>. Sigurnosne kopije ne sadrže niti jednu datoteku iz mapa knjižnice.",
"MessageBackupsLocationEditNote": "Napomena: Uređivanje lokacije za sigurnosne kopije ne premješta ili mijenja postojeće sigurnosne kopije",
"MessageBackupsLocationNoEditNote": "Napomena: Lokacija za sigurnosne kopije zadana je kroz varijablu okoline i ovdje se ne može izmijeniti.",
@@ -730,6 +753,7 @@
"MessageChaptersNotFound": "Poglavlja nisu pronađena",
"MessageCheckingCron": "Provjeravam cron...",
"MessageConfirmCloseFeed": "Sigurno želite zatvoriti ovaj izvor?",
"MessageConfirmDeleteApiKey": "Sigurno želite izbrisati API ključ \"{0}\"?",
"MessageConfirmDeleteBackup": "Sigurno želite izbrisati sigurnosnu kopiju za {0}?",
"MessageConfirmDeleteDevice": "Sigurno želite izbrisati e-čitač \"{0}\"?",
"MessageConfirmDeleteFile": "Ovo će izbrisati datoteke s datotečnog sustava. Jeste li sigurni?",
@@ -757,6 +781,7 @@
"MessageConfirmRemoveAuthor": "Sigurno želite ukloniti autora \"{0}\"?",
"MessageConfirmRemoveCollection": "Sigurno želite obrisati kolekciju \"{0}\"?",
"MessageConfirmRemoveEpisode": "Sigurno želite ukloniti nastavak \"{0}\"?",
"MessageConfirmRemoveEpisodeNote": "Napomena: Ova funkcija neće izbrisati zvučnu datoteku ukoliko ne uključite opciju \"Izbriši datoteku zauvijek\"",
"MessageConfirmRemoveEpisodes": "Sigurno želite ukloniti {0} nastavaka?",
"MessageConfirmRemoveListeningSessions": "Sigurno želite ukloniti {0} sesija slušanja?",
"MessageConfirmRemoveMetadataFiles": "Sigurno želite ukloniti sve datoteke metadata.{0} u mapama vaših knjižničkih stavki?",
@@ -782,6 +807,8 @@
"MessageFeedURLWillBe": "URL izvora bit će {0}",
"MessageFetching": "Dohvaćam...",
"MessageForceReScanDescription": "će ponovno skenirati sve datoteke kao nove datoteke. ID3 tagovi zvučnih datoteka, OPF datoteke i tekstualne datoteke skenirat će se kao da su nove.",
"MessageHeatmapListeningTimeTooltip": "<strong>{0} sluša</strong> na {1}",
"MessageHeatmapNoListeningSessions": "Nema sesija slušanja na {0}",
"MessageImportantNotice": "Važna obavijest!",
"MessageInsertChapterBelow": "Unesi poglavlje ispod",
"MessageInvalidAsin": "Nevažeći ASIN",
@@ -918,6 +945,8 @@
"NotificationOnBackupCompletedDescription": "Pokreće se po završetku sigurnosnog kopiranja",
"NotificationOnBackupFailedDescription": "Pokreće se kada sigurnosno kopiranje ne uspije",
"NotificationOnEpisodeDownloadedDescription": "Pokreće se kada se nastavak podcasta automatski preuzme",
"NotificationOnRSSFeedDisabledDescription": "Pokreće se kada su automatska preuzimanja nastavaka onemogućena zbog previše neuspjelih pokušaja",
"NotificationOnRSSFeedFailedDescription": "Pokreće se u slučaju pogreške pri pokušaju automatskog preuzimanja nastavka s RSS izvora",
"NotificationOnTestDescription": "Događaj za testiranje sustava obavijesti",
"PlaceholderNewCollection": "Ime nove zbirke",
"PlaceholderNewFolderPath": "Nova putanja mape",
@@ -998,6 +1027,8 @@
"ToastEpisodeDownloadQueueClearSuccess": "Redoslijed preuzimanja nastavaka očišćen",
"ToastEpisodeUpdateSuccess": "{0} nastavak/a ažurirano",
"ToastErrorCannotShare": "Dijeljenje na ovaj uređaj nije moguće",
"ToastFailedToCreate": "Izrada nije uspjela",
"ToastFailedToDelete": "Brisanje nije uspjelo",
"ToastFailedToLoadData": "Učitavanje podataka nije uspjelo",
"ToastFailedToMatch": "Nije prepoznato",
"ToastFailedToShare": "Dijeljenje nije uspjelo",
@@ -1005,6 +1036,7 @@
"ToastInvalidImageUrl": "Neispravan URL slike",
"ToastInvalidMaxEpisodesToDownload": "Neispravan unos maksimalnog broja nastavaka",
"ToastInvalidUrl": "Neispravan URL",
"ToastInvalidUrls": "Jedan ili više URL-ova nisu ispravni",
"ToastItemCoverUpdateSuccess": "Naslovnica stavke ažurirana",
"ToastItemDeletedFailed": "Brisanje stavke nije uspjelo",
"ToastItemDeletedSuccess": "Stavka je izbrisana",
@@ -1029,6 +1061,7 @@
"ToastMustHaveAtLeastOnePath": "Mora postojati barem jedna putanja",
"ToastNameEmailRequired": "Ime i adresa e-pošte su obavezni",
"ToastNameRequired": "Ime je obavezno",
"ToastNewApiKeyUserError": "Morate odabrati korisnika",
"ToastNewEpisodesFound": "pronađeno {0} novih nastavaka",
"ToastNewUserCreatedFailed": "Račun \"{0}\" nije uspješno izrađen",
"ToastNewUserCreatedSuccess": "Novi račun izrađen",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Hozzáadás",
"ButtonAddApiKey": "API kulcs hozzáadása",
"ButtonAddChapters": "Fejezetek hozzáadása",
"ButtonAddDevice": "Eszköz hozzáadása",
"ButtonAddLibrary": "Könyvtár hozzáadása",
@@ -11,7 +12,7 @@
"ButtonAuthors": "Szerzők",
"ButtonBack": "Vissza",
"ButtonBatchEditPopulateFromExisting": "Létezőből feltöltés",
"ButtonBatchEditPopulateMapDetails": "",
"ButtonBatchEditPopulateMapDetails": "A térkép részleteinek feltöltése",
"ButtonBrowseForFolder": "Mappa keresése",
"ButtonCancel": "Mégse",
"ButtonCancelEncode": "Kódolás megszakítása",
@@ -20,6 +21,7 @@
"ButtonChooseAFolder": "Válassz egy mappát",
"ButtonChooseFiles": "Fájlok kiválasztása",
"ButtonClearFilter": "Szűrő törlése",
"ButtonClose": "Bezár",
"ButtonCloseFeed": "Hírcsatorna bezárása",
"ButtonCloseSession": "Nyitott munkamenet bezárása",
"ButtonCollections": "Gyűjtemények",
@@ -119,6 +121,7 @@
"HeaderAccount": "Fiók",
"HeaderAddCustomMetadataProvider": "Egyedi metaadat szolgáltató hozzáadása",
"HeaderAdvanced": "Haladó",
"HeaderApiKeys": "API kulcsok",
"HeaderAppriseNotificationSettings": "Apprise értesítési beállítások",
"HeaderAudioTracks": "Audiósávok",
"HeaderAudiobookTools": "Hangoskönyv fájlkezelő eszközök",
@@ -162,6 +165,7 @@
"HeaderMetadataOrderOfPrecedence": "Metaadatok előnyben részesítési sorrendje",
"HeaderMetadataToEmbed": "Beágyazandó metaadatok",
"HeaderNewAccount": "Új fiók",
"HeaderNewApiKey": "Új API kulcs",
"HeaderNewLibrary": "Új könyvtár",
"HeaderNotificationCreate": "Értesítés készítése",
"HeaderNotificationUpdate": "Értesítés frissítése",
@@ -177,6 +181,7 @@
"HeaderPlaylist": "Lejátszási lista",
"HeaderPlaylistItems": "Lejátszási lista elemek",
"HeaderPodcastsToAdd": "Hozzáadandó podcastok",
"HeaderPresets": "Alapbeállítások",
"HeaderPreviewCover": "Borító előnézete",
"HeaderRSSFeedGeneral": "RSS részletek",
"HeaderRSSFeedIsOpen": "RSS hírcsatorna nyitva van",
@@ -205,6 +210,7 @@
"HeaderTableOfContents": "Tartalomjegyzék",
"HeaderTools": "Eszközök",
"HeaderUpdateAccount": "Fiók frissítése",
"HeaderUpdateApiKey": "API kulcs frissítése",
"HeaderUpdateAuthor": "Szerző frissítése",
"HeaderUpdateDetails": "Részletek frissítése",
"HeaderUpdateLibrary": "Könyvtár frissítése",
@@ -219,6 +225,7 @@
"LabelAccountTypeAdmin": "Adminisztrátor",
"LabelAccountTypeGuest": "Vendég",
"LabelAccountTypeUser": "Felhasználó",
"LabelActivities": "Tevékenységek",
"LabelActivity": "Tevékenység",
"LabelAddToCollection": "Hozzáadás a gyűjteményhez",
"LabelAddToCollectionBatch": "{0} könyv hozzáadása a gyűjteményhez",
@@ -228,10 +235,15 @@
"LabelAddedDate": "{0} Hozzáadva",
"LabelAdminUsersOnly": "Csak admin felhasználók",
"LabelAll": "Összes",
"LabelAllEpisodesDownloaded": "Minden epizód letöltve",
"LabelAllUsers": "Minden felhasználó",
"LabelAllUsersExcludingGuests": "Minden felhasználó, vendégek kivételével",
"LabelAllUsersIncludingGuests": "Minden felhasználó, beleértve a vendégeket is",
"LabelAlreadyInYourLibrary": "Már a könyvtárában van",
"LabelApiKeyCreated": "\"{0}\" API kulcs sikeresen létrehozva.",
"LabelApiKeyCreatedDescription": "Feltétlenül másolja le az API kulcsot, mert később már nem fogja látni.",
"LabelApiKeyUser": "Felhasználó nevében eljárva",
"LabelApiKeyUserDescription": "Ez az API-kulcs ugyanazokkal a jogosultságokkal rendelkezik, mint az a felhasználó, akinek a nevében működik. A naplófájlokban ez úgy jelenik meg, mintha a felhasználó maga küldte volna a kérést.",
"LabelApiToken": "API Token",
"LabelAppend": "Hozzáfűzés",
"LabelAudioBitrate": "Audió bitráta (pl.128k)",
@@ -251,7 +263,7 @@
"LabelBackToUser": "Vissza a felhasználóhoz",
"LabelBackupAudioFiles": "Audiófájlok biztonsági mentése",
"LabelBackupLocation": "Biztonsági másolat helye",
"LabelBackupsEnableAutomaticBackups": "Automatikus biztonsági másolatok engedélyezése",
"LabelBackupsEnableAutomaticBackups": "Automatikus biztonsági másolatok",
"LabelBackupsEnableAutomaticBackupsHelp": "Biztonsági másolatok mentése a /metadata/backups mappába",
"LabelBackupsMaxBackupSize": "Maximális biztonsági másolat méret (GB-ban) (0-tól végtelenig)",
"LabelBackupsMaxBackupSizeHelp": "A rossz konfiguráció elleni védelem érdekében a biztonsági másolatok meghiúsulnak, ha meghaladják a beállított méretet.",
@@ -261,7 +273,7 @@
"LabelBonus": "Bónusz",
"LabelBooks": "Könyvek",
"LabelButtonText": "Gomb szövege",
"LabelByAuthor": "{} által",
"LabelByAuthor": "{0} által",
"LabelChangePassword": "Jelszó megváltoztatása",
"LabelChannels": "Csatornák",
"LabelChapterCount": "{0} Fejezet",
@@ -275,7 +287,7 @@
"LabelCollapseSeries": "Sorozat összecsukása",
"LabelCollapseSubSeries": "Alszéria összecsukása",
"LabelCollection": "Gyűjtemény",
"LabelCollections": "Gyűjtemény",
"LabelCollections": "Gyűjtemények",
"LabelComplete": "Kész",
"LabelConfirmPassword": "Jelszó megerősítése",
"LabelContinueListening": "Hallgatás folytatása",
@@ -283,6 +295,7 @@
"LabelContinueSeries": "Sorozat folytatása",
"LabelCover": "Borító",
"LabelCoverImageURL": "Borítókép URL",
"LabelCoverProvider": "Borító Szolgáltató",
"LabelCreatedAt": "Létrehozás ideje",
"LabelCronExpression": "Cron kifejezés",
"LabelCurrent": "Jelenlegi",
@@ -342,6 +355,10 @@
"LabelExample": "Példa",
"LabelExpandSeries": "Sorozat kinyitása",
"LabelExpandSubSeries": "Alsorozat kinyitása",
"LabelExpired": "Lejárt",
"LabelExpiresAt": "Lejár",
"LabelExpiresInSeconds": "Lejár (másodpercben)",
"LabelExpiresNever": "Soha",
"LabelExplicit": "Szókimondó",
"LabelExplicitChecked": "Explicit (ellenőrizve)",
"LabelExplicitUnchecked": "Nem explicit (nem ellenőrzött)",
@@ -391,7 +408,8 @@
"LabelIntervalEvery6Hours": "Minden 6 órában",
"LabelIntervalEveryDay": "Minden nap",
"LabelIntervalEveryHour": "Minden órában",
"LabelInvert": "Megfordítás",
"LabelIntervalEveryMinute": "Minden percben",
"LabelInvert": "Inverz",
"LabelItem": "Elem",
"LabelJumpBackwardAmount": "Visszafelé ugrás mennyisége",
"LabelJumpForwardAmount": "Előre ugrás mennyisége",
@@ -400,6 +418,7 @@
"LabelLanguages": "Nyelvek",
"LabelLastBookAdded": "Utolsó hozzáadott könyv",
"LabelLastBookUpdated": "Utolsó frissített könyv",
"LabelLastProgressDate": "Legutóbbi haladás: {0}",
"LabelLastSeen": "Utolsó látogatás",
"LabelLastTime": "Utolsó alkalom",
"LabelLastUpdate": "Utolsó frissítés",
@@ -412,6 +431,7 @@
"LabelLibraryFilterSublistEmpty": "Nem {0}",
"LabelLibraryItem": "Könyvtári elem",
"LabelLibraryName": "Könyvtár neve",
"LabelLibrarySortByProgress": "Haladás frissítve",
"LabelLimit": "Korlát",
"LabelLineSpacing": "Sorköz",
"LabelListenAgain": "Újrahallgatás",
@@ -420,6 +440,7 @@
"LabelLogLevelWarn": "Figyelmeztetés",
"LabelLookForNewEpisodesAfterDate": "Új epizódok keresése ezen a dátum után",
"LabelLowestPriority": "Legalacsonyabb prioritás",
"LabelMatchConfidence": "Bizalom",
"LabelMatchExistingUsersBy": "Meglévő felhasználók egyeztetése",
"LabelMatchExistingUsersByDescription": "Meglévő felhasználók összekapcsolására használt. Egyszer összekapcsolva, a felhasználók egyedülálló azonosítóval lesznek egyeztetve az Ön SSO szolgáltatójától",
"LabelMaxEpisodesToDownload": "Letölthető epizódok maximális száma. Használja a 0-t a korlátlan letöltéshez.",
@@ -450,6 +471,7 @@
"LabelNewestEpisodes": "Legújabb epizódok",
"LabelNextBackupDate": "Következő biztonsági másolat dátuma",
"LabelNextScheduledRun": "Következő ütemezett futtatás",
"LabelNoApiKeys": "Nincs API kulcs",
"LabelNoCustomMetadataProviders": "Nincsenek egyedi metaadat szolgáltatók",
"LabelNoEpisodesSelected": "Nincsenek kiválasztott epizódok",
"LabelNotFinished": "Nem befejezett",
@@ -486,6 +508,7 @@
"LabelPersonalYearReview": "Az éved összefoglalása ({0})",
"LabelPhotoPathURL": "Fénykép útvonal/URL",
"LabelPlayMethod": "Lejátszási módszer",
"LabelPlaybackRateIncrementDecrement": "Lejátszási sebesség növelés/csökkentés értéke",
"LabelPlayerChapterNumberMarker": "{0} a {1} -ből",
"LabelPlaylists": "Lejátszási listák",
"LabelPodcast": "Podcast",
@@ -508,7 +531,7 @@
"LabelPublishers": "Kiadók",
"LabelRSSFeedCustomOwnerEmail": "Egyéni tulajdonos e-mail",
"LabelRSSFeedCustomOwnerName": "Egyéni tulajdonos neve",
"LabelRSSFeedOpen": "RSS hírcsatorna nyitva",
"LabelRSSFeedOpen": "RSS-hírcsatorna nyitva",
"LabelRSSFeedPreventIndexing": "Indexelés megakadályozása",
"LabelRSSFeedSlug": "RSS hírcsatorna slug",
"LabelRSSFeedURL": "RSS hírcsatorna URL",
@@ -525,6 +548,7 @@
"LabelReleaseDate": "Megjelenés dátuma",
"LabelRemoveAllMetadataAbs": "Az összes metadata.abs fájl eltávolítása",
"LabelRemoveAllMetadataJson": "Az összes metadata.json fájl eltávolítása",
"LabelRemoveAudibleBranding": "Audible intro és outro eltávolítása a fejezetekből",
"LabelRemoveCover": "Borító eltávolítása",
"LabelRemoveMetadataFile": "Metaadatfájlok eltávolítása a könyvtár elemek mappáiból",
"LabelRemoveMetadataFileHelp": "A metadata.json és metadata.abs fájlokat eltávolítása a {0} mappáidból.",
@@ -537,6 +561,7 @@
"LabelSelectAll": "Minden kiválasztása",
"LabelSelectAllEpisodes": "Összes epizód kiválasztása",
"LabelSelectEpisodesShowing": "Kiválasztás {0} megjelenített epizód",
"LabelSelectUser": "Felhasználó kiválasztása",
"LabelSelectUsers": "Felhasználók kiválasztása",
"LabelSendEbookToDevice": "E-könyv küldése...",
"LabelSequence": "Sorozat",
@@ -554,6 +579,8 @@
"LabelSettingsBookshelfViewHelp": "Skeuomorfikus dizájn fa polcokkal",
"LabelSettingsChromecastSupport": "Chromecast támogatás",
"LabelSettingsDateFormat": "Dátumformátum",
"LabelSettingsEnableWatcher": "Változások automatikus vizsgálata a könyvtárakban",
"LabelSettingsEnableWatcherForLibrary": "Változások automatikus vizsgálata a könyvtárban",
"LabelSettingsEnableWatcherHelp": "Engedélyezi az automatikus elem hozzáadás/frissítés funkciót, amikor fájlváltozásokat észlel. *Szerver újraindítása szükséges",
"LabelSettingsEpubsAllowScriptedContent": "Szkriptelt tartalmak engedélyezése epub-okban",
"LabelSettingsEpubsAllowScriptedContentHelp": "Megengedi, hogy az epub fájlok szkripteket hajtsanak végre. Ezt a beállítást kikapcsolva ajánlott tartani, kivéve, ha megbízik az epub fájlok forrásában.",
@@ -597,6 +624,7 @@
"LabelSlug": "Rövid cím",
"LabelSortAscending": "Emelkedő",
"LabelSortDescending": "Csökkenő",
"LabelSortPubDate": "Rendezés megjelenés dátuma szerint",
"LabelStart": "Kezdés",
"LabelStartTime": "Kezdési idő",
"LabelStarted": "Elkezdődött",
@@ -630,6 +658,7 @@
"LabelTheme": "Téma",
"LabelThemeDark": "Sötét",
"LabelThemeLight": "Világos",
"LabelThemeSepia": "Szépia",
"LabelTimeBase": "Időalap",
"LabelTimeDurationXHours": "{0} óra",
"LabelTimeDurationXMinutes": "{0} perc",
@@ -697,12 +726,19 @@
"LabelYourProgress": "Haladásod",
"MessageAddToPlayerQueue": "Hozzáadás a lejátszó sorhoz",
"MessageAppriseDescription": "Ennek a funkció használatához futtatnia kell egy <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> példányt vagy egy olyan API-t, amely kezeli ezeket a kéréseket. <br />Az Apprise API URL-nek a teljes URL útvonalat kell tartalmaznia az értesítés elküldéséhez, például, ha az API példánya a <code>http://192.168.1.1:8337</code> címen szolgáltatva, akkor <code>http://192.168.1.1:8337/notify</code> értéket kell megadnia.",
"MessageAsinCheck": "Győződjön meg róla, hogy az ASIN-t a megfelelő Audible régióból használja, nem az Amazonból.",
"MessageAuthenticationLegacyTokenWarning": "A régi API-tokenek a jövőben eltávolításra kerülnek. Helyette használja az <a href=\"/config/api-keys\">API-kulcsokat</a>.",
"MessageAuthenticationOIDCChangesRestart": "A mentés után indítsa újra a szervert az OIDC módosítások alkalmazásához.",
"MessageAuthenticationSecurityMessage": "A biztonság érdekében a hitelesítés folyamatát továbbfejlesztettük. Minden felhasználónak újra be kell jelentkeznie.",
"MessageBackupsDescription": "A biztonsági másolatok tartalmazzák a felhasználókat, a felhasználói haladást, a könyvtári elem részleteit, a szerver beállításait és a képeket, amelyek a <code>/metadata/items</code> és <code>/metadata/authors</code> mappákban vannak tárolva. A biztonsági másolatok <strong>nem</strong> tartalmazzák a könyvtári mappákban tárolt fájlokat.",
"MessageBackupsLocationEditNote": "Megjegyzés: A biztonsági mentés helyének frissítése nem mozgatja vagy módosítja a meglévő biztonsági mentéseket",
"MessageBackupsLocationNoEditNote": "Megjegyzés: A biztonsági mentés helye egy környezeti változóval van beállítva, és itt nem módosítható.",
"MessageBackupsLocationPathEmpty": "A biztonsági mentés helyének elérési útvonala nem lehet üres",
"MessageBatchEditPopulateMapDetailsAllHelp": "Az engedélyezett mezők feltöltése az összes elem adatával. A több értéket tartalmazó mezők összevonásra kerülnek",
"MessageBatchEditPopulateMapDetailsItemHelp": "A térkép engedélyezett adatmezőinek feltöltése ezen elem adataival",
"MessageBatchQuickMatchDescription": "A Gyors egyeztetés megpróbálja hozzáadni a hiányzó borítókat és metaadatokat a kiválasztott elemekhez. Engedélyezze az alábbi opciókat, hogy a Gyors egyeztetés felülírhassa a meglévő borítókat és/vagy metaadatokat.",
"MessageBookshelfNoCollections": "Még nem készített gyűjteményeket",
"MessageBookshelfNoCollectionsHelp": "A gyűjtemények nyilvánosak. Minden, a könyvtárhoz hozzáféréssel rendelkező felhasználó láthatja őket.",
"MessageBookshelfNoRSSFeeds": "Nincsenek nyitott RSS hírcsatornák",
"MessageBookshelfNoResultsForFilter": "Nincs eredmény a \"{0}: {1}\" szűrőre",
"MessageBookshelfNoResultsForQuery": "Nincs eredmény a lekérdezéshez",
@@ -712,8 +748,10 @@
"MessageChapterErrorStartGteDuration": "Érvénytelen kezdési idő, kevesebbnek kell lennie, mint a hangoskönyv időtartama",
"MessageChapterErrorStartLtPrev": "Érvénytelen kezdési idő, nagyobbnak kell lennie, mint az előző fejezet kezdési ideje",
"MessageChapterStartIsAfter": "A fejezet kezdete a hangoskönyv végét követi",
"MessageChaptersNotFound": "Fejezetek nem találhatók",
"MessageCheckingCron": "Cron ellenőrzése...",
"MessageConfirmCloseFeed": "Biztosan be szeretné zárni ezt a hírcsatornát?",
"MessageConfirmDeleteApiKey": "Biztosan törölni szeretné az \"{0}\" API kulcsot?",
"MessageConfirmDeleteBackup": "Biztosan törölni szeretné a(z) {0} biztonsági másolatot?",
"MessageConfirmDeleteDevice": "Biztos, hogy törölni szeretné a „{0}” e-olvasó eszközt?",
"MessageConfirmDeleteFile": "Ez törölni fogja a fájlt a fájlrendszerből. Biztos benne?",
@@ -741,6 +779,7 @@
"MessageConfirmRemoveAuthor": "Biztosan eltávolítja a(z) \"{0}\" szerzőt?",
"MessageConfirmRemoveCollection": "Biztosan eltávolítja a(z) \"{0}\" gyűjteményt?",
"MessageConfirmRemoveEpisode": "Biztosan eltávolítja a(z) \"{0}\" epizódot?",
"MessageConfirmRemoveEpisodeNote": "Megjegyzés: Ez nem törli a hangfájlt, kivéve, ha a \"Hangfájl végleges törlése\" be van kapcsolva",
"MessageConfirmRemoveEpisodes": "Biztosan eltávolítja a(z) {0} epizódot?",
"MessageConfirmRemoveListeningSessions": "Biztosan eltávolítja a(z) {0} hallgatási munkamenetet?",
"MessageConfirmRemoveMetadataFiles": "Biztos, hogy az összes metaadatot el akarja távolítani {0} fájl van könyvtár mappáiban?",
@@ -768,6 +807,7 @@
"MessageForceReScanDescription": "minden fájlt újra szkennel, mint egy friss szkennelés. Az audiofájlok ID3 címkéi, OPF fájlok és szövegfájlok újként lesznek szkennelve.",
"MessageImportantNotice": "Fontos közlemény!",
"MessageInsertChapterBelow": "Fejezet beszúrása alulra",
"MessageInvalidAsin": "Érvénytelen ASIN",
"MessageItemsSelected": "{0} kiválasztott elem",
"MessageItemsUpdated": "{0} frissített elem",
"MessageJoinUsOn": "Csatlakozzon hozzánk a",
@@ -813,6 +853,7 @@
"MessageNoTasksRunning": "Nincsenek futó feladatok",
"MessageNoUpdatesWereNecessary": "Nem volt szükség frissítésekre",
"MessageNoUserPlaylists": "Nincsenek felhasználói lejátszási listák",
"MessageNoUserPlaylistsHelp": "A lejátszási listák személyesek. Csak az a felhasználó láthatja őket, aki létrehozta őket.",
"MessageNotYetImplemented": "Még nem implementált",
"MessageOpmlPreviewNote": "Megjegyzés: Ez egy előnézeti kép az elemzett OPML fájlról. A podcast tényleges címe az RSS hírcsatornából származik.",
"MessageOr": "vagy",
@@ -835,8 +876,10 @@
"MessageRestoreBackupConfirm": "Biztosan vissza szeretné állítani a biztonsági másolatot, amely ekkor készült:",
"MessageRestoreBackupWarning": "A biztonsági mentés visszaállítása felülírja az egész adatbázist, amely a /config mappában található, valamint a borítóképeket a /metadata/items és /metadata/authors mappákban.<br /><br />A biztonsági mentések nem módosítják a könyvtár mappáiban található fájlokat. Ha engedélyezte a szerverbeállításokat a borítóképek és a metaadatok könyvtármappákban való tárolására, akkor ezek nem kerülnek biztonsági mentésre vagy felülírásra.<br /><br />A szerver használó összes kliens automatikusan frissül.",
"MessageScheduleLibraryScanNote": "A legtöbb felhasználó számára ajánlott ezt a funkciót kikapcsolva hagyni, és engedélyezni a mappafigyelő beállítást. A mappafigyelő automatikusan észleli a könyvtári mappák változásait. A mappafigyelő nem működik minden fájlrendszernél (mint például az NFS), ezért helyette ütemezett könyvtárellenőrzéseket lehet használni.",
"MessageScheduleRunEveryWeekdayAtTime": "Futás minden {1} óra {0}-kor",
"MessageSearchResultsFor": "Keresési eredmények",
"MessageSelected": "{0} kiválasztva",
"MessageSeriesSequenceCannotContainSpaces": "Sorozat sorrend nem tartalmazhat szóközt",
"MessageServerCouldNotBeReached": "A szervert nem lehet elérni",
"MessageSetChaptersFromTracksDescription": "Fejezetek beállítása minden egyes hangfájlt egy fejezetként használva, és a fejezet címét a hangfájl neveként",
"MessageShareExpirationWillBe": "A lejárat: <strong>{0}</strong>",
@@ -861,6 +904,7 @@
"MessageTaskNoFilesToScan": "Nincs beolvasandó fájl",
"MessageTaskOpmlImport": "OPML import",
"MessageTaskOpmlImportDescription": "Podcastok létrehozása {0} RSS hírcsatornából",
"MessageTaskOpmlImportFeed": "OPML import hírcsatorna",
"MessageTaskOpmlImportFeedDescription": "RSS feed „{0}” importálása",
"MessageTaskOpmlImportFeedFailed": "Nem sikerült letölteni a podcast feedet",
"MessageTaskOpmlImportFeedPodcastDescription": "„{0}” podcast létrehozása",
@@ -869,6 +913,7 @@
"MessageTaskOpmlImportFinished": "{0} podcast hozzáadva",
"MessageTaskOpmlParseFailed": "Az OPML fájl elemzése nem sikerült",
"MessageTaskOpmlParseFastFail": "Érvénytelen OPML fájl: <opml> tag nem található VAGY nem találtak <outline> taget",
"MessageTaskOpmlParseNoneFound": "Nem található feed az OPML fájlban",
"MessageTaskScanItemsAdded": "{0} hozzáadva",
"MessageTaskScanItemsMissing": "{0} hiányzik",
"MessageTaskScanItemsUpdated": "{0} frissítve",
@@ -896,6 +941,8 @@
"NotificationOnBackupCompletedDescription": "A biztonsági mentés befejezésekor aktiválódik",
"NotificationOnBackupFailedDescription": "A biztonsági mentés sikertelensége esetén aktiválódik",
"NotificationOnEpisodeDownloadedDescription": "Egy podcast epizód automatikus letöltésekor aktiválódik",
"NotificationOnRSSFeedDisabledDescription": "Akkor lép működésbe, ha az automatikus epizódletöltés a túl sok sikertelen próbálkozás miatt letiltásra kerül",
"NotificationOnRSSFeedFailedDescription": "Akkor aktiválódik, ha az RSS feed kérés sikertelen az automatikus epizódletöltésnél",
"NotificationOnTestDescription": "Esemény az értesítési rendszer teszteléséhez",
"PlaceholderNewCollection": "Új gyűjtemény neve",
"PlaceholderNewFolderPath": "Új mappa útvonala",
@@ -940,8 +987,11 @@
"ToastBackupRestoreFailed": "A biztonsági mentés visszaállítása sikertelen",
"ToastBackupUploadFailed": "A biztonsági mentés feltöltése sikertelen",
"ToastBackupUploadSuccess": "Biztonsági mentés feltöltve",
"ToastBatchApplyDetailsToItemsSuccess": "Tételekre alkalmazott részletek",
"ToastBatchDeleteFailed": "A tömeges törlés nem sikerült",
"ToastBatchDeleteSuccess": "Sikeres tömeges törlés",
"ToastBatchQuickMatchFailed": "Tömeges Gyors Egyeztetés sikertelen!",
"ToastBatchQuickMatchStarted": "{0} könyv Tömeges Gyors Egyeztetése elkezdődött!",
"ToastBatchUpdateFailed": "Kötegelt frissítés sikertelen",
"ToastBatchUpdateSuccess": "Kötegelt frissítés sikeres",
"ToastBookmarkCreateFailed": "Könyvjelző létrehozása sikertelen",
@@ -950,9 +1000,12 @@
"ToastCachePurgeFailed": "A gyorsítótár törlése sikertelen",
"ToastCachePurgeSuccess": "A gyorsítótár sikeresen törölve",
"ToastChaptersHaveErrors": "A fejezetek hibákat tartalmaznak",
"ToastChaptersInvalidShiftAmountLast": "Érvénytelen eltolási érték. Az utolsó fejezet kezdési időpontja túlnyúlna a hangoskönyv időtartamán.",
"ToastChaptersInvalidShiftAmountStart": "Érvénytelen eltolási érték. Az első fejezet hossza nulla vagy negatív lenne, és a második fejezet felülírná. Növelje a második fejezet kezdő időtartamát.",
"ToastChaptersMustHaveTitles": "A fejezeteknek címekkel kell rendelkezniük",
"ToastChaptersRemoved": "Fejezetek eltávolítva",
"ToastChaptersUpdated": "Fejezetek frissítve",
"ToastCollectionItemsAddFailed": "A tétel(ek) hozzáadása gyűjteményhez sikertelen",
"ToastCollectionRemoveSuccess": "Gyűjtemény eltávolítva",
"ToastCollectionUpdateSuccess": "Gyűjtemény frissítve",
"ToastCoverUpdateFailed": "A borító frissítése nem sikerült",
@@ -967,13 +1020,17 @@
"ToastEncodeCancelFailed": "A kódolás törlése sikertelen volt",
"ToastEncodeCancelSucces": "Kódolás törölve",
"ToastEpisodeDownloadQueueClearFailed": "Nem sikerült törölni a várólistát",
"ToastEpisodeDownloadQueueClearSuccess": "Epizód letöltési várólista törölve",
"ToastEpisodeUpdateSuccess": "{0} epizód frissítve",
"ToastErrorCannotShare": "Ezen az eszközön nem lehet natívan megosztani",
"ToastFailedToCreate": "Sikertelen létrehozás",
"ToastFailedToDelete": "Sikertelen törlés",
"ToastFailedToLoadData": "Sikertelen adatbetöltés",
"ToastFailedToMatch": "Nem sikerült egyezőséget találni",
"ToastFailedToShare": "Nem sikerült megosztani",
"ToastFailedToUpdate": "Nem sikerült frissíteni",
"ToastInvalidImageUrl": "Érvénytelen a kép URL címe",
"ToastInvalidMaxEpisodesToDownload": "A letölthető epizódok száma érvénytelen",
"ToastInvalidUrl": "Érvénytelen URL",
"ToastItemCoverUpdateSuccess": "Elem borítója frissítve",
"ToastItemDeletedFailed": "Nem sikerült törölni az elemet",
@@ -999,6 +1056,7 @@
"ToastMustHaveAtLeastOnePath": "Legalább egy elérési útvonalnak kell lennie",
"ToastNameEmailRequired": "Név és e-mail cím megadása kötelező",
"ToastNameRequired": "A név megadása kötelező",
"ToastNewApiKeyUserError": "Ki kell választani egy felhasználót",
"ToastNewEpisodesFound": "{0} új epizód",
"ToastNewUserCreatedFailed": "Nem sikerült a fiókot létrehozni: „{0}”",
"ToastNewUserCreatedSuccess": "Új fiók létrehozva",
@@ -1011,8 +1069,11 @@
"ToastNoUpdatesNecessary": "Nincs szükség frissítésre",
"ToastNotificationCreateFailed": "Értesítés létrehozása sikertelen",
"ToastNotificationDeleteFailed": "Értesítés törlése sikertelen",
"ToastNotificationFailedMaximum": "A sikertelen kísérletek maximális száma >= 0 kell, hogy legyen",
"ToastNotificationQueueMaximum": "Az értesítési sor maximális száma >= 0 kell, hogy legyen",
"ToastNotificationSettingsUpdateSuccess": "Értesítési beállítások frissítve",
"ToastNotificationTestTriggerFailed": "Nem sikerült a tesztértesítést elindítani",
"ToastNotificationTestTriggerSuccess": "Kiváltott tesztértesítés",
"ToastNotificationUpdateSuccess": "Értesítés frissítve",
"ToastPlaylistCreateFailed": "Lejátszási lista létrehozása sikertelen",
"ToastPlaylistCreateSuccess": "Lejátszási lista létrehozva",
@@ -1020,6 +1081,7 @@
"ToastPlaylistUpdateSuccess": "Lejátszási lista frissítve",
"ToastPodcastCreateFailed": "Podcast létrehozása sikertelen",
"ToastPodcastCreateSuccess": "A podcast sikeresen létrehozva",
"ToastPodcastGetFeedFailed": "Nem sikerült podcast feedet kapni",
"ToastPodcastNoEpisodesInFeed": "Nincsenek epizódok az RSS hírcsatornában",
"ToastPodcastNoRssFeed": "A podcastnak nincs RSS-hírcsatornája",
"ToastProgressIsNotBeingSynced": "Az előrehaladás nem szinkronizálódik, a lejátszás újraindul",
@@ -1032,10 +1094,18 @@
"ToastRemoveFailed": "Sikertelen eltávolítás",
"ToastRemoveItemFromCollectionFailed": "Tétel eltávolítása a gyűjteményből sikertelen",
"ToastRemoveItemFromCollectionSuccess": "Tétel eltávolítva a gyűjteményből",
"ToastRemoveItemsWithIssuesFailed": "Nem sikerült eltávolítani a hibás könyvtárelemeket",
"ToastRemoveItemsWithIssuesSuccess": "Hibás könyvtárelemek eltávolítva",
"ToastRenameFailed": "Sikertelen átnevezés",
"ToastRescanFailed": "Sikertelen újrakeresés a következőnél: {0}",
"ToastRescanRemoved": "A teljes újrabeolvasás befejezve, elem eltávolítva",
"ToastRescanUpToDate": "A teljes újrabeolvasás befejezve, elem naprakész volt",
"ToastRescanUpdated": "A teljes újrabeolvasás befejezve, elem frissítve",
"ToastScanFailed": "Nem sikerült beolvasni a könyvtárelemet",
"ToastSelectAtLeastOneUser": "Válasszon legalább egy felhasználót",
"ToastSendEbookToDeviceFailed": "E-könyv küldése az eszközre sikertelen",
"ToastSendEbookToDeviceSuccess": "E-könyv elküldve az eszközre \"{0}\"",
"ToastSeriesSubmitFailedSameName": "Nem lehet két azonos nevű sorozatot hozzáadni",
"ToastSeriesUpdateFailed": "Sorozat frissítése sikertelen",
"ToastSeriesUpdateSuccess": "Sorozat frissítése sikeres",
"ToastServerSettingsUpdateSuccess": "Szerver beállítások frissítve",
@@ -1043,6 +1113,8 @@
"ToastSessionDeleteFailed": "Munkamenet törlése sikertelen",
"ToastSessionDeleteSuccess": "Munkamenet törölve",
"ToastSleepTimerDone": "Alvásidőzítő kész... zZzzZZz",
"ToastSlugMustChange": "A Slug érvénytelen karaktereket tartalmaz",
"ToastSlugRequired": "Slug szükséges",
"ToastSocketConnected": "Socket csatlakoztatva",
"ToastSocketDisconnected": "Socket lecsatlakoztatva",
"ToastSocketFailedToConnect": "A Socket csatlakoztatása sikertelen",
@@ -1050,9 +1122,14 @@
"ToastSortingPrefixesUpdateSuccess": "Rendezési előtagok frissítése ({0} elem)",
"ToastTitleRequired": "A cím kötelező",
"ToastUnknownError": "Ismeretlen hiba",
"ToastUnlinkOpenIdFailed": "Nem sikerült leválasztani a felhasználót az OpenID-ről",
"ToastUnlinkOpenIdSuccess": "Felhasználó leválasztva az OpenID-ről",
"ToastUploaderFilepathExistsError": "A \"{0}\" fájl elérési útja már létezik a szerveren",
"ToastUploaderItemExistsInSubdirectoryError": "A „{0}” elem a feltöltési útvonal egy alkönyvtárát használja.",
"ToastUserDeleteFailed": "Felhasználó törlése sikertelen",
"ToastUserDeleteSuccess": "Felhasználó törölve",
"ToastUserPasswordChangeSuccess": "Jelszó sikeresen megváltoztatva",
"ToastUserPasswordMismatch": "A jelszavak nem egyeznek",
"ToastUserPasswordMustChange": "Az új jelszó nem egyezik a régi jelszóval",
"ToastUserRootRequireName": "Egy root felhasználónevet kell megadnia"
}

View File

@@ -1,18 +1,19 @@
{
"ButtonAdd": "Aggiungi",
"ButtonAddApiKey": "Aggiungi chiave API",
"ButtonAddChapters": "Aggiungi Capitoli",
"ButtonAddDevice": "Aggiungi Dispositivo",
"ButtonAddLibrary": "Aggiungi Libreria",
"ButtonAddPodcasts": "Aggiungi Podcast",
"ButtonAddUser": "Aggiungi User",
"ButtonAddUser": "Aggiungi Utente",
"ButtonAddYourFirstLibrary": "Aggiungi la tua prima libreria",
"ButtonApply": "Applica",
"ButtonApplyChapters": "Applica",
"ButtonApplyChapters": "Applica Capitoli",
"ButtonAuthors": "Autori",
"ButtonBack": "Indietro",
"ButtonBatchEditPopulateFromExisting": "Popola da esistente",
"ButtonBatchEditPopulateMapDetails": "Inserisci i dettagli della mappa",
"ButtonBrowseForFolder": "Per Cartella",
"ButtonBrowseForFolder": "Sfoglia per Cartella",
"ButtonCancel": "Annulla",
"ButtonCancelEncode": "Ferma la codifica",
"ButtonChangeRootPassword": "Cambia la Password di root",
@@ -20,6 +21,7 @@
"ButtonChooseAFolder": "Seleziona la Cartella",
"ButtonChooseFiles": "Seleziona i File",
"ButtonClearFilter": "Elimina filtri",
"ButtonClose": "Chiudi",
"ButtonCloseFeed": "Chiudi flusso",
"ButtonCloseSession": "Chiudi la sessione aperta",
"ButtonCollections": "Raccolte",
@@ -514,7 +516,7 @@
"LabelPublishers": "Editori",
"LabelRSSFeedCustomOwnerEmail": "E-mail del proprietario personalizzato",
"LabelRSSFeedCustomOwnerName": "Nome del proprietario personalizzato",
"LabelRSSFeedOpen": "Flusso RSS aperto",
"LabelRSSFeedOpen": "Feed RSS aperto",
"LabelRSSFeedPreventIndexing": "Impedisci l'indicizzazione",
"LabelRSSFeedSlug": "Parole chiave del flusso RSS",
"LabelRSSFeedURL": "URL del flusso RSS",
@@ -708,6 +710,7 @@
"MessageAddToPlayerQueue": "Aggiungi alla coda di riproduzione",
"MessageAppriseDescription": "Per utilizzare questa funzione è necessario disporre di un'istanza di <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> in esecuzione o un'API che gestirà quelle stesse richieste. <br />L'API Url dovrebbe essere il percorso URL completo per inviare la notifica, ad esempio se la tua istanza API è servita cosi .<code>http://192.168.1.1:8337</code> Allora dovrai mettere <code>http://192.168.1.1:8337/notify</code>.",
"MessageAsinCheck": "Assicurati di utilizzare l'ASIN della regione Audible corretta, non di Amazon.",
"MessageAuthenticationOIDCChangesRestart": "Riavvia il tuo server dopo aver salvato per applicare le modifiche OIDC.",
"MessageBackupsDescription": "I backup includono utenti, progressi degli utenti, dettagli sugli elementi della libreria, impostazioni del server e immagini archiviate in <code>/metadata/items</code> & <code>/metadata/authors</code>. I backup non includono i file archiviati nelle cartelle della libreria.",
"MessageBackupsLocationEditNote": "Nota: l'aggiornamento della posizione di backup non sposterà o modificherà i backup esistenti",
"MessageBackupsLocationNoEditNote": "Nota: la posizione del backup viene impostata tramite una variabile di ambiente e non può essere modificata qui.",
@@ -855,6 +858,7 @@
"MessageScheduleRunEveryWeekdayAtTime": "Esegui ogni {0} alle {1}",
"MessageSearchResultsFor": "cerca risultati per",
"MessageSelected": "{0} selezionati",
"MessageSeriesSequenceCannotContainSpaces": "La sequenza della serie non può contenere spazi",
"MessageServerCouldNotBeReached": "Impossibile raggiungere il server",
"MessageSetChaptersFromTracksDescription": "Impostare i capitoli utilizzando ciascun file audio come capitolo e il titolo del capitolo come nome del file audio",
"MessageShareExpirationWillBe": "Scadrà tra <strong>{0}</strong>",
@@ -916,6 +920,8 @@
"NotificationOnBackupCompletedDescription": "Attivato al completamento di un backup",
"NotificationOnBackupFailedDescription": "Attivato quando un backup fallisce",
"NotificationOnEpisodeDownloadedDescription": "Attivato quando un episodio di podcast viene scaricato automaticamente",
"NotificationOnRSSFeedDisabledDescription": "Attivato quando i download automatici degli episodi vengono disabilitati a causa di troppi tentativi falliti",
"NotificationOnRSSFeedFailedDescription": "Attivato quando la richiesta del feed RSS per il download automatico di un episodio fallisce",
"NotificationOnTestDescription": "test il sistema di notifica",
"PlaceholderNewCollection": "Nome Nuova Raccolta",
"PlaceholderNewFolderPath": "Nuovo Percorso Cartella",

View File

@@ -1,15 +1,65 @@
{
"ButtonAdd": "追加",
"ButtonAddApiKey": "APIキーの追加",
"ButtonAddChapters": "チャプターの追加",
"ButtonAddDevice": "端末の追加",
"ButtonAddLibrary": "ライブラリーの追加",
"ButtonAddPodcasts": "ポッドキャストの追加",
"ButtonAddUser": "ユーザーの追加",
"ButtonAddYourFirstLibrary": "最初のライブラリーを追加",
"ButtonApply": "確定",
"ButtonApplyChapters": "チャプターを確定する",
"ButtonAuthors": "作者",
"ButtonBack": "戻る",
"ButtonCancel": "キャンセル",
"ButtonChangeRootPassword": "Rootのパスワードを変更する",
"ButtonChooseAFolder": "フォルダーを選ぶ",
"ButtonChooseFiles": "ファイルを選ぶ",
"ButtonClearFilter": "絞り込みを解除",
"ButtonClose": "閉じる",
"ButtonCollections": "コレクション",
"ButtonCreate": "作成",
"ButtonCreateBackup": "バックアップを作成する",
"ButtonDelete": "削除",
"ButtonDownloadQueue": "次に再生",
"ButtonEdit": "編集",
"ButtonEditChapters": "チャプターの編集",
"ButtonEditPodcast": "ポッドキャストの編集",
"ButtonEnable": "オンにする",
"ButtonHide": "非表示",
"ButtonHome": "ホーム",
"ButtonJumpBackward": "巻き戻し",
"ButtonJumpForward": "早送り",
"ButtonLibrary": "ライブラリー",
"ButtonLogout": "ログアウト",
"ButtonOk": "はい",
"ButtonPlay": "プレイ",
"ButtonPlaying": "プレイ中",
"ButtonPrevious": "先",
"ButtonQueueAddItem": "次に再生する",
"ButtonQueueRemoveItem": "次に再生から削除",
"ButtonReScan": "再スキャン",
"ButtonRead": "野村",
"ButtonReadLess": "閉じる",
"ButtonReadMore": "もっと見る",
"ButtonRefresh": "再読み込み",
"ButtonRemove": "削除",
"ButtonRemoveAll": "全て削除",
"ButtonRemoveAllLibraryItems": "ライブラリーの項目を全て削除",
"ButtonReset": "元に戻す",
"ButtonResetToDefault": "デフォルトに戻す",
"ButtonRestore": "復元",
"ButtonSave": "保存",
"ButtonSaveAndClose": "保存して閉じる",
"ButtonScan": "スキャン",
"ButtonScanLibrary": "ライブラリーをスキャン",
"ButtonScrollLeft": "左にスクロール",
"ButtonScrollRight": "右にスクロール",
"ButtonSearch": "検索",
"ButtonYes": "はい",
"HeaderPlayerSettings": "プレーヤーの設定",
"LabelBooks": "ほん",
"LabelContinueListening": "続きから聞く",
"LabelLanguage": "言語",
"LabelLanguages": "言語",
"LabelName": "名",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Toevoegen",
"ButtonAddApiKey": "API Key toevoegen",
"ButtonAddChapters": "Hoofdstukken toevoegen",
"ButtonAddDevice": "Toestel toevoegen",
"ButtonAddLibrary": "Bibliotheek toevoegen",
@@ -10,7 +11,7 @@
"ButtonApplyChapters": "Hoofdstukken toepassen",
"ButtonAuthors": "Auteurs",
"ButtonBack": "Terug",
"ButtonBatchEditPopulateFromExisting": "Vullen vanuit bestaande",
"ButtonBatchEditPopulateFromExisting": "Vul in met huidige",
"ButtonBatchEditPopulateMapDetails": "Kaartgegevens invullen",
"ButtonBrowseForFolder": "Bladeren naar map",
"ButtonCancel": "Annuleren",
@@ -20,11 +21,12 @@
"ButtonChooseAFolder": "Map kiezen",
"ButtonChooseFiles": "Bestanden kiezen",
"ButtonClearFilter": "Filter verwijderen",
"ButtonClose": "Sluiten",
"ButtonCloseFeed": "Feed sluiten",
"ButtonCloseSession": "Sluit Sessie",
"ButtonCollections": "Collecties",
"ButtonConfigureScanner": "Configureer scanner",
"ButtonCreate": "Creëer",
"ButtonCreate": "Aanmaken",
"ButtonCreateBackup": "Maak back-up",
"ButtonDelete": "Verwijder",
"ButtonDownloadQueue": "Wachtrij",
@@ -32,8 +34,8 @@
"ButtonEditChapters": "Hoofdstukken wijzigen",
"ButtonEditPodcast": "Podcast wijzigen",
"ButtonEnable": "Aanzetten",
"ButtonFireAndFail": "Fire and Fail",
"ButtonFireOnTest": "Fire onTest event",
"ButtonFireAndFail": "Uitvoeren en falen",
"ButtonFireOnTest": "Test-Event uitvoeren",
"ButtonForceReScan": "Forceer nieuwe scan",
"ButtonFullPath": "Volledig pad",
"ButtonHide": "Verberg",
@@ -43,9 +45,9 @@
"ButtonJumpForward": "Spring vooruit",
"ButtonLatest": "Meest recent",
"ButtonLibrary": "Bibliotheek",
"ButtonLogout": "Log uit",
"ButtonLogout": "Uitloggen",
"ButtonLookup": "Zoeken",
"ButtonManageTracks": "Beheer tracks",
"ButtonManageTracks": "Tracks beheren",
"ButtonMapChapterTitles": "Hoofdstuktitels mappen",
"ButtonMatchAllAuthors": "Alle auteurs matchen",
"ButtonMatchBooks": "Alle boeken matchen",
@@ -72,7 +74,7 @@
"ButtonQuickEmbedMetadata": "Snel Metadata Insluiten",
"ButtonQuickMatch": "Snelle match",
"ButtonReScan": "Nieuwe scan",
"ButtonRead": "Lees",
"ButtonRead": "Lezen",
"ButtonReadLess": "Lees minder",
"ButtonReadMore": "Lees meer",
"ButtonRefresh": "Verversen",
@@ -107,7 +109,7 @@
"ButtonUnlinkOpenId": "OpenID Ontkoppelen",
"ButtonUpload": "Upload",
"ButtonUploadBackup": "Upload back-up",
"ButtonUploadCover": "Upload cover",
"ButtonUploadCover": "Omslag uploaden",
"ButtonUploadOPMLFile": "Upload OPML-bestand",
"ButtonUserDelete": "Verwijder gebruiker {0}",
"ButtonUserEdit": "Wijzig gebruiker {0}",
@@ -119,6 +121,7 @@
"HeaderAccount": "Account",
"HeaderAddCustomMetadataProvider": "Aangepaste Metadataprovider Toevoegen",
"HeaderAdvanced": "Geavanceerd",
"HeaderApiKeys": "API Key",
"HeaderAppriseNotificationSettings": "Apprise-notificatie instellingen",
"HeaderAudioTracks": "Audiotracks",
"HeaderAudiobookTools": "Audioboekbestandbeheer tools",
@@ -162,6 +165,7 @@
"HeaderMetadataOrderOfPrecedence": "Metadata volgorde",
"HeaderMetadataToEmbed": "In te sluiten metadata",
"HeaderNewAccount": "Nieuwe account",
"HeaderNewApiKey": "Nieuwe API Key",
"HeaderNewLibrary": "Nieuwe bibliotheek",
"HeaderNotificationCreate": "Notificatie Aanmaken",
"HeaderNotificationUpdate": "Update Notificatie",
@@ -177,7 +181,8 @@
"HeaderPlaylist": "Afspeellijst",
"HeaderPlaylistItems": "Onderdelen in afspeellijst",
"HeaderPodcastsToAdd": "Toe te voegen podcasts",
"HeaderPreviewCover": "Preview cover",
"HeaderPresets": "Voorinstellingen",
"HeaderPreviewCover": "Voorbeeld omslag",
"HeaderRSSFeedGeneral": "RSS-details",
"HeaderRSSFeedIsOpen": "RSS-feed is open",
"HeaderRSSFeeds": "RSS-feeds",
@@ -205,6 +210,7 @@
"HeaderTableOfContents": "Inhoudsopgave",
"HeaderTools": "Gereedschap",
"HeaderUpdateAccount": "Account bijwerken",
"HeaderUpdateApiKey": "API Key updaten",
"HeaderUpdateAuthor": "Auteur bijwerken",
"HeaderUpdateDetails": "Details bijwerken",
"HeaderUpdateLibrary": "Bibliotheek bijwerken",
@@ -234,6 +240,10 @@
"LabelAllUsersExcludingGuests": "Alle gebruikers exclusief gasten",
"LabelAllUsersIncludingGuests": "Alle gebruikers inclusief gasten",
"LabelAlreadyInYourLibrary": "Reeds in je bibliotheek",
"LabelApiKeyCreated": "API Key \"{0}\" succesvol aangemaakt.",
"LabelApiKeyCreatedDescription": "Zorg ervoor dat je de API key nu kopieert, je kan deze later niet meer bekijken.",
"LabelApiKeyUser": "Uitvoeren namens de gebruiker",
"LabelApiKeyUserDescription": "Deze API key krijgt dezelfde rechten als de gebruiker waar deze zich tot voordoet. In de logs zullen de requests ook op naam van de gebruiker staan.",
"LabelApiToken": "API Token",
"LabelAppend": "Achteraan toevoegen",
"LabelAudioBitrate": "Audio Bitrate (b.v. 128k)",
@@ -284,7 +294,7 @@
"LabelContinueReading": "Verder lezen",
"LabelContinueSeries": "Doorgaan met Serie",
"LabelCover": "Omslag",
"LabelCoverImageURL": "Coverafbeelding URL",
"LabelCoverImageURL": "Omslagafbeelding-URL",
"LabelCoverProvider": "Omslag bron",
"LabelCreatedAt": "Gecreëerd op",
"LabelCronExpression": "Cron-uitdrukking",
@@ -311,7 +321,7 @@
"LabelDurationComparisonLonger": "({0} langer)",
"LabelDurationComparisonShorter": "({0} korter)",
"LabelDurationFound": "Gevonden duur:",
"LabelEbook": "Ebook",
"LabelEbook": "E-boek",
"LabelEbooks": "Eboeken",
"LabelEdit": "Wijzig",
"LabelEmail": "Email",
@@ -321,7 +331,7 @@
"LabelEmailSettingsSecure": "Veilig",
"LabelEmailSettingsSecureHelp": "Als 'waar', dan gebruikt de verbinding TLS om met de server te verbinden. Als 'onwaar', dan wordt TLS gebruikt als de server de STARTTLS-extensie ondersteunt. In de meeste gevallen kies je voor 'waar' verbindt met poort 465. Voo poort 587 of 25, laat op 'onwaar'. (van nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Test-adres",
"LabelEmbeddedCover": "Ingesloten cover",
"LabelEmbeddedCover": "Omslag in bestand",
"LabelEnable": "Inschakelen",
"LabelEncodingBackupLocation": "Er wordt een back-up van uw originele audiobestanden opgeslagen in:",
"LabelEncodingChaptersNotEmbedded": "Hoofdstukken zijn niet ingesloten in audioboeken met meerdere sporen.",
@@ -330,7 +340,7 @@
"LabelEncodingInfoEmbedded": "Metagegevens worden ingesloten in de audiotracks in uw audioboekmap.",
"LabelEncodingStartedNavigation": "Eenmaal de taak is gestart kan u weg navigeren van deze pagina.",
"LabelEncodingTimeWarning": "Encoding kan tot 30 minuten duren.",
"LabelEncodingWarningAdvancedSettings": "Waarschuwing: update deze instellingen niet tenzij u bekend bent met de coderingsopties van ffmpeg.",
"LabelEncodingWarningAdvancedSettings": "Waarschuwing: pas deze instellingen niet aan tenzij u bekend bent met de coderingsopties van ffmpeg.",
"LabelEncodingWatcherDisabled": "Als u de watcher hebt uitgeschakeld, moet u het audioboek daarna opnieuw scannen.",
"LabelEnd": "Einde",
"LabelEndOfChapter": "Einde van het Hoofdstuk",
@@ -345,6 +355,10 @@
"LabelExample": "Voorbeeld",
"LabelExpandSeries": "Serie Uitvouwen",
"LabelExpandSubSeries": "Subserie Uitvouwen",
"LabelExpired": "Verlopen",
"LabelExpiresAt": "Loopt af op",
"LabelExpiresInSeconds": "Loopt af in (seconds) seconden",
"LabelExpiresNever": "Nooit",
"LabelExplicit": "Expliciet",
"LabelExplicitChecked": "Expliciet (gechecked)",
"LabelExplicitUnchecked": "Niet Expliciet (niet gechecked)",
@@ -363,7 +377,7 @@
"LabelFolder": "Map",
"LabelFolders": "Mappen",
"LabelFontBold": "Vetgedrukt",
"LabelFontBoldness": "Font Boldness",
"LabelFontBoldness": "Lettertype Dikte",
"LabelFontFamily": "Lettertypefamilie",
"LabelFontItalic": "Cursief",
"LabelFontScale": "Lettertype schaal",
@@ -371,8 +385,8 @@
"LabelFormat": "Formaat",
"LabelFull": "Vol",
"LabelGenre": "Genre",
"LabelGenres": "Genres",
"LabelHardDeleteFile": "Hard-delete bestand",
"LabelGenres": "Categorieën",
"LabelHardDeleteFile": "Bestand permanent verwijderen",
"LabelHasEbook": "Heeft Ebook",
"LabelHasSupplementaryEbook": "Heeft aanvullend Ebook",
"LabelHideSubtitles": "Ondertitels Verstoppen",
@@ -394,6 +408,7 @@
"LabelIntervalEvery6Hours": "Iedere 6 uur",
"LabelIntervalEveryDay": "Iedere dag",
"LabelIntervalEveryHour": "Ieder uur",
"LabelIntervalEveryMinute": "Elke minuut",
"LabelInvert": "Omdraaien",
"LabelItem": "Onderdeel",
"LabelJumpBackwardAmount": "Terugspoelen hoeveelheid",
@@ -403,9 +418,10 @@
"LabelLanguages": "Talen",
"LabelLastBookAdded": "Laatst toegevoegde boek",
"LabelLastBookUpdated": "Laatst bijgewerkte boek",
"LabelLastProgressDate": "Laatste vooruitgang: {0}",
"LabelLastSeen": "Laatst gezien",
"LabelLastTime": "Laatste keer",
"LabelLastUpdate": "Laatste update",
"LabelLastUpdate": "Laatste wijziging",
"LabelLayout": "Layout",
"LabelLayoutSinglePage": "Enkele pagina",
"LabelLayoutSplitPage": "Gesplitste pagina",
@@ -415,6 +431,7 @@
"LabelLibraryFilterSublistEmpty": "Nee {0}",
"LabelLibraryItem": "Bibliotheekonderdeel",
"LabelLibraryName": "Bibliotheeknaam",
"LabelLibrarySortByProgress": "Voortuigang geüpdatet",
"LabelLimit": "Limiet",
"LabelLineSpacing": "Regelruimte",
"LabelListenAgain": "Opnieuw Beluisteren",
@@ -423,8 +440,9 @@
"LabelLogLevelWarn": "Waarschuwing",
"LabelLookForNewEpisodesAfterDate": "Zoek naar nieuwe afleveringen na deze datum",
"LabelLowestPriority": "Laagste Prioriteit",
"LabelMatchConfidence": "Vertrouwen",
"LabelMatchExistingUsersBy": "Bestaande gebruikers matchen op",
"LabelMatchExistingUsersByDescription": "Wordt gebruikt om bestaande gebruikers te verbinden. Zodra ze verbonden zijn, worden gebruikers gekoppeld aan een unieke id van uw SSO-provider.",
"LabelMatchExistingUsersByDescription": "Wordt gebruikt om bestaande gebruikers te verbinden. Zodra ze verbonden zijn, worden gebruikers gekoppeld aan een unieke id van uw SSO-provider",
"LabelMaxEpisodesToDownload": "Maximale # afleveringen om te downloaden. Gebruik 0 voor ongelimiteerd.",
"LabelMaxEpisodesToDownloadPerCheck": "Maximale # nieuwe afleveringen om te downloaden per check",
"LabelMaxEpisodesToKeep": "Maximale # afleveringen om te houden",
@@ -453,6 +471,7 @@
"LabelNewestEpisodes": "Nieuwste Afleveringen",
"LabelNextBackupDate": "Volgende back-up datum",
"LabelNextScheduledRun": "Volgende geplande run",
"LabelNoApiKeys": "Geen API keys",
"LabelNoCustomMetadataProviders": "Geen custom metadata bronnen",
"LabelNoEpisodesSelected": "Geen afleveringen geselecteerd",
"LabelNotFinished": "Niet Voltooid",
@@ -512,7 +531,7 @@
"LabelPublishers": "Uitgevers",
"LabelRSSFeedCustomOwnerEmail": "Aangepast e-mailadres eigenaar",
"LabelRSSFeedCustomOwnerName": "Aangepaste naam eigenaar",
"LabelRSSFeedOpen": "RSS-feed open",
"LabelRSSFeedOpen": "RSS Feed open",
"LabelRSSFeedPreventIndexing": "Voorkom indexering",
"LabelRSSFeedSlug": "RSS-feed slug",
"LabelRSSFeedURL": "RSS-feed URL",
@@ -529,7 +548,8 @@
"LabelReleaseDate": "Verschijningsdatum",
"LabelRemoveAllMetadataAbs": "Verwijder alle metadata.abs bestanden",
"LabelRemoveAllMetadataJson": "Verwijder alle metadata.json bestanden",
"LabelRemoveCover": "Verwijder cover",
"LabelRemoveAudibleBranding": "Verwijder Audible intro en outro uit hoofdstukken",
"LabelRemoveCover": "Omslag verwijderen",
"LabelRemoveMetadataFile": "Verwijder metadata bestanden in bibliotheek item folders",
"LabelRemoveMetadataFileHelp": "Verwijder alle metadata.json en metadata.abs bestanden in uw {0} folders.",
"LabelRowsPerPage": "Rijen per pagina",
@@ -541,6 +561,7 @@
"LabelSelectAll": "Alles selecteren",
"LabelSelectAllEpisodes": "Selecteer alle afleveringen",
"LabelSelectEpisodesShowing": "Selecteer {0} afleveringen laten zien",
"LabelSelectUser": "Gebruiker kiezen",
"LabelSelectUsers": "Selecteer gebruikers",
"LabelSendEbookToDevice": "Stuur ebook naar...",
"LabelSequence": "Sequentie",
@@ -557,14 +578,16 @@
"LabelSettingsAudiobooksOnlyHelp": "Deze instelling inschakelen zorgt ervoor dat ebook-bestanden genegeerd worden tenzij ze in een audiobook-map staan, in welk geval ze worden ingesteld als supplementaire ebooks",
"LabelSettingsBookshelfViewHelp": "Skeumorphisch design met houten planken",
"LabelSettingsChromecastSupport": "Chromecast ondersteuning",
"LabelSettingsDateFormat": "Datum format",
"LabelSettingsDateFormat": "Datumnotatie",
"LabelSettingsEnableWatcher": "Bibliotheken automatisch scannen op wijzigingen",
"LabelSettingsEnableWatcherForLibrary": "Bibliotheek automatisch scannen op wijzigingen",
"LabelSettingsEnableWatcherHelp": "Zorgt voor het automatisch toevoegen/bijwerken van onderdelen als bestandswijzigingen worden gedetecteerd. *Vereist herstarten van server",
"LabelSettingsEpubsAllowScriptedContent": "Sta scripted content toe in epubs",
"LabelSettingsEpubsAllowScriptedContentHelp": "Sta toe dat epub-bestanden scripts uitvoeren. Het wordt aanbevolen om deze instelling uitgeschakeld te houden, tenzij u de bron van de epub-bestanden vertrouwt.",
"LabelSettingsExperimentalFeatures": "Experimentele functies",
"LabelSettingsExperimentalFeaturesHelp": "Functies in ontwikkeling die je feedback en testing kunnen gebruiken. Klik om de Github-discussie te openen.",
"LabelSettingsFindCovers": "Zoek covers",
"LabelSettingsFindCoversHelp": "Als je audioboek geen ingesloten cover of cover in de map heeft, zal de scanner proberen een cover te vinden.<br>Opmerking: Dit zal de scan-duur verlengen",
"LabelSettingsFindCovers": "Omslagen zoeken",
"LabelSettingsFindCoversHelp": "Als je audioboek geen omslag in het bestand of in de map heeft, zal de scanner automatisch proberen een omslag te vinden.<br>Opmerking: Dit kan de scantijd verlengen",
"LabelSettingsHideSingleBookSeries": "Verberg series met een enkel boek",
"LabelSettingsHideSingleBookSeriesHelp": "Series die slechts een enkel boek bevatten worden verborgen op de seriespagina en de homepagina-planken.",
"LabelSettingsHomePageBookshelfView": "Boekenplank-view voor homepagina",
@@ -574,18 +597,18 @@
"LabelSettingsLibraryMarkAsFinishedWhen": "Markeer media item wanneer voltooid",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Sla eedere boeken in Serie Verderzetten over",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "De Continue Series home page shelf toont het eerste boek dat nog niet is begonnen in series waarvan er minstens één is voltooid en er geen boeken in uitvoering zijn. Als u deze instelling inschakelt, wordt de serie voortgezet vanaf het boek dat het verst is voltooid in plaats van het eerste boek dat nog niet is begonnen.",
"LabelSettingsParseSubtitles": "Parseer subtitel",
"LabelSettingsParseSubtitles": "Subtitel afleiden uit foldernaam",
"LabelSettingsParseSubtitlesHelp": "Haal subtitels uit mapnaam van audioboek.<br>Subtitel moet gescheiden zijn met \" - \"<br>b.v. \"Boektitel - Een Subtitel Hier\" heeft als subtitel \"Een Subtitel Hier\"",
"LabelSettingsPreferMatchedMetadata": "Prefereer gematchte metadata",
"LabelSettingsPreferMatchedMetadata": "Geef voorkeur aan gematchte metadata",
"LabelSettingsPreferMatchedMetadataHelp": "Gematchte data zal onderdeeldetails overschrijven bij gebruik van Quick Match. Standaard vult Quick Match uitsluitend ontbrekende details aan.",
"LabelSettingsSkipMatchingBooksWithASIN": "Sla matchen van boeken over die al over een ASIN beschikken",
"LabelSettingsSkipMatchingBooksWithISBN": "Sla matchen van boeken over die al over een ISBN beschikken",
"LabelSettingsSortingIgnorePrefixes": "Negeer voorvoegsels bij sorteren",
"LabelSettingsSortingIgnorePrefixesHelp": "b.v. voor voorvoegsel \"The\" wordt titel \"The Title\" dan gesorteerd als \"Title, The\"",
"LabelSettingsSquareBookCovers": "Gebruik vierkante boekcovers",
"LabelSettingsSquareBookCoversHelp": "Prefereer gebruik van vierkante covers boven standaard 1.6:1 boekcovers",
"LabelSettingsStoreCoversWithItem": "Bewaar covers bij onderdeel",
"LabelSettingsStoreCoversWithItemHelp": "Standaard worden covers bewaard in /metadata/items, door deze instelling in te schakelen zullen covers in de map van je bibliotheekonderdeel bewaard worden. Slechts een bestand genaamd \"cover\" zal worden bewaard",
"LabelSettingsSquareBookCovers": "Gebruik vierkante boekomslagen",
"LabelSettingsSquareBookCoversHelp": "Gebruik vierkante boekomslagen in plaats van standaard 1,6:1",
"LabelSettingsStoreCoversWithItem": "Bewaar omslagen bij onderdeel",
"LabelSettingsStoreCoversWithItemHelp": "Omslagen worden standaard in /metadata/items opgeslagen. Bij inschakelen worden ze in de map van het bibliotheekitem zelf opgeslagen. Slechts een bestand genaamd \"cover\" zal worden bewaard",
"LabelSettingsStoreMetadataWithItem": "Bewaar metadata bij onderdeel",
"LabelSettingsStoreMetadataWithItemHelp": "Standaard worden metadata-bestanden bewaard in /metadata/items, door deze instelling in te schakelen zullen metadata bestanden in de map van je bibliotheekonderdeel bewaard worden",
"LabelSettingsTimeFormat": "Tijdformat",
@@ -601,6 +624,7 @@
"LabelSlug": "Slak",
"LabelSortAscending": "Oplopend",
"LabelSortDescending": "Aflopend",
"LabelSortPubDate": "Sorteer Pub Datum",
"LabelStart": "Start",
"LabelStartTime": "Starttijd",
"LabelStarted": "Gestart",
@@ -630,10 +654,11 @@
"LabelTextEditorBulletedList": "Opgesomde lijst",
"LabelTextEditorLink": "Link",
"LabelTextEditorNumberedList": "Genummerde lijst",
"LabelTextEditorUnlink": "Unlink",
"LabelTextEditorUnlink": "Ontkoppelen",
"LabelTheme": "Thema",
"LabelThemeDark": "Donker",
"LabelThemeLight": "Licht",
"LabelThemeSepia": "Sepia",
"LabelTimeBase": "Tijdsbasis",
"LabelTimeDurationXHours": "{0} Uren",
"LabelTimeDurationXMinutes": "{0} minuten",
@@ -646,12 +671,12 @@
"LabelTimeToShift": "Tijd op te schuiven in seconden",
"LabelTitle": "Titel",
"LabelToolsEmbedMetadata": "Metadata insluiten",
"LabelToolsEmbedMetadataDescription": "Metadata insluiten in audiobestanden, inclusief coverafbeelding en hoofdstukken.",
"LabelToolsEmbedMetadataDescription": "Metadata insluiten in audiobestanden, inclusief omslagafbeelding en hoofdstukken.",
"LabelToolsM4bEncoder": "M4B Encoder",
"LabelToolsMakeM4b": "Maak M4B-audioboekbestand",
"LabelToolsMakeM4bDescription": "Genereer een .M4B-audioboekbestand met ingesloten metadata, coverafbeelding en hoofdstukken.",
"LabelToolsMakeM4bDescription": "Genereer een .M4B-audioboekbestand met ingesloten metadata, omslagafbeelding en hoofdstukken.",
"LabelToolsSplitM4b": "Splitst M4B in MP3's",
"LabelToolsSplitM4bDescription": "Maak MP3's van een M4B, gesplitst per hoofdstuk met ingesloten metadata, coverafbeelding en hoofdstukken.",
"LabelToolsSplitM4bDescription": "Maak MP3's van een M4B, gesplitst per hoofdstuk met ingesloten metadata, omslagafbeelding en hoofdstukken.",
"LabelTotalDuration": "Totale duur",
"LabelTotalTimeListened": "Totale tijd geluisterd",
"LabelTrackFromFilename": "Track vanuit bestandsnaam",
@@ -666,8 +691,8 @@
"LabelUndo": "Ongedaan maken",
"LabelUnknown": "Onbekend",
"LabelUnknownPublishDate": "Onbekende uitgeefdatum",
"LabelUpdateCover": "Cover bijwerken",
"LabelUpdateCoverHelp": "Sta overschrijven van bestaande covers toe voor de geselecteerde boeken wanneer een match is gevonden",
"LabelUpdateCover": "Omslag bijwerken",
"LabelUpdateCoverHelp": "Sta overschrijven van bestaande omslagen toe voor de geselecteerde boeken wanneer een match is gevonden",
"LabelUpdateDetails": "Details bijwerken",
"LabelUpdateDetailsHelp": "Sta overschrijven van bestaande details toe voor de geselecteerde boeken wanneer een match is gevonden",
"LabelUpdatedAt": "Bijgewerkt op",
@@ -701,13 +726,17 @@
"LabelYourProgress": "Je voortgang",
"MessageAddToPlayerQueue": "Toevoegen aan wachtrij",
"MessageAppriseDescription": "Om deze functie te gebruiken heb je een draaiende instantie van <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> nodig of een api die dezelfde requests afhandelt. <br />De Apprise API Url moet het volledige URL-pad zijn om de notificatie te verzenden, b.v., als je API-instantie draait op <code>http://192.168.1.1:8337</code> dan zou je <code>http://192.168.1.1:8337/notify</code> gebruiken.",
"MessageAsinCheck": "Zorg ervoor dat u de ASIN van de juiste Audible-regio gebruikt, niet die van Amazon.",
"MessageAuthenticationLegacyTokenWarning": "API tokens zijn verouderd en worden in de toekomst niet meer ondersteund. Gebruik inplaats daarvan <a href=\"/config/api-keys\">API keys</a> .",
"MessageAuthenticationOIDCChangesRestart": "Start uw server opnieuw op nadat u het opslaan hebt uitgevoerd, om de OIDC-wijzigingen toe te passen.",
"MessageAuthenticationSecurityMessage": "Authenticatie is verbeterd omwille van veiligheid. Alle gebruikers moeten opnieuw inloggen.",
"MessageBackupsDescription": "Back-ups omvatten gebruikers, gebruikers' voortgang, bibliotheekonderdeeldetails, serverinstellingen en afbeeldingen bewaard in <code>/metadata/items</code> & <code>/metadata/authors</code>. Back-ups <strong>bevatten niet</strong> de bestanden bewaard in je bibliotheekmappen.",
"MessageBackupsLocationEditNote": "Let op: het bijwerken van de back-uplocatie zal bestaande back-ups niet verplaatsen of wijzigen",
"MessageBackupsLocationNoEditNote": "Let op: De back-uplocatie wordt ingesteld via een omgevingsvariabele en kan hier niet worden gewijzigd.",
"MessageBackupsLocationPathEmpty": "Backup locatie pad kan niet leeg zijn",
"MessageBatchEditPopulateMapDetailsAllHelp": "Vul actieve velden in met data van alle items. Velden met meerdere waarden zullen worden samengevoegd",
"MessageBatchEditPopulateMapDetailsItemHelp": "Vul actieve folder detail velden met de data van dit item",
"MessageBatchQuickMatchDescription": "Quick Match zal proberen ontbrekende covers en metadata voor de geselecteerde onderdelen te matchten. Schakel de opties hieronder in om Quick Match toe te staan bestaande covers en/of metadata te overschrijven.",
"MessageBatchQuickMatchDescription": "Quick Match probeert ontbrekende omslagen en metadata toe te voegen aan de geselecteerde items. Schakel de opties hieronder in om Quick Match bestaande omslagen en/of metadata te laten overschrijven.",
"MessageBookshelfNoCollections": "Je hebt nog geen collecties gemaakt",
"MessageBookshelfNoCollectionsHelp": "Collecties zijn publiekelijk. Alle gebruikers met toegang tot de bibliotheek kunnen ze zien.",
"MessageBookshelfNoRSSFeeds": "Geen RSS-feeds geopend",
@@ -719,8 +748,10 @@
"MessageChapterErrorStartGteDuration": "Ongeldig: starttijd moet kleiner zijn dan duur van audioboek",
"MessageChapterErrorStartLtPrev": "Ongeldig: starttijd moet be groter zijn dan of equal aan starttijd van vorig hoofdstuk",
"MessageChapterStartIsAfter": "Start van hoofdstuk is na het einde van je audioboek",
"MessageChaptersNotFound": "Hoofdstukken niet gevonden",
"MessageCheckingCron": "Cron aan het checken...",
"MessageConfirmCloseFeed": "Ben je zeker dat je deze feed wil sluiten?",
"MessageConfirmDeleteApiKey": "Weet je zeker dat je deze API key \"{0}\" wil verwijderen?",
"MessageConfirmDeleteBackup": "Weet je zeker dat je de backup voor {0} wil verwijderen?",
"MessageConfirmDeleteDevice": "Ben je zeker dat je e-reader apparaat \"{0}\" wil verwijderen?",
"MessageConfirmDeleteFile": "Dit verwijdert het bestand uit het bestandssysteem. Weet je het zeker?",
@@ -748,11 +779,12 @@
"MessageConfirmRemoveAuthor": "Weet je zeker dat je auteur \"{0}\" wil verwijderen?",
"MessageConfirmRemoveCollection": "Weet je zeker dat je de collectie \"{0}\" wil verwijderen?",
"MessageConfirmRemoveEpisode": "Weet je zeker dat je de aflevering \"{0}\" wil verwijderen?",
"MessageConfirmRemoveEpisodeNote": "Let op: Het audiobestand wordt niet verwijderd, tenzij je Bestand permanent verwijderen inschakelt",
"MessageConfirmRemoveEpisodes": "Weet je zeker dat je {0} afleveringen wil verwijderen?",
"MessageConfirmRemoveListeningSessions": "Weet je zeker dat je {0} luistersessies wilt verwijderen?",
"MessageConfirmRemoveMetadataFiles": "Bent u zeker dat u alle metadata wil verwijderen. {0} bestanden in uw bibliotheel item folders?",
"MessageConfirmRemoveNarrator": "Weet je zeker dat je verteller \"{0}\" wil verwijderen?",
"MessageConfirmRemovePlaylist": "Weet je zeker dat je je afspeellijst \"{0}\" wil verwijderen?",
"MessageConfirmRemovePlaylist": "Weet je zeker dat je afspeellijst \"{0}\" wil verwijderen?",
"MessageConfirmRenameGenre": "Weet je zeker dat je genre \"{0}\" wil hernoemen naar \"{1}\" voor alle onderdelen?",
"MessageConfirmRenameGenreMergeNote": "Opmerking: Dit genre bestaat al, dus zullen ze worden samengevoegd.",
"MessageConfirmRenameGenreWarning": "Waarschuwing! Een gelijknamig genre met ander hoofdlettergebruik bestaat al: \"{0}\".",
@@ -775,8 +807,9 @@
"MessageForceReScanDescription": "zal alle bestanden opnieuw scannen als een verse scan. Audiobestanden ID3-tags, OPF-bestanden en textbestanden zullen als nieuw worden gescand.",
"MessageImportantNotice": "Belangrijke opmerking!",
"MessageInsertChapterBelow": "Hoofdstuk hieronder invoegen",
"MessageItemsSelected": "{0} onderdelen geselecteerd",
"MessageItemsUpdated": "{0} onderdelen bijgewerkt",
"MessageInvalidAsin": "Ongeldige ASIN",
"MessageItemsSelected": "{0} items geselecteerd",
"MessageItemsUpdated": "{0} items bijgewerkt",
"MessageJoinUsOn": "Doe mee op",
"MessageLoading": "Aan het laden...",
"MessageLoadingFolders": "Mappen aan het laden...",
@@ -788,14 +821,14 @@
"MessageMarkAllEpisodesNotFinished": "Markeer alle afleveringen als niet voltooid",
"MessageMarkAsFinished": "Markeer als Voltooid",
"MessageMarkAsNotFinished": "Markeer als Niet Voltooid",
"MessageMatchBooksDescription": "zal proberen boeken in de bibliotheek te matchen met een boek uit de geselecteerde bron en lege details en coverafbeelding te vullen. Overschrijft details niet.",
"MessageMatchBooksDescription": "zal proberen boeken in de bibliotheek te koppelen aan een boek uit de geselecteerde bron en ontbrekende gegevens en een omslag toe te voegen. Overschrijft geen bestaande gegevens.",
"MessageNoAudioTracks": "Geen audiotracks",
"MessageNoAuthors": "Geen auteurs",
"MessageNoBackups": "Geen back-ups",
"MessageNoBookmarks": "Geen boekwijzers",
"MessageNoChapters": "Geen hoofdstukken",
"MessageNoCollections": "Geen collecties",
"MessageNoCoversFound": "Geen covers gevonden",
"MessageNoCoversFound": "Geen omslagen gevonden",
"MessageNoDescription": "Geen beschrijving",
"MessageNoDevices": "Geen Apparaten",
"MessageNoDownloadsInProgress": "Geen downloads bezig op dit moment",
@@ -808,7 +841,7 @@
"MessageNoItems": "Geen onderdelen",
"MessageNoItemsFound": "Geen onderdelen gevonden",
"MessageNoListeningSessions": "Geen luistersessies",
"MessageNoLogs": "Geen logs",
"MessageNoLogs": "Geen logbestanden",
"MessageNoMediaProgress": "Geen mediavoortgang",
"MessageNoNotifications": "Geen notificaties",
"MessageNoPodcastFeed": "Ongeldige podcast: Geen Feed",
@@ -833,7 +866,7 @@
"MessageQuickEmbedInProgress": "Snelle inbedding in uitvoering",
"MessageQuickEmbedQueue": "In de wachtrij voor snelle insluiting ({0} in wachtrij)",
"MessageQuickMatchAllEpisodes": "Alle Afleveringen Snel Matchen",
"MessageQuickMatchDescription": "Vul lege onderdeeldetails & cover met eerste matchresultaat van '{0}'. Overschrijft geen details tenzij 'Prefereer gematchte metadata' serverinstelling is ingeschakeld.",
"MessageQuickMatchDescription": "Vult ontbrekende gegevens & omslag met eerste matchresultaat van '{0}'. Overschrijft gegevens alleen als de serverinstelling Geef voorkeur aan gematchte metadata is ingeschakeld.",
"MessageRemoveChapter": "Verwijder hoofdstuk",
"MessageRemoveEpisodes": "Verwijder {0} aflevering(en)",
"MessageRemoveFromPlayerQueue": "Verwijder uit afspeelwachtrij",
@@ -841,10 +874,12 @@
"MessageReportBugsAndContribute": "Rapporteer bugs, vraag functionaliteiten aan en draag bij op",
"MessageResetChaptersConfirm": "Weet je zeker dat je de hoofdstukken wil resetten en de wijzigingen die je gemaakt hebt ongedaan wil maken?",
"MessageRestoreBackupConfirm": "Weet je zeker dat je wil herstellen met behulp van de back-up gemaakt op",
"MessageRestoreBackupWarning": "Herstellen met een back-up zal de volledige database in /config en de covers in /metadata/items & /metadata/authors overschrijven.<br /><br />Back-ups wijzigen geen bestanden in je bibliotheekmappen. Als je de serverinstelling gebruikt om covers en metadata in je bibliotheekmappen te bewaren dan worden deze niet geback-upt of overschreven.<br /><br />Alle clients die van je server gebruik maken zullen automatisch worden ververst.",
"MessageRestoreBackupWarning": "Een back-up herstellen zal de volledige database in /config en de omslagen in /metadata/items & /metadata/authors overschrijven.<br /><br />Back-ups wijzigen geen bestanden in je bibliotheekmappen. Als je de serverinstelling gebruikt om omslagen en metadata in je bibliotheekmappen te bewaren dan worden deze niet geback-upt of overschreven.<br /><br />Alle apparaten die je server gebruiken, worden automatisch ververst.",
"MessageScheduleLibraryScanNote": "Voor de meeste gebruikers is het raadzaam om deze functie uitgeschakeld te laten en de folder watcher-instelling ingeschakeld te houden. De folder watcher detecteert automatisch wijzigingen in uw bibliotheekmappen. De folder watcher werkt niet voor elk bestandssysteem (zoals NFS), dus geplande bibliotheekscans kunnen in plaats daarvan worden gebruikt.",
"MessageScheduleRunEveryWeekdayAtTime": "Elke {0} uitvoeren op {1}",
"MessageSearchResultsFor": "Zoekresultaten voor",
"MessageSelected": "{0} geselecteerd",
"MessageSeriesSequenceCannotContainSpaces": "Serievolgorde mag geen spaties bevatten",
"MessageServerCouldNotBeReached": "Server niet bereikbaar",
"MessageSetChaptersFromTracksDescription": "Stel hoofdstukken in met ieder audiobestand als een hoofdstuk en de audiobestandsnaam als hoofdstuktitel",
"MessageShareExpirationWillBe": "Vervaldatum is <strong>{0}</strong>",
@@ -906,6 +941,8 @@
"NotificationOnBackupCompletedDescription": "Wordt geactiveerd wanneer een back-up is voltooid",
"NotificationOnBackupFailedDescription": "Wordt geactiveerd wanneer een back-up mislukt",
"NotificationOnEpisodeDownloadedDescription": "Wordt geactiveerd wanneer een podcastaflevering automatisch wordt gedownload",
"NotificationOnRSSFeedDisabledDescription": "Wordt geactiveerd wanneer automatische afleveringsdownloads zijn uitgeschakeld vanwege te veel mislukte pogingen",
"NotificationOnRSSFeedFailedDescription": "Getriggerd wanneer de RSS feed aanvraag faalt voor een automatische aflevering download",
"NotificationOnTestDescription": "Event voor het testen van het notificatiesysteem",
"PlaceholderNewCollection": "Nieuwe naam collectie",
"PlaceholderNewFolderPath": "Nieuwe locatie map",
@@ -950,6 +987,7 @@
"ToastBackupRestoreFailed": "Herstellen back-up mislukt",
"ToastBackupUploadFailed": "Uploaden back-up mislukt",
"ToastBackupUploadSuccess": "Back-up geüpload",
"ToastBatchApplyDetailsToItemsSuccess": "Details toegepast op items",
"ToastBatchDeleteFailed": "Batch verwijderen mislukt",
"ToastBatchDeleteSuccess": "Batch verwijderen gelukt",
"ToastBatchQuickMatchFailed": "Batch Snel Vergelijken mislukt!",
@@ -962,13 +1000,15 @@
"ToastCachePurgeFailed": "Cache wissen is mislukt",
"ToastCachePurgeSuccess": "Cache succesvol verwijderd",
"ToastChaptersHaveErrors": "Hoofdstukken bevatten fouten",
"ToastChaptersInvalidShiftAmountLast": "Ongeldige shift-tijd. De starttijd van het laatste hoofdstuk zou langer zijn dan de duur van dit audioboek.",
"ToastChaptersInvalidShiftAmountStart": "Ongeldige shift-lengte. Het eerste hoofdstuk zou nul of een negatieve lengte hebben en zou worden overschreven door het tweede hoofdstuk. Verleng de startduur van het tweede hoofdstuk.",
"ToastChaptersMustHaveTitles": "Hoofdstukken moeten titels hebben",
"ToastChaptersRemoved": "Hoofdstukken verwijderd",
"ToastChaptersUpdated": "Hoofdstukken bijgewerkt",
"ToastCollectionItemsAddFailed": "Item(s) toegevoegd aan collectie mislukt",
"ToastCollectionRemoveSuccess": "Collectie verwijderd",
"ToastCollectionUpdateSuccess": "Collectie bijgewerkt",
"ToastCoverUpdateFailed": "Cover update mislukt",
"ToastCoverUpdateFailed": "Omslag bijwerken mislukt",
"ToastDateTimeInvalidOrIncomplete": "Datum en tijd ongeldig of onvolledig",
"ToastDeleteFileFailed": "Bestand verwijderen mislukt",
"ToastDeleteFileSuccess": "Bestand verwijderd",
@@ -983,6 +1023,8 @@
"ToastEpisodeDownloadQueueClearSuccess": "Aflevering download-wachtrij geleegt",
"ToastEpisodeUpdateSuccess": "{0} afleveringen bijgewerkt",
"ToastErrorCannotShare": "Kan niet native delen op dit apparaat",
"ToastFailedToCreate": "Fout tijdens creëren",
"ToastFailedToDelete": "Fout tijdens verwijderen",
"ToastFailedToLoadData": "Data laden mislukt",
"ToastFailedToMatch": "Match mislukt",
"ToastFailedToShare": "Delen mislukt",
@@ -990,7 +1032,7 @@
"ToastInvalidImageUrl": "Ongeldige afbeeldings-URL",
"ToastInvalidMaxEpisodesToDownload": "Ongeldig maximum aantal afleveringen om te downloaden",
"ToastInvalidUrl": "Ongeldige URL",
"ToastItemCoverUpdateSuccess": "Cover onderdeel bijgewerkt",
"ToastItemCoverUpdateSuccess": "Omslag bijgewerkt",
"ToastItemDeletedFailed": "Item verwijderen mislukt",
"ToastItemDeletedSuccess": "Verwijderd item",
"ToastItemDetailsUpdateSuccess": "Details onderdeel bijgewerkt",
@@ -1014,6 +1056,7 @@
"ToastMustHaveAtLeastOnePath": "Moet ten minste een pad hebben",
"ToastNameEmailRequired": "Naam en email zijn vereist",
"ToastNameRequired": "Naam is vereist",
"ToastNewApiKeyUserError": "Selecteer een gebruiker",
"ToastNewEpisodesFound": "{0} nieuwe afleveringen gevonden",
"ToastNewUserCreatedFailed": "Account: \"{0}\" aanmaken mislukt",
"ToastNewUserCreatedSuccess": "Nieuw account aangemaakt",
@@ -1062,6 +1105,7 @@
"ToastSelectAtLeastOneUser": "Selecteer ten minste een gebruiker",
"ToastSendEbookToDeviceFailed": "Ebook naar apparaat sturen mislukt",
"ToastSendEbookToDeviceSuccess": "Ebook verstuurd naar apparaat \"{0}\"",
"ToastSeriesSubmitFailedSameName": "Kan niet twee series met dezelfde naam toevoegen",
"ToastSeriesUpdateFailed": "Bijwerken serie mislukt",
"ToastSeriesUpdateSuccess": "Bijwerken serie gelukt",
"ToastServerSettingsUpdateSuccess": "Server instellingen bijgewerkt",
@@ -1080,6 +1124,8 @@
"ToastUnknownError": "Onbekende fout",
"ToastUnlinkOpenIdFailed": "Gebruiker ontkoppelen van OpenID mislukt",
"ToastUnlinkOpenIdSuccess": "Gebruiker ontkoppeld van OpenID",
"ToastUploaderFilepathExistsError": "Bestandspad \"{0}\" bestaat al op de server",
"ToastUploaderItemExistsInSubdirectoryError": "Item \"{0}\" gebruikt een submap van het uploadpad.",
"ToastUserDeleteFailed": "Verwijderen gebruiker mislukt",
"ToastUserDeleteSuccess": "Gebruiker verwijderd",
"ToastUserPasswordChangeSuccess": "Wachtwoord succesvol gewijzigd",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Legg til",
"ButtonAddApiKey": "Legg til API-nøkkel",
"ButtonAddChapters": "Legg til kapittel",
"ButtonAddDevice": "Legg til enhet",
"ButtonAddLibrary": "Legg til bibliotek",
@@ -8,8 +9,10 @@
"ButtonAddYourFirstLibrary": "Legg til ditt første bibliotek",
"ButtonApply": "Bruk",
"ButtonApplyChapters": "Bruk kapittel",
"ButtonAuthors": "Forfatter",
"ButtonAuthors": "Forfattere",
"ButtonBack": "Tilbake",
"ButtonBatchEditPopulateFromExisting": "Opprett fra eksisterende",
"ButtonBatchEditPopulateMapDetails": "Legg til detaljer",
"ButtonBrowseForFolder": "Bla gjennom mappe",
"ButtonCancel": "Avbryt",
"ButtonCancelEncode": "Avbryt konvertering",
@@ -18,6 +21,7 @@
"ButtonChooseAFolder": "Velg mappe",
"ButtonChooseFiles": "Velg filer",
"ButtonClearFilter": "Fjern filter",
"ButtonClose": "Lukk",
"ButtonCloseFeed": "Lukk Feed",
"ButtonCloseSession": "Lukk åpen økt",
"ButtonCollections": "Samlinger",
@@ -117,6 +121,7 @@
"HeaderAccount": "Konto",
"HeaderAddCustomMetadataProvider": "Legg til egendefinert metadata tilbyder",
"HeaderAdvanced": "Avansert",
"HeaderApiKeys": "API-nøkler",
"HeaderAppriseNotificationSettings": "Apprise varslingsinstillinger",
"HeaderAudioTracks": "Lydspor",
"HeaderAudiobookTools": "Lydbok Filbehandlingsverktøy",
@@ -160,6 +165,7 @@
"HeaderMetadataOrderOfPrecedence": "Prioriteringsrekkefølge for metadata",
"HeaderMetadataToEmbed": "Metadata å bake inn",
"HeaderNewAccount": "Ny konto",
"HeaderNewApiKey": "Ny API-nøkkel",
"HeaderNewLibrary": "Ny bibliotek",
"HeaderNotificationCreate": "Opprett varsling",
"HeaderNotificationUpdate": "Oppdater varsling",
@@ -175,6 +181,7 @@
"HeaderPlaylist": "Spilleliste",
"HeaderPlaylistItems": "Spillelisteelement",
"HeaderPodcastsToAdd": "Podcaster å legge til",
"HeaderPresets": "Forhåndsinnstillinger",
"HeaderPreviewCover": "Forhåndsvis omslag",
"HeaderRSSFeedGeneral": "RSS Detailer",
"HeaderRSSFeedIsOpen": "RSS Feed er åpen",
@@ -192,6 +199,7 @@
"HeaderSettingsExperimental": "Eksperimentelle funksjoner",
"HeaderSettingsGeneral": "Generell",
"HeaderSettingsScanner": "Skanner",
"HeaderSettingsSecurity": "Sikkerhet",
"HeaderSettingsWebClient": "Webklient",
"HeaderSleepTimer": "Sove timer",
"HeaderStatsLargestItems": "Største enheter",
@@ -203,6 +211,7 @@
"HeaderTableOfContents": "Innholdsfortegnelse",
"HeaderTools": "Verktøy",
"HeaderUpdateAccount": "Oppdater konto",
"HeaderUpdateApiKey": "Oppdater API-nøkkel",
"HeaderUpdateAuthor": "Oppdater forfatter",
"HeaderUpdateDetails": "Oppdater detaljer",
"HeaderUpdateLibrary": "Oppdater bibliotek",
@@ -217,6 +226,7 @@
"LabelAccountTypeAdmin": "Administrator",
"LabelAccountTypeGuest": "Gjest",
"LabelAccountTypeUser": "Bruker",
"LabelActivities": "Aktiviteter",
"LabelActivity": "Aktivitet",
"LabelAddToCollection": "Legg til i samling",
"LabelAddToCollectionBatch": "Legg {0} bøker til samling",
@@ -226,10 +236,15 @@
"LabelAddedDate": "La til {0}",
"LabelAdminUsersOnly": "Kun administratorer",
"LabelAll": "Alle",
"LabelAllEpisodesDownloaded": "Alle nedlastede episoder",
"LabelAllUsers": "Alle brukere",
"LabelAllUsersExcludingGuests": "Alle brukere bortsett fra gjester",
"LabelAllUsersIncludingGuests": "Alle brukere inkludert gjester",
"LabelAlreadyInYourLibrary": "Allerede i biblioteket",
"LabelApiKeyCreated": "API-nøkkel \"{0}\" ble opprettet.",
"LabelApiKeyCreatedDescription": "Husk å kopiere API-nøkkelen nå siden du ikke kan se den igjen senere.",
"LabelApiKeyUser": "Handle på vegne av bruker",
"LabelApiKeyUserDescription": "Denne API-nøkkelen vil ha de samme tillatelsene som brukeren den handler på vegne av. I loggene vil dette se ut som om brukeren selv foretok forespørselen.",
"LabelApiToken": "API token",
"LabelAppend": "Legge til",
"LabelAudioBitrate": "Bitrate for lyd (f.eks. 128k)",
@@ -249,7 +264,7 @@
"LabelBackToUser": "Tilbake til bruker",
"LabelBackupAudioFiles": "Sikkerhetskopier lydfiler",
"LabelBackupLocation": "Mappe for sikkerhetskopiering",
"LabelBackupsEnableAutomaticBackups": "Aktiver automatisk sikkerhetskopi",
"LabelBackupsEnableAutomaticBackups": "Automatiske sikkerhetskopier",
"LabelBackupsEnableAutomaticBackupsHelp": "Sikkerhetskopier lagret under /metadata/backups",
"LabelBackupsMaxBackupSize": "Maksimal størrelse for sikkerhetskopi (i GB) (0 for ubegrenset)",
"LabelBackupsMaxBackupSizeHelp": "For å forhindre feilkonfigurasjon, vil sikkerhetskopier mislykkes hvis de oveskride konfigurert størrelse.",
@@ -279,8 +294,10 @@
"LabelContinueListening": "Fortsett lytting",
"LabelContinueReading": "Fortsett lesing",
"LabelContinueSeries": "Fortsett serier",
"LabelCorsAllowed": "Tillate CORS-opprinnelser",
"LabelCover": "Omslag",
"LabelCoverImageURL": "Omslagsbilde URL",
"LabelCoverProvider": "Tilbyder av omslagsbilde",
"LabelCreatedAt": "Dato opprettet",
"LabelCronExpression": "Cron uttrykk",
"LabelCurrent": "Nåværende",
@@ -340,6 +357,10 @@
"LabelExample": "Eksempel",
"LabelExpandSeries": "Vis serie",
"LabelExpandSubSeries": "Vis underserie",
"LabelExpired": "Utløpt",
"LabelExpiresAt": "Utløper",
"LabelExpiresInSeconds": "Utløper om (sekunder)",
"LabelExpiresNever": "Aldri",
"LabelExplicit": "Eksplisitt",
"LabelExplicitChecked": "Eksplisitt (avhuket)",
"LabelExplicitUnchecked": "Ikke eksplisitt (ikke avhuket)",
@@ -369,7 +390,7 @@
"LabelGenres": "Sjangre",
"LabelHardDeleteFile": "Tving sletting av fil",
"LabelHasEbook": "Har e-bok",
"LabelHasSupplementaryEbook": "Har komplimentær e-bok",
"LabelHasSupplementaryEbook": "Har supplerende e-bok",
"LabelHideSubtitles": "Skjul undertitler",
"LabelHighestPriority": "Høyeste prioritet",
"LabelHost": "Tjener",
@@ -389,6 +410,7 @@
"LabelIntervalEvery6Hours": "Hver 6. timer",
"LabelIntervalEveryDay": "Hver dag",
"LabelIntervalEveryHour": "Hver time",
"LabelIntervalEveryMinute": "Hvert minutt",
"LabelInvert": "Inverter",
"LabelItem": "Enhet",
"LabelJumpBackwardAmount": "Hopp bakover med",
@@ -398,10 +420,11 @@
"LabelLanguages": "Språk",
"LabelLastBookAdded": "Siste bok lagt til",
"LabelLastBookUpdated": "Siste bok oppdatert",
"LabelLastProgressDate": "Siste fremgang: {0}",
"LabelLastSeen": "Sist sett",
"LabelLastTime": "Siste tid",
"LabelLastUpdate": "Siste oppdatering",
"LabelLayout": "Oppsett",
"LabelLayout": "Utseende",
"LabelLayoutSinglePage": "Enkeltside",
"LabelLayoutSplitPage": "Del side",
"LabelLess": "Mindre",
@@ -410,6 +433,7 @@
"LabelLibraryFilterSublistEmpty": "Ingen {0}",
"LabelLibraryItem": "Bibliotek enhet",
"LabelLibraryName": "Bibliotek navn",
"LabelLibrarySortByProgress": "Fremgang oppdatert",
"LabelLimit": "Begrensning",
"LabelLineSpacing": "Linjemellomrom",
"LabelListenAgain": "Lytt igjen",
@@ -463,7 +487,8 @@
"LabelNotificationsMaxQueueSize": "Maksimalt antall varslinger i kø",
"LabelNotificationsMaxQueueSizeHelp": "Hendelser er begrenset til avfyre én gang per sekund. Hendelser blir ignorert om køen er full. Dette forhindrer overflod av varslinger.",
"LabelNumberOfBooks": "Antall bøker",
"LabelNumberOfEpisodes": "Antall episoder",
"LabelNumberOfEpisodes": "# episoder",
"LabelOpenIDAdvancedPermsClaimDescription": "Navnet på OpenID claim'et som inneholder avanserte tilganger for brukerhandlinger i applikasjonen som vil brukes for ikke-administratorroller (<b>hvis konfigurert</b>). Hvis claim'et mangler fra responsen, nektes tilgang til ABS. Hvis en enkelt opsjon mangler, blir behandlet som <code>false</code>. Påse at identitetstilbyderens claim stemmer overens med den forventede strukturen:",
"LabelOpenIDClaims": "La følge valg være tomme for å slå av avanserte gruppe og tillatelser. Gruppen \"Bruker\" vil da også automatisk legges til.",
"LabelOpenRSSFeed": "Åpne RSS Feed",
"LabelOverwrite": "Overskriv",
@@ -504,11 +529,11 @@
"LabelPublishers": "Utgivere",
"LabelRSSFeedCustomOwnerEmail": "Tilpasset eier e-post",
"LabelRSSFeedCustomOwnerName": "Tilpasset eier Navn",
"LabelRSSFeedOpen": "RSS Feed åpne",
"LabelRSSFeedOpen": "RSS-strøm åpen",
"LabelRSSFeedPreventIndexing": "Forhindre indeksering",
"LabelRSSFeedSlug": "RSS-feed ID",
"LabelRSSFeedURL": "RSS-feed URL",
"LabelRandomly": "Tilfeldig",
"LabelRandomly": "Tilfeldighet",
"LabelReAddSeriesToContinueListening": "Legg til igjen til \"Fortsett å lytte\"",
"LabelRead": "Les",
"LabelReadAgain": "Les igjen",
@@ -521,6 +546,7 @@
"LabelReleaseDate": "Utgivelsesdato",
"LabelRemoveAllMetadataAbs": "Fjern alle metadata.abs filer",
"LabelRemoveAllMetadataJson": "Fjern alle metadata.json filer",
"LabelRemoveAudibleBranding": "Fjern Audible inn- og utledning fra kapitler",
"LabelRemoveCover": "Fjern omslag",
"LabelRemoveMetadataFile": "Fjern metadata-filer fra biblioteks-mapper",
"LabelRemoveMetadataFileHelp": "Fjern alle metadata.json og metadata.abs i alle {0} mappene.",
@@ -550,6 +576,8 @@
"LabelSettingsBookshelfViewHelp": "Skeuomorf design med hyller av ved",
"LabelSettingsChromecastSupport": "Chromecast støtte",
"LabelSettingsDateFormat": "Dato Format",
"LabelSettingsEnableWatcher": "Skann biblioteker automatisk for endringer",
"LabelSettingsEnableWatcherForLibrary": "Skann bibliotek automatisk for endringer",
"LabelSettingsEnableWatcherHelp": "Aktiverer automatisk opprettelse/oppdatering av enheter når filendringer er oppdaget. *Krever restart av server*",
"LabelSettingsEpubsAllowScriptedContent": "Tillat scripting i innholdet i ebub-bøker",
"LabelSettingsEpubsAllowScriptedContentHelp": "Tillat epub-filer å kjøre script. Det er anbefalt å slå av denne innstillingen med mindre du stoler på kilden til epub-filene.",
@@ -593,6 +621,7 @@
"LabelSlug": "Slug",
"LabelSortAscending": "Stigende",
"LabelSortDescending": "Synkende",
"LabelSortPubDate": "Sorter etter publiseringsdato",
"LabelStart": "Start",
"LabelStartTime": "Start Tid",
"LabelStarted": "Startet",
@@ -614,7 +643,7 @@
"LabelStatsWeekListening": "Uker lyttet",
"LabelSubtitle": "Undertittel",
"LabelSupportedFileTypes": "Støttede filtyper",
"LabelTag": "Tag",
"LabelTag": "Merke",
"LabelTags": "Tagger",
"LabelTagsAccessibleToUser": "Tagger tilgjengelig for bruker",
"LabelTagsNotAccessibleToUser": "Tagger ikke tilgjengelig for bruker",
@@ -693,6 +722,8 @@
"LabelYourProgress": "Din fremgang",
"MessageAddToPlayerQueue": "Legg til i kø",
"MessageAppriseDescription": "For å bruke denne funksjonen trenger du en instans av <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> kjørende eller et API som håndterer disse forespørslene. <br />Apprise API URL skal være hele URL-en til varslingen, f.eks., hvis din API-instans er på <code>http://192.168.1.1:8337</code> så skal du bruke <code>http://192.168.1.1:8337/notify</code>.",
"MessageAsinCheck": "Påse at du bruker ASIN fra den riktige Audible-regionen, ikke Amazon.",
"MessageAuthenticationOIDCChangesRestart": "Etter å ha lagret, start serveren din på nytt for at OIDC-endringene skal tre i kraft.",
"MessageBackupsDescription": "Sikkerhetskopier inkluderer, brukerfremgang, detaljer om bibliotekgjenstander, tjener instillinger og bilder lagret under <code>/metadata/items</code> og <code>/metadata/authors</code>. Sikkerhetskopier <strong>vil ikke</strong> inkludere filer som er lagret i bibliotek mappene.",
"MessageBackupsLocationEditNote": "Viktig: Endring av mappen for sikkerhetskopi hverken endrer eller flytter eksisterende sikkerhetskopier!",
"MessageBackupsLocationNoEditNote": "NB: Mappen for sikkerhetskopi settes i en miljøvariabel og kan ikke endres her.",
@@ -817,7 +848,7 @@
"MessagePlaylistCreateFromCollection": "Lag spilleliste fra samling",
"MessagePleaseWait": "Vennligst vent...",
"MessagePodcastHasNoRSSFeedForMatching": "Podcast har ingen RSS feed url til bruk av sammenligning",
"MessagePodcastSearchField": "Skriv inn søkeord eller RSS-feed URL",
"MessagePodcastSearchField": "Skriv inn søkeord eller URL til en RSS-strøm",
"MessageQuickEmbedInProgress": "Hurtiginnbygging pågår",
"MessageQuickEmbedQueue": "Kø for hurtiginnbygging ({0} i kø)",
"MessageQuickMatchAllEpisodes": "Kjapp matching av alle episoder",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Dodaj",
"ButtonAddApiKey": "Dodaj klucz API",
"ButtonAddChapters": "Dodaj rozdziały",
"ButtonAddDevice": "Dodaj urządzenie",
"ButtonAddLibrary": "Dodaj bibliotekę",
@@ -20,6 +21,7 @@
"ButtonChooseAFolder": "Wybierz folder",
"ButtonChooseFiles": "Wybierz pliki",
"ButtonClearFilter": "Wyczyść filtr",
"ButtonClose": "Zamknij",
"ButtonCloseFeed": "Zamknij kanał",
"ButtonCloseSession": "Zamknij otwartą sesję",
"ButtonCollections": "Kolekcje",
@@ -119,6 +121,7 @@
"HeaderAccount": "Konto",
"HeaderAddCustomMetadataProvider": "Dodaj niestandardowego dostawcę metadanych",
"HeaderAdvanced": "Zaawansowane",
"HeaderApiKeys": "Klucze API",
"HeaderAppriseNotificationSettings": "Ustawienia powiadomień Apprise",
"HeaderAudioTracks": "Ścieżki audio",
"HeaderAudiobookTools": "Narzędzia do zarządzania audiobookami",
@@ -162,6 +165,7 @@
"HeaderMetadataOrderOfPrecedence": "Kolejność metadanych",
"HeaderMetadataToEmbed": "Metadane do osadzenia",
"HeaderNewAccount": "Nowe konto",
"HeaderNewApiKey": "Nowy klucz API",
"HeaderNewLibrary": "Nowa biblioteka",
"HeaderNotificationCreate": "Utwórz powiadomienie",
"HeaderNotificationUpdate": "Zaktualizuj powiadomienie",
@@ -206,6 +210,7 @@
"HeaderTableOfContents": "Spis treści",
"HeaderTools": "Narzędzia",
"HeaderUpdateAccount": "Zaktualizuj konto",
"HeaderUpdateApiKey": "Aktualizuj klucz API",
"HeaderUpdateAuthor": "Zaktualizuj autorów",
"HeaderUpdateDetails": "Zaktualizuj szczegóły",
"HeaderUpdateLibrary": "Zaktualizuj bibliotekę",
@@ -235,6 +240,8 @@
"LabelAllUsersExcludingGuests": "Wszyscy użytkownicy z wyłączeniem gości",
"LabelAllUsersIncludingGuests": "Wszyscy użytkownicy, łącznie z gośćmi",
"LabelAlreadyInYourLibrary": "Już istnieje w twojej bibliotece",
"LabelApiKeyCreated": "Klucz API \"{0}\" został pomyślnie utworzony.",
"LabelApiKeyCreatedDescription": "Pamiętaj o skopiowaniu klucza API, ponieważ nie będziesz już mógł go zobaczyć.",
"LabelApiToken": "API Token",
"LabelAppend": "Dołącz",
"LabelAudioBitrate": "Audio Bitrate (np. 128k)",
@@ -306,6 +313,7 @@
"LabelDiscover": "Odkrywaj",
"LabelDownload": "Pobierz",
"LabelDownloadNEpisodes": "Ściąganie {0} odcinków",
"LabelDownloadable": "Do pobrania",
"LabelDuration": "Czas trwania",
"LabelDurationComparisonExactMatch": "(dokładne dopasowanie)",
"LabelDurationComparisonLonger": "({0} dłużej)",
@@ -324,15 +332,29 @@
"LabelEmbeddedCover": "Wbudowana okładka",
"LabelEnable": "Włącz",
"LabelEncodingBackupLocation": "Kopia zapasowa twoich oryginalnych plików audio będzie się znajdować w:",
"LabelEncodingChaptersNotEmbedded": "W audiobookach wielościeżkowych rozdziały nie są osadzone.",
"LabelEncodingClearItemCache": "Pamiętaj o okresowym czyszczeniu pamięci podręcznej elementów.",
"LabelEncodingFinishedM4B": "Ukończony plik M4B zostanie umieszczony w folderze audiobooka pod adresem:",
"LabelEncodingInfoEmbedded": "Metadane zostaną osadzone w ścieżkach audio w folderze z audiobookiem.",
"LabelEncodingStartedNavigation": "Po uruchomieniu zadania możesz opuścić tę stronę.",
"LabelEncodingTimeWarning": "Konwersja może potrwać do 30 minut.",
"LabelEncodingWarningAdvancedSettings": "Ostrzeżenie: Nie aktualizuj tych ustawień, jeśli nie jesteś zaznajomiony ze sposobem działania ffmpeg i opcji konwersji.",
"LabelEncodingWatcherDisabled": "Jeśli monitorowanie folderów jest wyłączone, należy ponownie przeskanować audiobooka.",
"LabelEnd": "Zakończ",
"LabelEndOfChapter": "Koniec rozdziału",
"LabelEpisode": "Odcinek",
"LabelEpisodeNotLinkedToRssFeed": "Odcinek nie jest powiązany z kanałem RSS",
"LabelEpisodeNumber": "Odcinek #{0}",
"LabelEpisodeTitle": "Tytuł odcinka",
"LabelEpisodeType": "Typ odcinka",
"LabelEpisodeUrlFromRssFeed": "Adres URL odcinka z kanału RSS",
"LabelEpisodes": "Epizody",
"LabelEpisodic": "Epizodyczny",
"LabelExample": "Przykład",
"LabelExpandSeries": "Rozwiń serie",
"LabelExpandSubSeries": "Rozwiń podserie",
"LabelExpiresInSeconds": "Wygasa za (sekund)",
"LabelExpiresNever": "Nigdy",
"LabelExplicit": "Nieprzyzwoite",
"LabelExplicitChecked": "Nieprzyzwoite (sprawdzone)",
"LabelExplicitUnchecked": "Przyzwoite (niesprawdzone)",
@@ -357,6 +379,7 @@
"LabelFontScale": "Rozmiar czcionki",
"LabelFontStrikethrough": "Przekreślony",
"LabelFormat": "Format",
"LabelFull": "Pełny",
"LabelGenre": "Gatunek",
"LabelGenres": "Gatunki",
"LabelHardDeleteFile": "Usuń trwale plik",
@@ -381,6 +404,7 @@
"LabelIntervalEvery6Hours": "Co 6 godzin",
"LabelIntervalEveryDay": "Każdego dnia",
"LabelIntervalEveryHour": "Każdej godziny",
"LabelIntervalEveryMinute": "Co minutę",
"LabelInvert": "Inversja",
"LabelItem": "Pozycja",
"LabelJumpBackwardAmount": "Przeskocz do tyłu o:",
@@ -390,6 +414,7 @@
"LabelLanguages": "Języki",
"LabelLastBookAdded": "Ostatnio dodana książka",
"LabelLastBookUpdated": "Ostatnio modyfikowana książka",
"LabelLastProgressDate": "Ostatni postęp: {0}",
"LabelLastSeen": "Ostatnio widziany",
"LabelLastTime": "Ostatni czas",
"LabelLastUpdate": "Ostatnia aktualizacja",
@@ -402,6 +427,7 @@
"LabelLibraryFilterSublistEmpty": "Brak {0}",
"LabelLibraryItem": "Element biblioteki",
"LabelLibraryName": "Nazwa biblioteki",
"LabelLibrarySortByProgress": "Postęp zaktualizowany",
"LabelLimit": "Limit",
"LabelLineSpacing": "Odstęp między wierszami",
"LabelListenAgain": "Słuchaj ponownie",
@@ -412,6 +438,10 @@
"LabelLowestPriority": "Najniższy priorytet",
"LabelMatchExistingUsersBy": "Dopasuje istniejących użytkowników poprzez",
"LabelMatchExistingUsersByDescription": "Służy do łączenia istniejących użytkowników. Po połączeniu użytkownicy zostaną dopasowani za pomocą unikalnego identyfikatora od dostawcy SSO",
"LabelMaxEpisodesToDownload": "Maksymalna liczba odcinków do pobrania. Użyj 0, aby wyłączyć ograniczenie.",
"LabelMaxEpisodesToDownloadPerCheck": "Maksymalna liczba nowych odcinków do pobrania na jedno sprawdzenie",
"LabelMaxEpisodesToKeep": "Maksymalna liczba odcinków do zachowania",
"LabelMaxEpisodesToKeepHelp": "Wartość 0 wyłącza maksymalny limit. Po automatycznym pobraniu nowego odcinka, najstarszy odcinek zostanie usunięty, jeśli masz ich więcej niż X. Spowoduje to usunięcie tylko 1 odcinka na nowe pobieranie.",
"LabelMediaPlayer": "Odtwarzacz",
"LabelMediaType": "Typ mediów",
"LabelMetaTag": "Tag",
@@ -424,6 +454,7 @@
"LabelMissingEbook": "Nie posiada ebooka",
"LabelMissingSupplementaryEbook": "Nie posiada dodatkowego ebooka",
"LabelMobileRedirectURIs": "Dozwolone URI przekierowań mobilnych",
"LabelMobileRedirectURIsDescription": "To jest biała lista prawidłowych adresów URI przekierowań dla aplikacji mobilnych. Domyślny adres to <code>audiobookshelf://oauth</code>, który można usunąć lub dodać inne adresy URI w celu integracji z aplikacjami innych firm. Użycie gwiazdki (<code>*</code>) jako jedynego wpisu zezwala na dowolny URI.",
"LabelMore": "Więcej",
"LabelMoreInfo": "Więcej informacji",
"LabelName": "Nazwa",
@@ -435,6 +466,7 @@
"LabelNewestEpisodes": "Najnowsze odcinki",
"LabelNextBackupDate": "Data kolejnej kopii zapasowej",
"LabelNextScheduledRun": "Następne uruchomienie",
"LabelNoApiKeys": "Brak kluczy API",
"LabelNoCustomMetadataProviders": "Brak niestandardowych dostawców metadanych",
"LabelNoEpisodesSelected": "Nie wybrano żadnych odcinków",
"LabelNotFinished": "Nieukończone",
@@ -451,14 +483,18 @@
"LabelNotificationsMaxQueueSizeHelp": "Zdarzenia są ograniczone do 1 na sekundę. Zdarzenia będą ignorowane jeśli kolejka ma maksymalny rozmiar. Zapobiega to spamowaniu powiadomieniami.",
"LabelNumberOfBooks": "Liczba książek",
"LabelNumberOfEpisodes": "# Odcinków",
"LabelOpenIDAdvancedPermsClaimDescription": "Nazwa deklaracji OpenID zawierającej zaawansowane uprawnienia do działań użytkownika w aplikacji, które będą miały zastosowanie do ról innych niż administracyjne (<b>jeśli skonfigurowano</b>). Jeśli deklaracja nie zostanie uwzględniona w odpowiedzi, dostęp do ABS zostanie zablokowany. Brak jednej opcji zostanie uznany za <code>fałsz</code>. Upewnij się, że deklaracja dostawcy tożsamości jest zgodna z oczekiwaną strukturą:",
"LabelOpenIDClaims": "Pozostaw poniższe opcje puste, aby wyłączyć zaawansowane przypisywanie grup i uprawnień. Automatycznie zostanie przypisana grupa „Użytkownik”.",
"LabelOpenRSSFeed": "Otwórz kanał RSS",
"LabelOverwrite": "Nadpisz",
"LabelPaginationPageXOfY": "Strona {0} z {1}",
"LabelPassword": "Hasło",
"LabelPath": "Ścieżka",
"LabelPermanent": "Stałe",
"LabelPermissionsAccessAllLibraries": "Ma dostęp do wszystkich bibliotek",
"LabelPermissionsAccessAllTags": "Ma dostęp do wszystkich tagów",
"LabelPermissionsAccessExplicitContent": "Ma dostęp do treści oznacznych jako nieprzyzwoite",
"LabelPermissionsCreateEreader": "Możliwość stworzenia czytnika e-booków",
"LabelPermissionsDelete": "Ma możliwość usuwania",
"LabelPermissionsDownload": "Ma możliwość pobierania",
"LabelPermissionsUpdate": "Ma możliwość aktualizowania",
@@ -466,20 +502,32 @@
"LabelPersonalYearReview": "Podsumowanie twojego roku ({0})",
"LabelPhotoPathURL": "Scieżka/URL do zdjęcia",
"LabelPlayMethod": "Metoda odtwarzania",
"LabelPlaybackRateIncrementDecrement": "Zwiększenie/zmniejszenie szybkości odtwarzania",
"LabelPlayerChapterNumberMarker": "{0} z {1}",
"LabelPlaylists": "Listy odtwarzania",
"LabelPodcast": "Podcast",
"LabelPodcastSearchRegion": "Obszar wyszukiwania podcastów",
"LabelPodcastType": "Typ podcastu",
"LabelPodcasts": "Podcasty",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Ignorowane prefiksy (wielkość liter nie ma znaczenia)",
"LabelPreventIndexing": "Zapobiega indeksowaniu przez iTunes i Google",
"LabelPrimaryEbook": "Główny ebook",
"LabelProgress": "Postęp",
"LabelProvider": "Dostawca",
"LabelProviderAuthorizationValue": "Wartość nagłówka autoryzacji",
"LabelPubDate": "Data publikacji",
"LabelPublishYear": "Rok publikacji",
"LabelPublishedDate": "Opublikowano {0}",
"LabelPublishedDecade": "Dekada publikacji",
"LabelPublishedDecades": "Dekada publikacji",
"LabelPublisher": "Wydawca",
"LabelPublishers": "Wydawcy",
"LabelRSSFeedOpen": "RSS Feed otwarty",
"LabelRSSFeedCustomOwnerEmail": "Email właściciela",
"LabelRSSFeedCustomOwnerName": "Nazwa właściciela",
"LabelRSSFeedOpen": "Otwarty Kanał RSS",
"LabelRSSFeedPreventIndexing": "Zapobiegaj indeksowaniu",
"LabelRSSFeedSlug": "Numer Kanału RSS",
"LabelRSSFeedURL": "URL kanały RSS",
"LabelRandomly": "Losowo",
"LabelReAddSeriesToContinueListening": "Ponownie Dodaj Serię do sekcji Kontunuuj Odtwarzanie",
@@ -490,15 +538,24 @@
"LabelRecentlyAdded": "Niedawno dodane",
"LabelRecommended": "Polecane",
"LabelRedo": "Wycofaj",
"LabelRegion": "Region",
"LabelReleaseDate": "Data wydania",
"LabelRemoveAllMetadataAbs": "Usuń wszystkie pliki metadata.abs",
"LabelRemoveAllMetadataJson": "Usuń wszystkie pliki metadata.json",
"LabelRemoveAudibleBranding": "Usuń Audible intro i outro z rozdziałów",
"LabelRemoveCover": "Usuń okładkę",
"LabelRemoveMetadataFile": "Usuń pliki metadanych z folderów biblioteki",
"LabelRemoveMetadataFileHelp": "Usuń wszystkie pliki metadata.json i metadata.abs z {0} folderów.",
"LabelRowsPerPage": "Wierszy na stronę",
"LabelSearchTerm": "Wyszukiwanie frazy",
"LabelSearchTitle": "Wyszukaj tytuł",
"LabelSearchTitleOrASIN": "Szukaj tytuł lub ASIN",
"LabelSeason": "Sezon",
"LabelSeasonNumber": "Sezon #{0}",
"LabelSelectAll": "Wybierz wszystko",
"LabelSelectAllEpisodes": "Wybierz wszystkie odcinki",
"LabelSelectEpisodesShowing": "Wybierz {0} wyświetlanych odcinków",
"LabelSelectUser": "Wybierz użytkownika",
"LabelSelectUsers": "Wybór użytkowników",
"LabelSendEbookToDevice": "Wyślij ebook do...",
"LabelSequence": "Kolejność",
@@ -508,11 +565,14 @@
"LabelServerYearReview": "Podsumowanie serwera w roku ({0})",
"LabelSetEbookAsPrimary": "Ustaw jako pierwszy",
"LabelSetEbookAsSupplementary": "Ustaw jako dodatkowy",
"LabelSettingsAllowIframe": "Zezwól na osadzanie w ramce iframe",
"LabelSettingsAudiobooksOnly": "Wyłącznie audiobooki",
"LabelSettingsAudiobooksOnlyHelp": "Włączenie tej funkcji spowoduje ignorowanie plików ebooków, chyba że znajdują się wewnątrz folderu audiobooka kiedy to będą pokazywane jako dodatkowe ebooki",
"LabelSettingsBookshelfViewHelp": "Widok półki z książkami",
"LabelSettingsChromecastSupport": "Wsparcie Chromecast",
"LabelSettingsDateFormat": "Format daty",
"LabelSettingsEnableWatcher": "Automatyczne skanowanie bibliotek w poszukiwaniu zmian",
"LabelSettingsEnableWatcherForLibrary": "Automatyczne skanowanie biblioteki w poszukiwaniu zmian",
"LabelSettingsEnableWatcherHelp": "Włącza automatyczne dodawanie/aktualizację pozycji gdy wykryte zostaną zmiany w plikach. Wymaga restartu serwera",
"LabelSettingsEpubsAllowScriptedContent": "Zezwalanie na skrypty w plikach epub",
"LabelSettingsEpubsAllowScriptedContentHelp": "Zezwala plikom epub na wykonywanie skryptów. Zaleca się mieć to ustawienie wyłączone, chyba że ma się zaufanie do źródła plików epub.",
@@ -524,8 +584,13 @@
"LabelSettingsHideSingleBookSeriesHelp": "Serie, które posiadają tylko jedną książkę, nie będą pokazywane na stronie z seriami i na stronie domowej z półkami.",
"LabelSettingsHomePageBookshelfView": "Widok półki z książkami na stronie głównej",
"LabelSettingsLibraryBookshelfView": "Widok półki z książkami na stronie biblioteki",
"LabelSettingsLibraryMarkAsFinishedPercentComplete": "Procent ukończenia jest większy niż",
"LabelSettingsLibraryMarkAsFinishedTimeRemaining": "Pozostały czas jest mniejszy niż (sekund)",
"LabelSettingsLibraryMarkAsFinishedWhen": "Oznacz element multimedialny jako ukończony, gdy",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Pomiń poprzednie książki przy kontynuacji serii",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Strona „Kontynuuj serię” wyświetla pierwszą nierozpoczętą książkę z serii, w której ukończono co najmniej jedną książkę i żadnej nie rozpoczęto. Włączając to ustawienie, będziesz kontynuować serię po przeczytaniu ostatniej książki, a nie od pierwszej nierozpoczętej książki z serii.",
"LabelSettingsParseSubtitles": "Przetwarzaj podtytuły",
"LabelSettingsParseSubtitlesHelp": "Opcja pozwala na pobranie podtytułu z nazwy folderu z audiobookiem. <br>Podtytuł musi być rozdzielony za pomocą separatora \" - \"<br>Przykład: \"Book Title - A Subtitle Here\" podtytuł \"A Subtitle Here\"",
"LabelSettingsParseSubtitlesHelp": "Opcja pozwala na pobranie podtytułu z nazwy folderu z audiobookiem. <br>Podtytuł musi być rozdzielony za pomocą separatora \" - \"<br>Przykład: \"Tytuł książki - Podtytuł\" podtytuł \"Podtytuł\"",
"LabelSettingsPreferMatchedMetadata": "Preferowanie dopasowanych metadanych",
"LabelSettingsPreferMatchedMetadataHelp": "Dopasowane dane będą miały pierwszeństwo nad szczegółami pozycji podczas używania Szybkiego dopasowania. Domyślnie Szybkie dopasowanie uzupełnia tylko brakujące szczegóły.",
"LabelSettingsSkipMatchingBooksWithASIN": "Pomiń dopasowanie książek, które już mają ASIN",
@@ -547,6 +612,9 @@
"LabelShowSubtitles": "Pokaż Napisy",
"LabelSize": "Rozmiar",
"LabelSleepTimer": "Wyłącznik czasowy",
"LabelSortAscending": "Rosnąco",
"LabelSortDescending": "Malejąco",
"LabelSortPubDate": "Sortuj według daty publikacji",
"LabelStart": "Rozpocznij",
"LabelStartTime": "Czas rozpoczęcia",
"LabelStarted": "Rozpoczęty",
@@ -568,14 +636,21 @@
"LabelStatsWeekListening": "Tydzień słuchania",
"LabelSubtitle": "Podtytuł",
"LabelSupportedFileTypes": "Obsługiwane typy plików",
"LabelTag": "Znacznik",
"LabelTags": "Tagi",
"LabelTagsAccessibleToUser": "Tagi dostępne dla użytkownika",
"LabelTagsNotAccessibleToUser": "Znaczniki niedostępne dla użytkownika",
"LabelTasks": "Uruchomione zadania",
"LabelTextEditorLink": "Link",
"LabelTextEditorNumberedList": "Lista numerowana",
"LabelTextEditorUnlink": "Usuń link",
"LabelThemeDark": "Ciemny",
"LabelThemeLight": "Jasny",
"LabelTimeDurationXHours": "{0} godzin",
"LabelTimeDurationXMinutes": "{0} minuty",
"LabelTimeDurationXSeconds": "{0} sekundy",
"LabelTimeInMinutes": "Czas w minutach",
"LabelTimeLeft": "pozostało {0}",
"LabelTimeListened": "Czas odtwarzania",
"LabelTimeListenedToday": "Czas odtwarzania dzisiaj",
"LabelTimeRemaining": "Pozostało {0}",
@@ -583,6 +658,7 @@
"LabelTitle": "Tytuł",
"LabelToolsEmbedMetadata": "Załącz metadane",
"LabelToolsEmbedMetadataDescription": "Załącz metadane do plików audio (okładkę oraz znaczniki rozdziałów).",
"LabelToolsM4bEncoder": "Enkoder M4B",
"LabelToolsMakeM4b": "Generuj plik M4B",
"LabelToolsMakeM4bDescription": "Tworzy plik w formacie .M4B, który zawiera metadane, okładkę oraz rozdziały.",
"LabelToolsSplitM4b": "Podziel plik .M4B na pliki .MP3",
@@ -595,12 +671,14 @@
"LabelType": "Typ",
"LabelUndo": "Wycofaj",
"LabelUnknown": "Nieznany",
"LabelUnknownPublishDate": "Nieznana data publikacji",
"LabelUpdateCover": "Zaktalizuj odkładkę",
"LabelUpdateCoverHelp": "Umożliwienie nadpisania istniejących okładek dla wybranych książek w przypadku znalezienia dopasowania",
"LabelUpdateDetails": "Zaktualizuj szczegóły",
"LabelUpdateDetailsHelp": "Umożliwienie nadpisania istniejących szczegółów dla wybranych książek w przypadku znalezienia dopasowania",
"LabelUpdatedAt": "Zaktualizowano",
"LabelUploaderDragAndDrop": "Przeciągnij i puść foldery lub pliki",
"LabelUploaderDragAndDropFilesOnly": "Przeciągnij i upuść pliki",
"LabelUploaderDropFiles": "Puść pliki",
"LabelUploaderItemFetchMetadataHelp": "Automatycznie pobierz tytuł, autora i serie",
"LabelUseChapterTrack": "Użyj ścieżki rozdziału",
@@ -624,46 +702,87 @@
"LabelYourPlaylists": "Twoje playlisty",
"LabelYourProgress": "Twój postęp",
"MessageAppriseDescription": "Aby użyć tej funkcji, konieczne jest posiadanie instancji <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> albo innego rozwiązania, które obsługuje schemat zapytań Apprise. <br />URL do interfejsu API powinno być całkowitą ścieżką, np., jeśli Twoje API do powiadomień jest dostępne pod adresem <code>http://192.168.1.1:8337</code> to wpisany tutaj URL powinien mieć postać: <code>http://192.168.1.1:8337/notify</code>.",
"MessageAuthenticationLegacyTokenWarning": "Starsze tokeny API zostaną w przyszłości usunięte. Zamiast nich należy używać <a href=\"/config/api-keys\">kluczy API</a>.",
"MessageAuthenticationSecurityMessage": "Uwierzytelnianie zostało ulepszone ze względów bezpieczeństwa. Wszyscy użytkownicy muszą się ponownie zalogować.",
"MessageBackupsDescription": "Kopie zapasowe obejmują użytkowników, postępy użytkowników, szczegóły pozycji biblioteki, ustawienia serwera i obrazy przechowywane w <code>/metadata/items</code> & <code>/metadata/authors</code>. Kopie zapasowe nie obejmują żadnych plików przechowywanych w folderach biblioteki.",
"MessageBackupsLocationEditNote": "Uwaga: Zmiana lokalizacji kopii zapasowej nie przenosi ani nie modyfikuje istniejących kopii zapasowych",
"MessageBackupsLocationNoEditNote": "Uwaga: Lokalizacja kopii zapasowej jest ustawiona poprzez zmienną środowiskową i nie może być tutaj zmieniona.",
"MessageBackupsLocationPathEmpty": "Ścieżka do kopii zapasowej nie może być pusta",
"MessageBatchEditPopulateMapDetailsAllHelp": "Wypełnij włączone pola danymi ze wszystkich elementów. Pola z wieloma wartościami zostaną scalone.",
"MessageBatchQuickMatchDescription": "Quick Match będzie próbował dodać brakujące okładki i metadane dla wybranych elementów. Włącz poniższe opcje, aby umożliwić Quick Match nadpisanie istniejących okładek i/lub metadanych.",
"MessageBookshelfNoCollections": "Nie posiadasz jeszcze żadnych kolekcji",
"MessageBookshelfNoCollectionsHelp": "Kolekcje są publiczne. Wszyscy użytkownicy mający dostęp do biblioteki mogą je zobaczyć.",
"MessageBookshelfNoRSSFeeds": "Nie posiadasz żadnych otwartych feedów RSS",
"MessageBookshelfNoResultsForFilter": "Nie znaleziono żadnych pozycji przy aktualnym filtrowaniu \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "Brak wyników zapytania",
"MessageBookshelfNoSeries": "Nie masz jeszcze żadnych serii",
"MessageChapterEndIsAfter": "Koniec rozdziału następuje po zakończeniu audiobooka",
"MessageChapterErrorFirstNotZero": "Pierwszy rozdział musi rozpoczynać się na 0",
"MessageChapterErrorStartGteDuration": "Nieprawidłowy czas rozpoczęcia, musi być krótszy niż długość audiobooka",
"MessageChapterErrorStartLtPrev": "Nieprawidłowy czas rozpoczęcia, musi być większy lub taki sam, jak czas rozpoczęcia poprzedniego rozdziału.",
"MessageChapterStartIsAfter": "Początek rozdziału następuje po zakończeniu audiobooka",
"MessageChaptersNotFound": "Nie znaleziono rozdziałów",
"MessageCheckingCron": "Sprawdzanie cron...",
"MessageConfirmCloseFeed": "Czy na pewno chcesz zamknąć ten kanał?",
"MessageConfirmDeleteApiKey": "Czy na pewno chcesz usunąć klucz API \"{0}\"?",
"MessageConfirmDeleteBackup": "Czy na pewno chcesz usunąć kopię zapasową dla {0}?",
"MessageConfirmDeleteDevice": "Czy na pewno chcesz usunąć czytnik e-booków \"{0}\"?",
"MessageConfirmDeleteFile": "Ta operacja usunie plik z twojego dysku. Jesteś pewien?",
"MessageConfirmDeleteLibrary": "Czy na pewno chcesz trwale usunąć bibliotekę \"{0}\"?",
"MessageConfirmDeleteLibraryItem": "Ta operacja usunie pozycję biblioteki z bazy danych i z dysku. Czy jesteś pewien?",
"MessageConfirmDeleteLibraryItems": "{0} element(ów) zostanie teraz usuniętych z bazy danych i systemu plików. Czy jesteś pewien?",
"MessageConfirmDeleteMetadataProvider": "Czy na pewno chcesz usunąć niestandardowego dostawcę metadanych: \"{0}\"?",
"MessageConfirmDeleteNotification": "Czy na pewno chcesz usunąć to powiadomienie?",
"MessageConfirmDeleteSession": "Czy na pewno chcesz usunąć tę sesję?",
"MessageConfirmEmbedMetadataInAudioFiles": "Czy na pewno chcesz osadzić metadane w {0} plikach audio?",
"MessageConfirmForceReScan": "Czy na pewno chcesz wymusić ponowne skanowanie?",
"MessageConfirmMarkAllEpisodesFinished": "Czy na pewno chcesz oznaczyć wszystkie odcinki jako ukończone?",
"MessageConfirmMarkAllEpisodesNotFinished": "Czy na pewno chcesz oznaczyć wszystkie odcinki jako nieukończone?",
"MessageConfirmMarkItemFinished": "Czy na pewno chcesz oznaczyć \"{0}\" jako zakończone?",
"MessageConfirmMarkItemNotFinished": "Czy na pewno chcesz oznaczyć \"{0}\" jako nieukończone?",
"MessageConfirmMarkSeriesFinished": "Czy na pewno chcesz oznaczyć wszystkie książki w tej serii jako ukończone?",
"MessageConfirmMarkSeriesNotFinished": "Czy na pewno chcesz oznaczyć wszystkie książki w tej serii jako nieukończone?",
"MessageConfirmNotificationTestTrigger": "Czy wywołać to powiadomienie za pomocą danych testowych?",
"MessageConfirmPurgeCache": "Wyczyszczenie pamięci podręcznej spowoduje usunięcie całego katalogu <code>/metadata/cache</code>. <br /><br />Czy na pewno chcesz usunąć katalog pamięci podręcznej?",
"MessageConfirmPurgeItemsCache": "Wyczyszczenie pamięci podręcznej elementów spowoduje usunięcie całego katalogu <code>/metadata/cache/items</code>.<br />Czy jesteś pewien?",
"MessageConfirmQuickEmbed": "Ostrzeżenie! Szybkie osadzanie nie utworzy kopii zapasowej plików audio. Upewnij się, że masz kopię zapasową plików audio. <br><br>Czy chcesz kontynuować?",
"MessageConfirmQuickMatchEpisodes": "Szybkie dopasowywanie odcinków spowoduje nadpisanie szczegółów w przypadku znalezienia dopasowania. Zaktualizowane zostaną tylko niedopasowane odcinki. Jesteś pewien?",
"MessageConfirmReScanLibraryItems": "Czy na pewno chcesz ponownie zeskanować {0} pozycji?",
"MessageConfirmRemoveAllChapters": "Czy na pewno chcesz usunąć wszystkie rozdziały?",
"MessageConfirmRemoveAuthor": "Czy na pewno chcesz usunąć autora \"{0}\"?",
"MessageConfirmRemoveCollection": "Czy na pewno chcesz usunąć kolekcję \"{0}\"?",
"MessageConfirmRemoveEpisode": "Czy na pewno chcesz usunąć odcinek \"{0}\"?",
"MessageConfirmRemoveEpisodeNote": "Uwaga: Plik audio nie zostanie usunięty, chyba że przełączysz opcję „Twarde usunięcie pliku”",
"MessageConfirmRemoveEpisodes": "Czy na pewno chcesz usunąć {0} odcinki?",
"MessageConfirmRemoveListeningSessions": "Czy na pewno chcesz usunąć {0} sesji słuchania?",
"MessageConfirmRemoveMetadataFiles": "Czy na pewno chcesz usunąć wszystkie metadane.{0} plików w folderach elementów biblioteki?",
"MessageConfirmRemoveNarrator": "Czy na pewno chcesz usunąć lektora \"{0}\"?",
"MessageConfirmRemovePlaylist": "Czy jesteś pewien, że chcesz usunąć twoją playlistę \"{0}\"?",
"MessageConfirmRenameGenre": "Czy na pewno chcesz zmienić nazwę gatunku \"{0}\" na \"{1}\" dla wszystkich elementów?",
"MessageConfirmRenameGenreMergeNote": "Uwaga: Ten gatunek już istnieje, więc zostaną połączone.",
"MessageConfirmRenameGenreWarning": "Uwaga! Podobny gatunek z inną wielkością liter już istnieje: \"{0}\".",
"MessageConfirmRenameTag": "Czy na pewno chcesz zmienić nazwę tagu \"{0}\" na \"{1}\" dla wszystkich elementów?",
"MessageConfirmRenameTagMergeNote": "Uwaga: Ten tag już istnieje, więc zostaną scalone.",
"MessageConfirmRenameTagWarning": "Uwaga! Podobny tag z inną wielkością liter już istnieje: \"{0}\".",
"MessageConfirmResetProgress": "Czy na pewno chcesz zresetować swój postęp?",
"MessageConfirmSendEbookToDevice": "Czy na pewno chcesz wysłać {0} e-booka \"{1}\" na urządzenie \"{2}\"?",
"MessageConfirmUnlinkOpenId": "Czy na pewno chcesz odłączyć tego użytkownika od OpenID?",
"MessageDaysListenedInTheLastYear": "{0} dni słuchania w ciągu ostatniego roku",
"MessageDownloadingEpisode": "Pobieranie odcinka",
"MessageDragFilesIntoTrackOrder": "przeciągnij pliki aby ustawić właściwą kolejność utworów",
"MessageEmbedFailed": "Niepowodzenie wstawiania!",
"MessageEmbedFinished": "Osadzanie zakończone!",
"MessageEmbedQueue": "W kolejce do osadzenia metadanych ({0} w kolejce)",
"MessageEpisodesQueuedForDownload": "{0} odcinki w kolejce do pobrania",
"MessageEreaderDevices": "Aby zagwarantować dostawę e-booków, konieczne może być dodanie powyższego adresu e-mail jako prawidłowego nadawcy dla każdego z urządzeń wymienionych poniżej.",
"MessageFeedURLWillBe": "URL kanału: {0}",
"MessageFetching": "Pobieranie...",
"MessageForceReScanDescription": "przeskanuje wszystkie pliki ponownie, jak przy świeżym skanowaniu. Tagi ID3 plików audio, pliki OPF i pliki tekstowe będą skanowane jak nowe.",
"MessageImportantNotice": "Ważna informacja!",
"MessageInsertChapterBelow": "Wstaw rozdział poniżej",
"MessageInvalidAsin": "Nieprawidłowy ASIN",
"MessageItemsSelected": "{0} zaznaczone elementy",
"MessageItemsUpdated": "Zaktualizowano {0} elementów",
"MessageJoinUsOn": "Dołącz do nas na",
"MessageLoading": "Ładowanie...",
"MessageLoadingFolders": "Ładowanie folderów...",
@@ -684,6 +803,9 @@
"MessageNoCollections": "Brak kolekcji",
"MessageNoCoversFound": "Okładki nieznalezione",
"MessageNoDescription": "Brak opisu",
"MessageNoDevices": "Brak urządzeń",
"MessageNoDownloadsInProgress": "Brak aktualnie trwających pobrań",
"MessageNoDownloadsQueued": "Brak pobrań w kolejce",
"MessageNoEpisodeMatchesFound": "Nie znaleziono pasujących odcinków",
"MessageNoEpisodes": "Brak odcinków",
"MessageNoFoldersAvailable": "Brak dostępnych folderów",
@@ -695,25 +817,35 @@
"MessageNoLogs": "Brak logów",
"MessageNoMediaProgress": "Brak postępu",
"MessageNoNotifications": "Brak powiadomień",
"MessageNoPodcastFeed": "Nieprawidłowy podcast: Brak kanału",
"MessageNoPodcastsFound": "Nie znaleziono podcastów",
"MessageNoResults": "Brak wyników",
"MessageNoSearchResultsFor": "Brak wyników wyszukiwania dla \"{0}\"",
"MessageNoSeries": "Brak serii",
"MessageNoTags": "Brak tagów",
"MessageNoTasksRunning": "Brak uruchomionych zadań",
"MessageNoUpdatesWereNecessary": "Brak aktualizacji",
"MessageNoUserPlaylists": "Nie masz żadnych list odtwarzania",
"MessageNoUserPlaylistsHelp": "Listy odtwarzania są prywatne. Tylko użytkownik, który je utworzył, może je zobaczyć.",
"MessageNotYetImplemented": "Jeszcze nie zaimplementowane",
"MessageOpmlPreviewNote": "Uwaga: To jest podgląd sparsowanego pliku OPML. Tytuł podcastu wzięty został z wątku RSS.",
"MessageOr": "lub",
"MessagePauseChapter": "Zatrzymaj odtwarzanie rozdziały",
"MessagePlayChapter": "Rozpocznij odtwarzanie od początku rozdziału",
"MessagePlaylistCreateFromCollection": "Utwórz listę odtwarzania na podstawie kolekcji",
"MessagePleaseWait": "Proszę czekać...",
"MessagePodcastHasNoRSSFeedForMatching": "Podcast nie ma adresu url kanału RSS, który mógłby zostać użyty do dopasowania",
"MessagePodcastSearchField": "Wprowadź wyszukiwane hasło lub adres URL kanału RSS",
"MessageQuickEmbedInProgress": "Szybkie osadzanie w toku",
"MessageQuickEmbedQueue": "W kolejce do szybkiego osadzenia ({0} w kolejce)",
"MessageQuickMatchAllEpisodes": "Szybkie dopasowanie wszystkich odcinków",
"MessageQuickMatchDescription": "Wypełnij puste informacje i okładkę pierwszym wynikiem dopasowania z '{0}'. Nie nadpisuje szczegółów, chyba że włączone jest ustawienie serwera 'Preferuj dopasowane metadane'.",
"MessageRemoveChapter": "Usuń rozdział",
"MessageRemoveEpisodes": "Usuń {0} odcinków",
"MessageRemoveFromPlayerQueue": "Usuń z kolejki odtwarzacza",
"MessageRemoveUserWarning": "Czy na pewno chcesz trwale usunąć użytkownika \"{0}\"?",
"MessageReportBugsAndContribute": "Zgłoś błędy, pomysły i pomóż rozwijać aplikację na",
"MessageResetChaptersConfirm": "Czy na pewno chcesz zresetować rozdziały i cofnąć wprowadzone zmiany?",
"MessageRestoreBackupConfirm": "Czy na pewno chcesz przywrócić kopię zapasową utworzoną w dniu",
"MessageRestoreBackupWarning": "Przywrócenie kopii zapasowej spowoduje nadpisanie bazy danych w folderze /config oraz okładek w folderze /metadata/items & /metadata/authors.<br /><br />Kopie zapasowe nie modyfikują żadnego pliku w folderach z plikami audio. Jeśli włączyłeś ustawienia serwera, aby przechowywać okładki i metadane w folderach biblioteki, to nie są one zapisywane w kopii zapasowej lub nadpisywane<br /><br />Wszyscy klienci korzystający z Twojego serwera będą automatycznie odświeżani.",
"MessageSearchResultsFor": "Wyniki wyszukiwania dla",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Добавить",
"ButtonAddApiKey": "Добавить API ключ",
"ButtonAddChapters": "Добавить главы",
"ButtonAddDevice": "Добавить устройство",
"ButtonAddLibrary": "Добавить библиотеку",
@@ -20,6 +21,7 @@
"ButtonChooseAFolder": "Выбор папки",
"ButtonChooseFiles": "Выбор файлов",
"ButtonClearFilter": "Очистить фильтр",
"ButtonClose": "Закрыть",
"ButtonCloseFeed": "Закрыть канал",
"ButtonCloseSession": "Закрыть открытый сеанс",
"ButtonCollections": "Коллекции",
@@ -119,6 +121,7 @@
"HeaderAccount": "Учетная запись",
"HeaderAddCustomMetadataProvider": "Добавление пользовательского поставщика метаданных",
"HeaderAdvanced": "Дополнительно",
"HeaderApiKeys": "API ключи",
"HeaderAppriseNotificationSettings": "Настройки оповещений",
"HeaderAudioTracks": "Аудио треки",
"HeaderAudiobookTools": "Инструменты файлов аудиокниг",
@@ -162,6 +165,7 @@
"HeaderMetadataOrderOfPrecedence": "Порядок приоритета метаданных",
"HeaderMetadataToEmbed": "Метаинформация для встраивания",
"HeaderNewAccount": "Новая учетная запись",
"HeaderNewApiKey": "Новый API ключ",
"HeaderNewLibrary": "Новая библиотека",
"HeaderNotificationCreate": "Создать уведомление",
"HeaderNotificationUpdate": "Уведомление об обновлении",
@@ -195,6 +199,7 @@
"HeaderSettingsExperimental": "Экспериментальные функции",
"HeaderSettingsGeneral": "Основные",
"HeaderSettingsScanner": "Сканер",
"HeaderSettingsSecurity": "Безопасность",
"HeaderSettingsWebClient": "Веб-клиент",
"HeaderSleepTimer": "Таймер сна",
"HeaderStatsLargestItems": "Самые большые элементы",
@@ -206,15 +211,16 @@
"HeaderTableOfContents": "Содержание",
"HeaderTools": "Инструменты",
"HeaderUpdateAccount": "Обновить учетную запись",
"HeaderUpdateApiKey": "Обновить API ключ",
"HeaderUpdateAuthor": "Обновить автора",
"HeaderUpdateDetails": "Обновить детали",
"HeaderUpdateLibrary": "Обновить библиотеку",
"HeaderUsers": "Пользователи",
"HeaderYearReview": "Итоги {0} года",
"HeaderYourStats": "Ваша статистика",
"LabelAbridged": "Сокращенное издание",
"LabelAbridged": "Сокращенная форма",
"LabelAbridgedChecked": "Сокращено (отмечено)",
"LabelAbridgedUnchecked": "Без сокращений (не отмечено)",
"LabelAbridgedUnchecked": "Полное издание (не отмечено)",
"LabelAccessibleBy": "Доступ",
"LabelAccountType": "Тип учетной записи",
"LabelAccountTypeAdmin": "Администратор",
@@ -235,6 +241,10 @@
"LabelAllUsersExcludingGuests": "Все пользователи, кроме гостей",
"LabelAllUsersIncludingGuests": "Все пользователи, включая гостей",
"LabelAlreadyInYourLibrary": "Уже в Вашей библиотеке",
"LabelApiKeyCreated": "API ключ \"{0}\" успешно создан.",
"LabelApiKeyCreatedDescription": "Обязательно скопируйте API-ключ сейчас, так как вы больше не сможете его увидеть.",
"LabelApiKeyUser": "Управление от пользователя",
"LabelApiKeyUserDescription": "Этот API-ключ будет иметь те же права доступа, что и пользователь, от имени которого он действует. В логах это будет отображаться так же, как если бы пользователь отправлял запрос.",
"LabelApiToken": "Токен API",
"LabelAppend": "Добавить",
"LabelAudioBitrate": "Битрейт (напр. 128k)",
@@ -284,6 +294,7 @@
"LabelContinueListening": "Продолжить слушать",
"LabelContinueReading": "Продолжить чтение",
"LabelContinueSeries": "Продолжить серию",
"LabelCorsAllowed": "Разрешённые CORS источники",
"LabelCover": "Обложка",
"LabelCoverImageURL": "URL изображения обложки",
"LabelCoverProvider": "Провайдер обложек",
@@ -346,9 +357,13 @@
"LabelExample": "Пример",
"LabelExpandSeries": "Развернуть серию",
"LabelExpandSubSeries": "Развернуть подсерию",
"LabelExplicit": "Явный",
"LabelExplicitChecked": "Явный (отмечено)",
"LabelExplicitUnchecked": "Не явно (не отмечено)",
"LabelExpired": "Истекший",
"LabelExpiresAt": "Истекает в",
"LabelExpiresInSeconds": "Истекает через (секунд)",
"LabelExpiresNever": "Никогда",
"LabelExplicit": "18+",
"LabelExplicitChecked": "18+ (отмечено)",
"LabelExplicitUnchecked": "+18 (не отмечено)",
"LabelExportOPML": "Экспорт OPML",
"LabelFeedURL": "URL канала",
"LabelFetchingMetadata": "Извлечение метаданных",
@@ -405,6 +420,7 @@
"LabelLanguages": "Языки",
"LabelLastBookAdded": "Последняя книга добавлена",
"LabelLastBookUpdated": "Последняя книга обновлена",
"LabelLastProgressDate": "Последний прогресс: {0}",
"LabelLastSeen": "Последнее сканирование",
"LabelLastTime": "Последний по времени",
"LabelLastUpdate": "Последний обновленный",
@@ -417,6 +433,7 @@
"LabelLibraryFilterSublistEmpty": "Нет {0}",
"LabelLibraryItem": "Элемент библиотеки",
"LabelLibraryName": "Имя библиотеки",
"LabelLibrarySortByProgress": "Прогресс обновлён",
"LabelLimit": "Лимит",
"LabelLineSpacing": "Межстрочный интервал",
"LabelListenAgain": "Послушать снова",
@@ -425,6 +442,7 @@
"LabelLogLevelWarn": "Предупреждение",
"LabelLookForNewEpisodesAfterDate": "Искать новые эпизоды после этой даты",
"LabelLowestPriority": "Самый низкий приоритет",
"LabelMatchConfidence": "Уверенность",
"LabelMatchExistingUsersBy": "Сопоставление существующих пользователей по",
"LabelMatchExistingUsersByDescription": "Используется для подключения существующих пользователей. После подключения пользователям будет присвоен уникальный идентификатор от поставщика единого входа",
"LabelMaxEpisodesToDownload": "Максимальное количество эпизодов для загрузки. Используйте 0 для неограниченного количества.",
@@ -455,6 +473,7 @@
"LabelNewestEpisodes": "Новые эпизоды",
"LabelNextBackupDate": "Следующая дата бэкапирования",
"LabelNextScheduledRun": "Следущий запланированный запуск",
"LabelNoApiKeys": "API ключи отсутствуют",
"LabelNoCustomMetadataProviders": "Нет пользовательских поставщиков метаданных",
"LabelNoEpisodesSelected": "Эпизоды не выбраны",
"LabelNotFinished": "Не завершено",
@@ -514,7 +533,7 @@
"LabelPublishers": "Издатели",
"LabelRSSFeedCustomOwnerEmail": "Пользовательский Email владельца",
"LabelRSSFeedCustomOwnerName": "Пользовательское Имя владельца",
"LabelRSSFeedOpen": "Открыть RSS-канал",
"LabelRSSFeedOpen": "Открыть RSS-ленту",
"LabelRSSFeedPreventIndexing": "Запретить индексирование",
"LabelRSSFeedSlug": "Встроить RSS-канал",
"LabelRSSFeedURL": "URL RSS-канала",
@@ -544,6 +563,7 @@
"LabelSelectAll": "Выбрать все",
"LabelSelectAllEpisodes": "Выбрать все эпизоды",
"LabelSelectEpisodesShowing": "Выберите {0} эпизодов для показа",
"LabelSelectUser": "Выбрать пользователя",
"LabelSelectUsers": "Выбор пользователей",
"LabelSendEbookToDevice": "Отправить e-книгу в...",
"LabelSequence": "Последовательность",
@@ -640,7 +660,8 @@
"LabelTheme": "Тема",
"LabelThemeDark": "Темная",
"LabelThemeLight": "Светлая",
"LabelTimeBase": "Временная база",
"LabelThemeSepia": "Сепия",
"LabelTimeBase": "Основное время",
"LabelTimeDurationXHours": "{0} часов",
"LabelTimeDurationXMinutes": "{0} минут",
"LabelTimeDurationXSeconds": "{0} секунд",
@@ -708,7 +729,9 @@
"MessageAddToPlayerQueue": "Добавить в очередь проигрывателя",
"MessageAppriseDescription": "Для использования этой функции необходимо иметь запущенный экземпляр <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> или api которое обрабатывает те же самые запросы. <br />URL-адрес API Apprise должен быть полным URL-адресом для отправки уведомления, т.е., если API запущено по адресу <code>http://192.168.1.1:8337</code> тогда нужно указать <code>http://192.168.1.1:8337/notify</code>.",
"MessageAsinCheck": "Убедитесь, что вы используете ASIN из правильной региональной зоны Audible, а не из Amazon.",
"MessageAuthenticationLegacyTokenWarning": "Устаревшие токены API в будущем будут удалены. Вместо них используйте <a href=\"/config/api-keys\">API-ключи</a>.",
"MessageAuthenticationOIDCChangesRestart": "Перезапустите ваш сервер после сохранения для применения изменений в OIDC.",
"MessageAuthenticationSecurityMessage": "В целях безопасности была улучшена аутентификация. Всем пользователям необходимо повторно войти в систему.",
"MessageBackupsDescription": "Бэкап включает пользователей, прогресс пользователей, данные элементов библиотеки, настройки сервера и изображения хранящиеся в <code>/metadata/items</code> и <code>/metadata/authors</code>. Бэкапы <strong>НЕ</strong> сохраняют файлы из папок библиотек.",
"MessageBackupsLocationEditNote": "Примечание: Обновление местоположения резервной копии не приведет к перемещению или изменению существующих резервных копий",
"MessageBackupsLocationNoEditNote": "Примечание: Местоположение резервного копирования задается с помощью переменной среды и не может быть изменено здесь.",
@@ -730,6 +753,7 @@
"MessageChaptersNotFound": "Главы не найденны",
"MessageCheckingCron": "Проверка cron...",
"MessageConfirmCloseFeed": "Вы уверены, что хотите закрыть этот канал?",
"MessageConfirmDeleteApiKey": "Вы уверены, что хотите удалить API ключ \"{0}\"?",
"MessageConfirmDeleteBackup": "Вы уверены, что хотите удалить бэкап для {0}?",
"MessageConfirmDeleteDevice": "Вы уверены, что хотите удалить устройство для чтения электронных книг \"{0}\"?",
"MessageConfirmDeleteFile": "Это удалит файл из Вашей файловой системы. Вы уверены?",
@@ -757,6 +781,7 @@
"MessageConfirmRemoveAuthor": "Вы уверены, что хотите удалить автора \"{0}\"?",
"MessageConfirmRemoveCollection": "Вы уверены, что хотите удалить коллекцию \"{0}\"?",
"MessageConfirmRemoveEpisode": "Вы уверены, что хотите удалить эпизод \"{0}\"?",
"MessageConfirmRemoveEpisodeNote": "Примечание: Это не приведет к удалению аудиофайла, если не включить опцию \"Жесткое удаление файла\"",
"MessageConfirmRemoveEpisodes": "Вы уверены, что хотите удалить {0} эпизодов?",
"MessageConfirmRemoveListeningSessions": "Вы уверены, что хотите удалить {0} сеансов прослушивания?",
"MessageConfirmRemoveMetadataFiles": "Вы уверены, что хотите удалить все файлы metadata. {0} файлов из папок элементов вашей библиотеки?",
@@ -782,6 +807,8 @@
"MessageFeedURLWillBe": "URL канала будет {0}",
"MessageFetching": "Завершается...",
"MessageForceReScanDescription": "будет сканировать все файлы снова, как свежее сканирование. Теги ID3 аудиофайлов, OPF-файлы и текстовые файлы будут сканироваться как новые.",
"MessageHeatmapListeningTimeTooltip": "<strong>{0} прослушивание</strong> на {1}",
"MessageHeatmapNoListeningSessions": "Нет сессий прослушивания на {0}",
"MessageImportantNotice": "Важное замечание!",
"MessageInsertChapterBelow": "Вставить главу ниже",
"MessageInvalidAsin": "Неправильный ASIN",
@@ -856,6 +883,7 @@
"MessageScheduleRunEveryWeekdayAtTime": "Запуск каждые {0} по {1}",
"MessageSearchResultsFor": "Результаты поиска для",
"MessageSelected": "{0} выбрано",
"MessageSeriesSequenceCannotContainSpaces": "Последовательность серии должна быть без пропусков",
"MessageServerCouldNotBeReached": "Не удалось связаться с сервером",
"MessageSetChaptersFromTracksDescription": "Установка глав с использованием каждого аудиофайла в качестве главы и заголовка главы в качестве имени аудиофайла",
"MessageShareExpirationWillBe": "Срок действия истекает <strong>{0}</strong>",
@@ -917,6 +945,8 @@
"NotificationOnBackupCompletedDescription": "Запускается при завершении резервного копирования",
"NotificationOnBackupFailedDescription": "Срабатывает при сбое резервного копирования",
"NotificationOnEpisodeDownloadedDescription": "Запускается при автоматической загрузке эпизода подкаста",
"NotificationOnRSSFeedDisabledDescription": "Срабатывает, когда автоматическая загрузка эпизодов отключена из-за слишком большого количества неудачных попыток",
"NotificationOnRSSFeedFailedDescription": "Срабатывает при сбое запроса RSS-канала на автоматическую загрузку эпизода",
"NotificationOnTestDescription": "Событие для тестирования системы оповещения",
"PlaceholderNewCollection": "Новое имя коллекции",
"PlaceholderNewFolderPath": "Путь к новой папке",
@@ -997,6 +1027,8 @@
"ToastEpisodeDownloadQueueClearSuccess": "Очередь загрузки эпизода очищена",
"ToastEpisodeUpdateSuccess": "{0 эпизодов обновлено",
"ToastErrorCannotShare": "Невозможно предоставить общий доступ на этом устройстве",
"ToastFailedToCreate": "Не удалось создать",
"ToastFailedToDelete": "Не удалось удалить",
"ToastFailedToLoadData": "Не удалось загрузить данные",
"ToastFailedToMatch": "Не удалось найти совпадения",
"ToastFailedToShare": "Не удалось поделиться",
@@ -1004,6 +1036,7 @@
"ToastInvalidImageUrl": "Неверный URL изображения",
"ToastInvalidMaxEpisodesToDownload": "Недопустимое максимальное количество загружаемых эпизодов",
"ToastInvalidUrl": "Неверный URL",
"ToastInvalidUrls": "Один или несколько URL неверны",
"ToastItemCoverUpdateSuccess": "Обложка элемента обновлена",
"ToastItemDeletedFailed": "Не удалось удалить элемент",
"ToastItemDeletedSuccess": "Удаленный элемент",
@@ -1028,6 +1061,7 @@
"ToastMustHaveAtLeastOnePath": "Должен быть хотя бы один путь",
"ToastNameEmailRequired": "Имя и адрес электронной почты обязательны",
"ToastNameRequired": "Имя обязательно для заполнения",
"ToastNewApiKeyUserError": "Необходимо выбрать пользователя",
"ToastNewEpisodesFound": "{0} новых эпизодов найдено",
"ToastNewUserCreatedFailed": "Не удалось создать учетную запись: \"{0}\"",
"ToastNewUserCreatedSuccess": "Новая учетная запись создана",

View File

@@ -346,7 +346,7 @@
"LabelExample": "Príklad",
"LabelExpandSeries": "Rozbaliť série",
"LabelExpandSubSeries": "Rozbaliť podsérie",
"LabelExplicit": "Explicitné",
"LabelExplicit": "Explicitný obsah",
"LabelExplicitChecked": "Explicitné (zaškrtnuté)",
"LabelExplicitUnchecked": "Ne-explicitné (nezaškrtnuté)",
"LabelExportOPML": "Exportovať OPML",
@@ -757,6 +757,7 @@
"MessageConfirmRemoveAuthor": "Ste si istý, že chcete odstrániť autora \"{0}\"?",
"MessageConfirmRemoveCollection": "Ste si istý, že chcete odstrániť zbierku \"{0}\"?",
"MessageConfirmRemoveEpisode": "Ste si istý, že chcete odstrániť epizódu \"{0}\"?",
"MessageConfirmRemoveEpisodeNote": "Poznámka: Tento krok neodstráni zvukový súbor, pokiaľ nezaškrtnete voľbu \"Nezvratné zmazanie súborov\"",
"MessageConfirmRemoveEpisodes": "Ste si istý, že chcete odstrániť {0} epizód?",
"MessageConfirmRemoveListeningSessions": "Ste si istý, že chcete odstrániť týchto {0} relácií?",
"MessageConfirmRemoveMetadataFiles": "Ste si istý, že chcete odstrániť všetky súbory metadata.{0} z priečinkov položiek vašej knižnice?",
@@ -918,6 +919,8 @@
"NotificationOnBackupCompletedDescription": "Spustené po dokončení zálohovania",
"NotificationOnBackupFailedDescription": "Spustené pri zlyhaní zálohovania",
"NotificationOnEpisodeDownloadedDescription": "Spustené po automatickom stiahnutí epizódy podcastu",
"NotificationOnRSSFeedDisabledDescription": "Spustí sa, keď je automatické sťahovanie epizód pozastavené z dôvodu veľkého počtu zlyhaní",
"NotificationOnRSSFeedFailedDescription": "Spustí sa v prípade, keď zlyhá požiadavka RSS zdroja na automatické stiahnutie epizódy",
"NotificationOnTestDescription": "Udalosť určená na testovanie systému notifikácií",
"PlaceholderNewCollection": "Názov novej zbierky",
"PlaceholderNewFolderPath": "Umiestnenie nového priečinka",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Dodaj",
"ButtonAddApiKey": "Dodaj API ključ",
"ButtonAddChapters": "Dodaj poglavja",
"ButtonAddDevice": "Dodaj napravo",
"ButtonAddLibrary": "Dodaj knjižnico",
@@ -20,6 +21,7 @@
"ButtonChooseAFolder": "Izberite mapo",
"ButtonChooseFiles": "Izberite datoteke",
"ButtonClearFilter": "Počisti filter",
"ButtonClose": "Zapri",
"ButtonCloseFeed": "Zapri vir",
"ButtonCloseSession": "Zapri odprto sejo",
"ButtonCollections": "Zbirke",
@@ -119,6 +121,7 @@
"HeaderAccount": "Račun",
"HeaderAddCustomMetadataProvider": "Dodaj ponudnika metapodatkov po meri",
"HeaderAdvanced": "Napredno",
"HeaderApiKeys": "API ključi",
"HeaderAppriseNotificationSettings": "Nastavitve obvestil Apprise",
"HeaderAudioTracks": "Zvočni posnetki",
"HeaderAudiobookTools": "Orodja za upravljanje datotek zvočnih knjig",
@@ -162,6 +165,7 @@
"HeaderMetadataOrderOfPrecedence": "Vrstni red metapodatkov",
"HeaderMetadataToEmbed": "Metapodatki za vdelavo",
"HeaderNewAccount": "Nov račun",
"HeaderNewApiKey": "Nov API ključ",
"HeaderNewLibrary": "Nova knjižnica",
"HeaderNotificationCreate": "Ustvari obvestilo",
"HeaderNotificationUpdate": "Posodobi obvestilo",
@@ -206,6 +210,7 @@
"HeaderTableOfContents": "Kazalo",
"HeaderTools": "Orodja",
"HeaderUpdateAccount": "Posodobi račun",
"HeaderUpdateApiKey": "Posodobi API ključ",
"HeaderUpdateAuthor": "Posodobi avtorja",
"HeaderUpdateDetails": "Posodobi podrobnosti",
"HeaderUpdateLibrary": "Posodobi knjižnico",
@@ -235,6 +240,10 @@
"LabelAllUsersExcludingGuests": "Vsi uporabniki razen gosti",
"LabelAllUsersIncludingGuests": "Vsi uporabniki vključno z gosti",
"LabelAlreadyInYourLibrary": "Že v tvoji knjižnici",
"LabelApiKeyCreated": "API ključ \"{0}\" je uspešno ustvarjen.",
"LabelApiKeyCreatedDescription": "Ne pozabite takoj kopirati API ključ, saj ga kasneje ne boste mogli več videti.",
"LabelApiKeyUser": "Izvedi v imenu uporabnika",
"LabelApiKeyUserDescription": "Ta API ključ bo imel enaka dovoljenja kot uporabnik, v imenu katerega deluje. V dnevnikih bo to prikazano enako, kot če bi zahtevo oddal uporabnik.",
"LabelApiToken": "API žeton",
"LabelAppend": "Priloži",
"LabelAudioBitrate": "Avdio bitna hitrost (npr. 128k)",
@@ -346,6 +355,10 @@
"LabelExample": "Primer",
"LabelExpandSeries": "Razširi serije",
"LabelExpandSubSeries": "Razširi podserije",
"LabelExpired": "Potekel",
"LabelExpiresAt": "Peteče ob",
"LabelExpiresInSeconds": "Poteče čez (sekunde)",
"LabelExpiresNever": "Nikoli",
"LabelExplicit": "Eksplicitno",
"LabelExplicitChecked": "Eksplicitno (omogočeno)",
"LabelExplicitUnchecked": "Ne eksplicitno (onemogočeno)",
@@ -405,6 +418,7 @@
"LabelLanguages": "Jeziki",
"LabelLastBookAdded": "Zadnja dodana knjiga",
"LabelLastBookUpdated": "Zadnja posodobljena knjiga",
"LabelLastProgressDate": "Zadnji napredek: {0}",
"LabelLastSeen": "Nazadnje viden",
"LabelLastTime": "Nazadnje",
"LabelLastUpdate": "Zadnja posodobitev",
@@ -417,6 +431,7 @@
"LabelLibraryFilterSublistEmpty": "Ne {0}",
"LabelLibraryItem": "Element knjižnice",
"LabelLibraryName": "Ime knjižnice",
"LabelLibrarySortByProgress": "Napredek posodobljen",
"LabelLimit": "Omejitev",
"LabelLineSpacing": "Vrstični razmak",
"LabelListenAgain": "Poslušaj znova",
@@ -425,6 +440,7 @@
"LabelLogLevelWarn": "Opozoritve",
"LabelLookForNewEpisodesAfterDate": "Poiščite nove epizode po tem datumu",
"LabelLowestPriority": "Najnižja prioriteta",
"LabelMatchConfidence": "Zaupanje",
"LabelMatchExistingUsersBy": "Poveži obstoječe uporabnike po",
"LabelMatchExistingUsersByDescription": "Uporablja se za povezovanje obstoječih uporabnikov. Ko se vzpostavi povezava, se bodo uporabniki ujemali z enoličnim ID-jem vašega ponudnika SSO",
"LabelMaxEpisodesToDownload": "Največje število epizod za prenos. Uporabite 0 za neomejeno.",
@@ -455,6 +471,7 @@
"LabelNewestEpisodes": "Najnovejše epizode",
"LabelNextBackupDate": "Naslednji datum varnostnega kopiranja",
"LabelNextScheduledRun": "Naslednji načrtovani zagon",
"LabelNoApiKeys": "Ni API ključev",
"LabelNoCustomMetadataProviders": "Ni ponudnikov metapodatkov po meri",
"LabelNoEpisodesSelected": "Izbrana ni nobena epizoda",
"LabelNotFinished": "Ni dokončano",
@@ -514,7 +531,7 @@
"LabelPublishers": "Izdajatelji",
"LabelRSSFeedCustomOwnerEmail": "E-pošta lastnika po meri",
"LabelRSSFeedCustomOwnerName": "Ime lastnika po meri",
"LabelRSSFeedOpen": "Odprt vir RSS",
"LabelRSSFeedOpen": "RSS vir je odprt",
"LabelRSSFeedPreventIndexing": "Prepreči indeksiranje",
"LabelRSSFeedSlug": "Slug RSS vira",
"LabelRSSFeedURL": "URL vira RSS",
@@ -544,6 +561,7 @@
"LabelSelectAll": "Izberite vse",
"LabelSelectAllEpisodes": "Izberite vse epizode",
"LabelSelectEpisodesShowing": "Izberi {0} prikazanih epizod",
"LabelSelectUser": "Izberi uporabnika",
"LabelSelectUsers": "Izberite uporabnike",
"LabelSendEbookToDevice": "Pošlji eknjigo k...",
"LabelSequence": "Zaporedje",
@@ -640,6 +658,7 @@
"LabelTheme": "Tema",
"LabelThemeDark": "Temna",
"LabelThemeLight": "Svetla",
"LabelThemeSepia": "Sepija",
"LabelTimeBase": "Osnovni čas",
"LabelTimeDurationXHours": "{0} ur",
"LabelTimeDurationXMinutes": "{0} minut",
@@ -708,7 +727,9 @@
"MessageAddToPlayerQueue": "Dodaj v čakalno vrsto predvajalnika",
"MessageAppriseDescription": "Če želite uporabljati to funkcijo, morate imeti zagnano namestitev <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">API Apprise</a> ali API, ki bo obravnavala te iste zahteve. <br />Url API-ja Apprise mora biti celotna pot URL-ja za pošiljanje obvestila, npr. če je vaša namestitev API-ja postrežena na <code>http://192.168.1.1:8337</code>, bi morali vnesti <code >http://192.168.1.1:8337/notify</code>.",
"MessageAsinCheck": "Prepričajte se, da uporabljate ASIN iz pravilne zvočne regije, ne iz Amazona.",
"MessageAuthenticationLegacyTokenWarning": "Zastareli API žetoni bodo v prihodnosti odstranjeni. Namesto tega uporabite <a href=\"/config/api-keys\">API ključe</a>.",
"MessageAuthenticationOIDCChangesRestart": "Za uveljavitev OIDC sprememb, po shranjevanju znova zaženite strežnik.",
"MessageAuthenticationSecurityMessage": "Zaradi varnosti je bila izboljšana avtentikacija. Vsi uporabniki se morajo ponovno prijaviti.",
"MessageBackupsDescription": "Varnostne kopije vključujejo uporabnike, napredek uporabnikov, podrobnosti elementov knjižnice, nastavitve strežnika in slike, shranjene v <code>/metadata/items</code> & <code>/metadata/authors</code>. Varnostne kopije <strong>ne</strong> vključujejo datotek, shranjenih v mapah vaše knjižnice.",
"MessageBackupsLocationEditNote": "Opomba: Posodabljanje lokacije varnostne kopije ne bo premaknilo ali spremenilo obstoječih varnostnih kopij",
"MessageBackupsLocationNoEditNote": "Opomba: Lokacija varnostne kopije je nastavljena s spremenljivko okolja in je tu ni mogoče spremeniti.",
@@ -730,6 +751,7 @@
"MessageChaptersNotFound": "Poglavij ni bilo najdenih",
"MessageCheckingCron": "Preverjam cron...",
"MessageConfirmCloseFeed": "Ali ste prepričani, da želite zapreti ta vir?",
"MessageConfirmDeleteApiKey": "Ali ste prepričani, da želite izbrisati API ključ \"{0}\"?",
"MessageConfirmDeleteBackup": "Ali ste prepričani, da želite izbrisati varnostno kopijo za {0}?",
"MessageConfirmDeleteDevice": "Ali ste prepričani, da želite izbrisati e-bralnik \"{0}\"?",
"MessageConfirmDeleteFile": "To bo izbrisalo datoteko iz vašega datotečnega sistema. Ali ste prepričani?",
@@ -757,6 +779,7 @@
"MessageConfirmRemoveAuthor": "Ali ste prepričani, da želite odstraniti avtorja \"{0}\"?",
"MessageConfirmRemoveCollection": "Ali ste prepričani, da želite odstraniti zbirko \"{0}\"?",
"MessageConfirmRemoveEpisode": "Ali ste prepričani, da želite odstraniti epizodo \"{0}\"?",
"MessageConfirmRemoveEpisodeNote": "Opomba: S tem se zvočna datoteka ne izbriše, razen če vklopite možnost \"Trdo brisanje datoteke\"",
"MessageConfirmRemoveEpisodes": "Ali ste prepričani, da želite odstraniti {0} epizod?",
"MessageConfirmRemoveListeningSessions": "Ali ste prepričani, da želite odstraniti {0} sej poslušanja?",
"MessageConfirmRemoveMetadataFiles": "Ali ste prepričani, da želite odstraniti vse metapodatke.{0} v mapah elementov knjižnice?",
@@ -918,6 +941,8 @@
"NotificationOnBackupCompletedDescription": "Sproži se, ko je varnostno kopiranje končano",
"NotificationOnBackupFailedDescription": "Sproži se, ko varnostno kopiranje ne uspe",
"NotificationOnEpisodeDownloadedDescription": "Sproži se, ko se epizoda podcasta samodejno prenese",
"NotificationOnRSSFeedDisabledDescription": "Sproži se, ko so samodejni prenosi epizod onemogočeni zaradi preveč neuspelih poskusov",
"NotificationOnRSSFeedFailedDescription": "Sproži se, ko zahteva za vir RSS za samodejni prenos epizode ne uspe",
"NotificationOnTestDescription": "Dogodek za testiranje sistema obveščanja",
"PlaceholderNewCollection": "Novo ime zbirke",
"PlaceholderNewFolderPath": "Pot nove mape",
@@ -998,6 +1023,8 @@
"ToastEpisodeDownloadQueueClearSuccess": "Čakalna vrsta za prenos epizod je počiščena",
"ToastEpisodeUpdateSuccess": "Število posodobljenih epizod: {0}",
"ToastErrorCannotShare": "V tej napravi ni mogoče dati v skupno rabo",
"ToastFailedToCreate": "Ustvarjanje ni bilo uspešno",
"ToastFailedToDelete": "Brisanje ni bilo uspešno",
"ToastFailedToLoadData": "Podatkov ni bilo mogoče naložiti",
"ToastFailedToMatch": "Ujemanje ni uspelo",
"ToastFailedToShare": "Skupna raba ni uspela",
@@ -1029,6 +1056,7 @@
"ToastMustHaveAtLeastOnePath": "Imeti mora vsaj eno pot",
"ToastNameEmailRequired": "Ime in e-pošta sta obvezna",
"ToastNameRequired": "Ime je obvezno",
"ToastNewApiKeyUserError": "Morate izbrati uporabnika",
"ToastNewEpisodesFound": "Število najdenih novih epizod: {0}",
"ToastNewUserCreatedFailed": "Računa ni bilo mogoče ustvariti: \"{0}\"",
"ToastNewUserCreatedSuccess": "Nov račun je bil ustvarjen",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Lägg till",
"ButtonAddApiKey": "Addera API-nyckel",
"ButtonAddChapters": "Lägg till kapitel",
"ButtonAddDevice": "Lägg till enhet",
"ButtonAddLibrary": "Lägg till bibliotek",
@@ -20,6 +21,7 @@
"ButtonChooseAFolder": "Välj en mapp",
"ButtonChooseFiles": "Välj filer",
"ButtonClearFilter": "Rensa filter",
"ButtonClose": "Stäng",
"ButtonCloseFeed": "Stäng flöde",
"ButtonCloseSession": "Stäng öppen session",
"ButtonCollections": "Samlingar",
@@ -119,6 +121,7 @@
"HeaderAccount": "Konto",
"HeaderAddCustomMetadataProvider": "Addera egen källa för metadata",
"HeaderAdvanced": "Avancerad",
"HeaderApiKeys": "API-nyckel",
"HeaderAppriseNotificationSettings": "Inställningar av meddelanden med Apprise",
"HeaderAudioTracks": "Ljudfiler",
"HeaderAudiobookTools": "Hantering av ljudboksfiler",
@@ -162,6 +165,7 @@
"HeaderMetadataOrderOfPrecedence": "Prioriteringsordning vid inläsning av metadata",
"HeaderMetadataToEmbed": "Metadata som kommer att adderas",
"HeaderNewAccount": "Nytt konto",
"HeaderNewApiKey": "Ny API-nyckel",
"HeaderNewLibrary": "Nytt bibliotek",
"HeaderNotificationCreate": "Addera ett meddelande",
"HeaderNotificationUpdate": "Uppdateringsnotis",
@@ -205,6 +209,7 @@
"HeaderTableOfContents": "Innehållsförteckning",
"HeaderTools": "Verktyg",
"HeaderUpdateAccount": "Uppdatera konto",
"HeaderUpdateApiKey": "Uppdatera API-nyckel",
"HeaderUpdateAuthor": "Uppdatera författare",
"HeaderUpdateDetails": "Uppdatera detaljer om boken",
"HeaderUpdateLibrary": "Uppdatera bibliotek",
@@ -234,6 +239,9 @@
"LabelAllUsersExcludingGuests": "Alla användare utom gäster",
"LabelAllUsersIncludingGuests": "Alla användare inklusive gäster",
"LabelAlreadyInYourLibrary": "Finns redan i samlingen",
"LabelApiKeyCreated": "API-nyckel \"{0}\" har adderats.",
"LabelApiKeyCreatedDescription": "Se till att kopiera API-nyckeln omedelbart eftersom du inte kommer att kunna se den igen.",
"LabelApiKeyUserDescription": "Denna API-nyckel kommer att ha samma behörigheter som användaren den agerar på uppdrag av. Detta kommer att visas på samma sätt i loggarna som om användaren gjorde begäran.",
"LabelApiToken": "API-token",
"LabelAppend": "Lägg till",
"LabelAudioBitrate": "Bitrate (t.ex. 128k)",
@@ -345,7 +353,11 @@
"LabelExample": "Exempel",
"LabelExpandSeries": "Expandera serier",
"LabelExpandSubSeries": "Expandera Underserier",
"LabelExplicit": "Explicit version",
"LabelExpired": "Upphört",
"LabelExpiresAt": "Gäller till och med",
"LabelExpiresInSeconds": "Upphör om (sekunder)",
"LabelExpiresNever": "Aldrig",
"LabelExplicit": "Bestämd",
"LabelExplicitChecked": "Explicit version (markerad)",
"LabelExplicitUnchecked": "Ej Explicit version (ej markerad)",
"LabelExportOPML": "Exportera OPML-information",
@@ -424,6 +436,7 @@
"LabelLogLevelWarn": "Varningar",
"LabelLookForNewEpisodesAfterDate": "Sök efter nya avsnitt efter detta datum",
"LabelLowestPriority": "Lägst prioritet",
"LabelMatchConfidence": "Förtroende",
"LabelMatchExistingUsersBy": "Matcha befintliga användare med",
"LabelMatchExistingUsersByDescription": "Används för att koppla existerande användare. När kopplingen sker kommer användaren att matchas med ett unikt ID från SSO-leverantören.",
"LabelMaxEpisodesToDownload": "Maximalt antal avsnitt att ladda ner (0 = obegränsat).",
@@ -454,6 +467,7 @@
"LabelNewestEpisodes": "Senaste avsnitten",
"LabelNextBackupDate": "Nästa tillfälle för säkerhetskopiering",
"LabelNextScheduledRun": "Nästa schemalagda körning",
"LabelNoApiKeys": "Ingen API-nyckel",
"LabelNoCustomMetadataProviders": "Ingen egen källa för metadata",
"LabelNoEpisodesSelected": "Inga avsnitt har valts",
"LabelNotFinished": "Ej avslutad",
@@ -470,11 +484,15 @@
"LabelNotificationsMaxQueueSizeHelp": "Evenemang är begränsade till att utlösa ett per sekund. Evenemang kommer att ignoreras om kön är full. Detta förhindrar aviseringsspam.",
"LabelNumberOfBooks": "Antal böcker",
"LabelNumberOfEpisodes": "# av Avsnitt",
"LabelOpenIDAdvancedPermsClaimDescription": "Namn på OpenID-anspråket som innehåller avancerade behörigheter för användaråtgärder i applikationen, vilka gäller för icke-administratörsroller (<b>om konfigurerat</b>). Om anspråket saknas i svaret kommer åtkomst till ABS att nekas. Om ett enskilt alternativ saknas kommer det att behandlas som <code>falskt</code>. Se till att identitetsleverantörens anspråk matchar den förväntade strukturen:",
"LabelOpenIDClaims": "Lämna följande alternativ tomma för att inaktivera avancerad grupp- och behörighetstilldelning, och tilldela då automatiskt gruppen 'Användare'.",
"LabelOpenIDGroupClaimDescription": "Namn på OpenID-anspråket som innehåller en lista över användarens grupper. Vanligtvis kallat <code>groups</code>. <b>Om det är konfigurerat</b> kommer programmet automatiskt att tilldela roller baserat på användarens gruppmedlemskap, förutsatt att dessa grupper namnges utan att skiftlägeskänsligt tolkas som 'admin', 'user' eller 'guest' i anspråket. Anspråket ska innehålla en lista, och om en användare tillhör flera grupper kommer programmet att tilldela den roll som motsvarar den högsta åtkomstnivån. Om ingen grupp matchar kommer åtkomst att nekas.",
"LabelOpenRSSFeed": "Öppna RSS-flöde",
"LabelOverwrite": "Skriv över",
"LabelPaginationPageXOfY": "Sida {0} av {1}",
"LabelPassword": "Lösenord",
"LabelPath": "Sökväg",
"LabelPermanent": "Permanent",
"LabelPermissionsAccessAllLibraries": "Kan komma åt alla bibliotek",
"LabelPermissionsAccessAllTags": "Kan komma åt alla taggar",
"LabelPermissionsAccessExplicitContent": "Kan komma åt explicit version",
@@ -486,6 +504,7 @@
"LabelPersonalYearReview": "En sammanställning av ditt år, sidan {0}",
"LabelPhotoPathURL": "Bildsökväg/URL",
"LabelPlayMethod": "Spelläge",
"LabelPlaybackRateIncrementDecrement": "Uppspelningshastighetsökning/minskning",
"LabelPlayerChapterNumberMarker": "{0} av {1}",
"LabelPlaylists": "Spellistor",
"LabelPodcast": "Podcast",
@@ -524,6 +543,7 @@
"LabelReleaseDate": "Utgivningsdatum",
"LabelRemoveAllMetadataAbs": "Radera alla 'metadata.abs' filer",
"LabelRemoveAllMetadataJson": "Radera alla 'metadata.json' filer",
"LabelRemoveAudibleBranding": "Ta bort Audible intro och outro från kapitel",
"LabelRemoveCover": "Ta bort omslag",
"LabelRemoveMetadataFile": "Radera metadata-filer i alla mappar i biblioteket",
"LabelRemoveMetadataFileHelp": "Radera alla 'metadata.json' och 'metadata.abs' filer i dina {0} mappar.",
@@ -536,6 +556,7 @@
"LabelSelectAll": "Välj alla",
"LabelSelectAllEpisodes": "Välj alla avsnitt",
"LabelSelectEpisodesShowing": "Välj {0} avsnitt som visas",
"LabelSelectUser": "Välj användare",
"LabelSelectUsers": "Välj användare",
"LabelSendEbookToDevice": "Skicka e-bok till...",
"LabelSequence": "Ordningsnummer",
@@ -629,6 +650,7 @@
"LabelTheme": "Utseende",
"LabelThemeDark": "Mörkt",
"LabelThemeLight": "Ljust",
"LabelThemeSepia": "Sepia",
"LabelTimeBase": "Tidsbas",
"LabelTimeDurationXHours": "{0} timmar",
"LabelTimeDurationXMinutes": "{0} minuter",
@@ -694,6 +716,9 @@
"LabelYourProgress": "Framsteg",
"MessageAddToPlayerQueue": "Lägg till i spellistan",
"MessageAppriseDescription": "För att använda den här funktionen behöver du ha en instans av <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> igång eller en API som hanterar dessa begäranden. <br />Apprise API-urlen bör vara hela URL-sökvägen för att skicka meddelandet, t.ex., om din API-instans är tillgänglig på <code>http://192.168.1.1:8337</code>, bör du ange <code>http://192.168.1.1:8337/notify</code>.",
"MessageAuthenticationLegacyTokenWarning": "Legacy API-koder kommer att raderas i framtiden. Använd denna istället: <a href=\"/config/api-keys\">API Keys</a>.",
"MessageAuthenticationOIDCChangesRestart": "Du måste starta om servern efter att du ändrat eller adderat OIDC (OpenID Connect).",
"MessageAuthenticationSecurityMessage": "Identifieringen av användare har förbättrats av säkerhetsskäl. Alla användare måste därför logga in på nytt.",
"MessageBackupsDescription": "Säkerhetskopior inkluderar användare, användarnas framsteg, biblioteksobjekt,<br>serverinställningar och bilder lagrade i <code>/metadata/items</code> & <code>/metadata/authors</code>.<br>De inkluderar <strong>INTE</strong> några filer lagrade i dina biblioteksmappar.",
"MessageBackupsLocationEditNote": "OBS: När du ändrar plats för säkerhetskopiorna så flyttas INTE gamla säkerhetskopior dit",
"MessageBackupsLocationNoEditNote": "OBS: Platsen där säkerhetskopiorna lagras bestäms av en central inställning och kan inte ändras här.",
@@ -712,8 +737,10 @@
"MessageChapterErrorStartGteDuration": "Ogiltig starttid, måste vara mindre än ljudbokens längd",
"MessageChapterErrorStartLtPrev": "Ogiltig starttid, måste vara större än eller lika med föregående kapitlets starttid",
"MessageChapterStartIsAfter": "Kapitlets start är efter din ljudboks slut",
"MessageChaptersNotFound": "Inga kapitel kunde hittas",
"MessageCheckingCron": "Kontrollerar cron...",
"MessageConfirmCloseFeed": "Är du säker på att du vill stänga detta flöde?",
"MessageConfirmDeleteApiKey": "Är du säker på att du vill radera API-nyckel \"{0}\"?",
"MessageConfirmDeleteBackup": "Är du säker på att du vill radera säkerhetskopian för {0}?",
"MessageConfirmDeleteDevice": "Är du säkert på att du vill radera enheten för e-böcker \"{0}\"?",
"MessageConfirmDeleteFile": "Detta kommer att radera filen från ditt filsystem. Är du säker?",
@@ -753,6 +780,7 @@
"MessageConfirmRenameTagWarning": "VARNING! En liknande tagg med annat skrivsätt finns redan \"{0}\".",
"MessageConfirmResetProgress": "Är du säker på att du vill nollställa ditt framsteg?",
"MessageConfirmSendEbookToDevice": "Är du säker på att du vill skicka {0} e-bok \"{1}\" till enheten \"{2}\"?",
"MessageConfirmUnlinkOpenId": "Är du säker på att du vill koppla bort denna användare från OpenID?",
"MessageDaysListenedInTheLastYear": "{0} dagars lyssnande det senaste året",
"MessageDownloadingEpisode": "Laddar ner avsnitt",
"MessageDragFilesIntoTrackOrder": "Ändra ordningen genom att klicka och dra filerna till rätt plats",
@@ -764,6 +792,7 @@
"MessageForceReScanDescription": "kommer att göra en omgångssökning av alla filer som en färsk sökning. ID3-taggar för ljudfiler, OPF-filer och textfiler kommer att sökas som nya.",
"MessageImportantNotice": "Viktig meddelande!",
"MessageInsertChapterBelow": "Infoga kapitel nedanför",
"MessageInvalidAsin": "Felaktig ASIN-kod",
"MessageItemsSelected": "{0} objekt markerade",
"MessageItemsUpdated": "{0} Objekt uppdaterade",
"MessageJoinUsOn": "Anslut dig till oss på",
@@ -833,8 +862,10 @@
"MessageScheduleRunEveryWeekdayAtTime": "Startar varje {0} klockan {1}",
"MessageSearchResultsFor": "Sökresultat för",
"MessageSelected": "{0} valda",
"MessageSeriesSequenceCannotContainSpaces": "Ordningsnumret i en serie får inte innehålla ett mellanslag",
"MessageServerCouldNotBeReached": "Servern kunde inte nås",
"MessageSetChaptersFromTracksDescription": "Använd varje ljudfil som ett kapitel och ljudfilens namn som kapitlets rubrik",
"MessageShareExpirationWillBe": "Giltig till kommer att bli <strong>{0}</strong>",
"MessageShareExpiresIn": "Upphör om {0}",
"MessageStartPlaybackAtTime": "Starta uppspelning av \"{0}\" vid tidpunkt {1}?",
"MessageTaskAudioFileNotWritable": "Det går inte att skriva till ljudfilen \"{0}\"",
@@ -912,6 +943,7 @@
"StatsTotalDuration": "Med den totala längden…",
"StatsYearInReview": "- SAMMANSTÄLLNING AV ÅRET",
"ToastAccountUpdateSuccess": "Kontot har uppdaterats",
"ToastAppriseUrlRequired": "En adress till Apprise måste anges",
"ToastAsinRequired": "En ASIN-kod krävs",
"ToastAuthorImageRemoveSuccess": "Författarens bild borttagen",
"ToastAuthorNotFound": "Författaren \"{0}\" kunde inte identifieras",
@@ -960,6 +992,8 @@
"ToastEpisodeDownloadQueueClearFailed": "Misslyckades med att tömma kön",
"ToastEpisodeDownloadQueueClearSuccess": "Kö för nedladdning av avsnitt har tömts",
"ToastEpisodeUpdateSuccess": "{0} avsnitt uppdaterades",
"ToastFailedToCreate": "Misslyckades med att addera",
"ToastFailedToDelete": "Misslyckades med att radera",
"ToastFailedToLoadData": "Misslyckades med att ladda data",
"ToastFailedToMatch": "Misslyckades med att matcha",
"ToastFailedToShare": "Misslyckades med att dela",
@@ -990,6 +1024,7 @@
"ToastMetadataFilesRemovedSuccess": "{0} 'metadata.{1}' raderades",
"ToastNameEmailRequired": "Ett namn och en e-postadress måste anges",
"ToastNameRequired": "Ett namn måste anges",
"ToastNewApiKeyUserError": "En användare måste väljas",
"ToastNewEpisodesFound": "Hittade {0} nya avsnitt",
"ToastNewUserCreatedFailed": "Misslyckades med att skapa kontot \"{0}\"",
"ToastNewUserCreatedSuccess": "Ett nytt konto har skapats",
@@ -1002,6 +1037,7 @@
"ToastNoUpdatesNecessary": "Inga uppdateringar var nödvändiga",
"ToastNotificationCreateFailed": "Misslyckades med att skapa meddelandet",
"ToastNotificationDeleteFailed": "Misslyckades med att radera meddelandet",
"ToastNotificationSettingsUpdateSuccess": "Inställningarna för meddelanden har ändrats",
"ToastNotificationUpdateSuccess": "Meddelandet har uppdaterats",
"ToastPlaylistCreateFailed": "Det gick inte att skapa spellistan",
"ToastPlaylistCreateSuccess": "Spellistan skapad",
@@ -1045,6 +1081,8 @@
"ToastSortingPrefixesUpdateSuccess": "{0} begrepp för sortering har uppdateras",
"ToastTitleRequired": "En titel måste anges",
"ToastUnknownError": "Ett okänt fel inträffade",
"ToastUnlinkOpenIdFailed": "Misslyckades med att koppla bort användaren från OpenID",
"ToastUnlinkOpenIdSuccess": "Användaren har kopplats bort från OpenID",
"ToastUploaderFilepathExistsError": "En fil med namnet \"{0}\" finns redan på servern",
"ToastUserDeleteFailed": "Misslyckades med att ta bort användaren",
"ToastUserDeleteSuccess": "Användaren borttagen",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "Ekle",
"ButtonAddApiKey": "API Anahtarı Ekle",
"ButtonAddChapters": "Bölüm Ekle",
"ButtonAddDevice": "Cihaz Ekle",
"ButtonAddLibrary": "Kütüphane Ekle",
@@ -20,6 +21,7 @@
"ButtonChooseAFolder": "Klasör seç",
"ButtonChooseFiles": "Dosya seç",
"ButtonClearFilter": "Filtreyi Temizle",
"ButtonClose": "Kapat",
"ButtonCloseFeed": "Akışı Kapat",
"ButtonCloseSession": "Acık Oturumu Kapat",
"ButtonCollections": "Koleksiyonlar",
@@ -95,7 +97,17 @@
"ButtonSearch": "Ara",
"ButtonSelectFolderPath": "Klasör Yolunu Seç",
"ButtonSeries": "Seriler",
"ButtonShare": "Paylaş",
"ButtonStats": "İstatistikler",
"ButtonSubmit": "Gönder",
"ButtonTest": "Dene",
"ButtonUnlinkOpenId": "OpenID ilişiğini kaldır",
"ButtonUpload": "Yükle",
"ButtonUploadBackup": "Yedeği Yükle",
"ButtonUploadCover": "Kapağı Yükle",
"ButtonUploadOPMLFile": "OPML Dosyası Yükle",
"ButtonUserDelete": "{0} kullanıcısını sil.",
"ButtonUserEdit": "{0} kullanıcısını düzenle",
"ButtonViewAll": "Tümünü Görüntüle",
"ButtonYes": "Evet",
"ErrorUploadFetchMetadataAPI": "Üst veriyi almakta hata",
@@ -104,6 +116,7 @@
"HeaderAccount": "Hesap",
"HeaderAddCustomMetadataProvider": "Özel Üstveri Sağlayıcısı Ekle",
"HeaderAdvanced": "Gelişmiş",
"HeaderApiKeys": "API Anahtarları",
"HeaderAppriseNotificationSettings": "Bildirim Ayarlarının Haberini Ver",
"HeaderAudioTracks": "Ses Kanalları",
"HeaderAudiobookTools": "Sesli Kitap Dosya Yönetim Araçları",
@@ -111,13 +124,23 @@
"HeaderBackups": "Yedeklemeler",
"HeaderChangePassword": "Parolayı Değiştir",
"HeaderChapters": "Bölümler",
"HeaderChooseAFolder": "Klasör Seç",
"HeaderCollection": "Koleksiyon",
"HeaderCollectionItems": "Koleksiyon Öğeleri",
"HeaderCover": "Kapak",
"HeaderCurrentDownloads": "Geçerli İndirmeler",
"HeaderCustomMessageOnLogin": "Girişteki Kişiselleştirilmiş Mesaj",
"HeaderCustomMetadataProviders": "Kişiselleştirilmiş Metadata Sağlayıcıları",
"HeaderDetails": "Detaylar",
"HeaderDownloadQueue": "Kuyruktakileri İndir",
"HeaderEbookFiles": "Ebook Dosyaları",
"HeaderEmail": "Email",
"HeaderEmailSettings": "Email Ayarları",
"HeaderEpisodes": "Bölümler",
"HeaderEreaderDevices": "Ekitap Cihazları",
"HeaderEreaderSettings": "Ereader Ayarları",
"HeaderFiles": "Dosyalar",
"HeaderFindChapters": "Bölümleri Bul",
"HeaderIgnoredFiles": "Görmezden Gelinen Dosyalar",
"HeaderItemFiles": "Öğe Dosyaları",
"HeaderItemMetadataUtils": "Öğe Üstveri Araçları",

View File

@@ -1,9 +1,10 @@
{
"ButtonAdd": "Додати",
"ButtonAddApiKey": "Додати ключ API",
"ButtonAddChapters": "Додати глави",
"ButtonAddDevice": "Додати пристрій",
"ButtonAddLibrary": "Додати бібліотеку",
"ButtonAddPodcasts": "Додати подкаст",
"ButtonAddPodcasts": "Додати подкасти",
"ButtonAddUser": "Додати користувача",
"ButtonAddYourFirstLibrary": "Додайте вашу першу бібліотеку",
"ButtonApply": "Застосувати",
@@ -16,10 +17,11 @@
"ButtonCancel": "Скасувати",
"ButtonCancelEncode": "Скасувати кодування",
"ButtonChangeRootPassword": "Змінити кореневий пароль",
"ButtonCheckAndDownloadNewEpisodes": "Перевірити та завантажити нові епізоди",
"ButtonCheckAndDownloadNewEpisodes": "Перевірити та скачати нові епізоди",
"ButtonChooseAFolder": "Обрати теку",
"ButtonChooseFiles": "Обрати файли",
"ButtonClearFilter": "Очистити фільтр",
"ButtonClose": "Закрити",
"ButtonCloseFeed": "Закрити стрічку",
"ButtonCloseSession": "Закрити відкритий сеанс",
"ButtonCollections": "Добірки",
@@ -32,8 +34,8 @@
"ButtonEditChapters": "Редагувати глави",
"ButtonEditPodcast": "Редагувати подкаст",
"ButtonEnable": "Увімкнути",
"ButtonFireAndFail": "Вогонь і невдача",
"ButtonFireOnTest": "Випробування на вогнестійкість",
"ButtonFireAndFail": "Виконати і завершити з помилкою",
"ButtonFireOnTest": "Виконати подію onTest",
"ButtonForceReScan": "Примусово сканувати",
"ButtonFullPath": "Повний шлях",
"ButtonHide": "Приховати",
@@ -44,7 +46,7 @@
"ButtonLatest": "Останні",
"ButtonLibrary": "Бібліотека",
"ButtonLogout": "Вийти",
"ButtonLookup": "Пошук",
"ButtonLookup": "Пошуки",
"ButtonManageTracks": "Керувати доріжками",
"ButtonMapChapterTitles": "Призначити назви глав",
"ButtonMatchAllAuthors": "Віднайти усіх авторів",
@@ -57,7 +59,7 @@
"ButtonOpenFeed": "Відкрити стрічку",
"ButtonOpenManager": "Відкрити менеджер",
"ButtonPause": "Пауза",
"ButtonPlay": "Слухати",
"ButtonPlay": "Відтворити",
"ButtonPlayAll": "Відтворити все",
"ButtonPlaying": "Відтворюється",
"ButtonPlaylists": "Списки відтворення",
@@ -86,7 +88,7 @@
"ButtonResetToDefault": "Скинути до стандартних",
"ButtonRestore": "Відновити",
"ButtonSave": "Зберегти",
"ButtonSaveAndClose": "Зберегти та закрити",
"ButtonSaveAndClose": "Зберегти і закрити",
"ButtonSaveTracklist": "Зберегти порядок",
"ButtonScan": "Сканувати",
"ButtonScanLibrary": "Сканувати бібліотеку",
@@ -103,7 +105,7 @@
"ButtonStartMetadataEmbed": "Почати вбудування метаданих",
"ButtonStats": "Статистика",
"ButtonSubmit": "Надіслати",
"ButtonTest": "Перевірити",
"ButtonTest": "Тест",
"ButtonUnlinkOpenId": "Вимкнути OpenID",
"ButtonUpload": "Завантажити",
"ButtonUploadBackup": "Завантажити резервну копію",
@@ -115,10 +117,11 @@
"ButtonYes": "Так",
"ErrorUploadFetchMetadataAPI": "Помилка при отриманні метаданих",
"ErrorUploadFetchMetadataNoResults": "Не вдалося отримати метадані — спробуйте оновити заголовок та/або автора",
"ErrorUploadLacksTitle": "Назва обов'язкова",
"ErrorUploadLacksTitle": "Потрібна назва",
"HeaderAccount": "Профіль",
"HeaderAddCustomMetadataProvider": "Додати користувацький постачальник метаданих",
"HeaderAdvanced": "Розширені",
"HeaderApiKeys": "Ключі API",
"HeaderAppriseNotificationSettings": "Налаштування сповіщень Apprise",
"HeaderAudioTracks": "Аудіодоріжки",
"HeaderAudiobookTools": "Інструменти керування файлами книг",
@@ -130,11 +133,11 @@
"HeaderCollection": "Добірка",
"HeaderCollectionItems": "Елементи добірки",
"HeaderCover": "Обкладинка",
"HeaderCurrentDownloads": "Поточні завантаження",
"HeaderCurrentDownloads": "Поточні скачування",
"HeaderCustomMessageOnLogin": "Повідомлення при вході",
"HeaderCustomMetadataProviders": "Постачальники метаданих",
"HeaderDetails": "Подробиці",
"HeaderDownloadQueue": "Черга завантажень",
"HeaderDownloadQueue": "Черга скачувань",
"HeaderEbookFiles": "Файли електронних книг",
"HeaderEmail": "Електронна пошта",
"HeaderEmailSettings": "Налаштування електронної пошти",
@@ -152,16 +155,17 @@
"HeaderLibraryFiles": "Файли бібліотеки",
"HeaderLibraryStats": "Статистика бібліотеки",
"HeaderListeningSessions": "Сеанси прослуховування",
"HeaderListeningStats": "Статистика відтворення",
"HeaderListeningStats": "Статистика прослуховування",
"HeaderLogin": "Вхід",
"HeaderLogs": "Журнал",
"HeaderManageGenres": "Керувати жанрами",
"HeaderManageTags": "Керувати мітками",
"HeaderMapDetails": "Призначити подробиці",
"HeaderMatch": "Пошук",
"HeaderMatch": "Допасуй",
"HeaderMetadataOrderOfPrecedence": "Порядок метаданих",
"HeaderMetadataToEmbed": "Вбудувати метадані",
"HeaderNewAccount": "Новий профіль",
"HeaderNewApiKey": "Новий ключ API",
"HeaderNewLibrary": "Нова бібліотека",
"HeaderNotificationCreate": "Створити сповіщення",
"HeaderNotificationUpdate": "Оновити сповіщення",
@@ -176,7 +180,7 @@
"HeaderPlayerSettings": "Налаштування програвача",
"HeaderPlaylist": "Список відтворення",
"HeaderPlaylistItems": "Елементи списку відтворення",
"HeaderPodcastsToAdd": "Додати подкасти",
"HeaderPodcastsToAdd": "Подкасти для додання",
"HeaderPresets": "Пресети",
"HeaderPreviewCover": "Попередній перегляд",
"HeaderRSSFeedGeneral": "Подробиці RSS",
@@ -186,7 +190,7 @@
"HeaderRemoveEpisodes": "Видалити епізодів: {0}",
"HeaderSavedMediaProgress": "Збережений прогрес медіа",
"HeaderSchedule": "Розклад",
"HeaderScheduleEpisodeDownloads": "Запланувати автоматичне завантаження епізодів",
"HeaderScheduleEpisodeDownloads": "Запланувати автоматичне скачування епізодів",
"HeaderScheduleLibraryScans": "Розклад автосканування бібліотеки",
"HeaderSession": "Сеанс",
"HeaderSetBackupSchedule": "Встановити розклад резервного копіювання",
@@ -195,6 +199,7 @@
"HeaderSettingsExperimental": "Експериментальні функції",
"HeaderSettingsGeneral": "Основне",
"HeaderSettingsScanner": "Сканер",
"HeaderSettingsSecurity": "Безпека",
"HeaderSettingsWebClient": "Вебклієнт",
"HeaderSleepTimer": "Таймер вимкнення",
"HeaderStatsLargestItems": "Найбільші елементи",
@@ -206,6 +211,7 @@
"HeaderTableOfContents": "Зміст",
"HeaderTools": "Інструменти",
"HeaderUpdateAccount": "Оновити профіль",
"HeaderUpdateApiKey": "Оновити ключ API",
"HeaderUpdateAuthor": "Оновити автора",
"HeaderUpdateDetails": "Оновити подробиці",
"HeaderUpdateLibrary": "Оновити бібліотеку",
@@ -223,21 +229,25 @@
"LabelActivities": "Діяльність",
"LabelActivity": "Активність",
"LabelAddToCollection": "Додати у добірку",
"LabelAddToCollectionBatch": "Додати книги до добірки: {0}",
"LabelAddToCollectionBatch": "Додати {0} книг до добірки",
"LabelAddToPlaylist": "Додати до списку відтворення",
"LabelAddToPlaylistBatch": "Додано елементів у список відтворення: {0}",
"LabelAddToPlaylistBatch": "Додати {0} елементів до списку відтворення",
"LabelAddedAt": "Дата додавання",
"LabelAddedDate": "Додано {0}",
"LabelAdminUsersOnly": "Тільки для адміністраторів",
"LabelAll": "Усе",
"LabelAllEpisodesDownloaded": "Усі серії завантажено",
"LabelAllEpisodesDownloaded": "Усі епізоди скачано",
"LabelAllUsers": "Усі користувачі",
"LabelAllUsersExcludingGuests": "Усі, крім гостей",
"LabelAllUsersIncludingGuests": "Усі, включно з гостями",
"LabelAlreadyInYourLibrary": "Вже у вашій бібліотеці",
"LabelApiKeyCreated": "Ключ API \"{0}\" успішно створено.",
"LabelApiKeyCreatedDescription": "Обов’язково скопіюйте ключ API зараз, оскільки ви більше не зможете його побачити.",
"LabelApiKeyUser": "Діяти від імені користувача",
"LabelApiKeyUserDescription": "Цей ключ API матиме ті самі дозволи, що й користувач, від імені якого він діє. Це відображатиметься в журналах так само, як і в разі надсилання запиту користувачем.",
"LabelApiToken": "Токен API",
"LabelAppend": "Додати",
"LabelAudioBitrate": "Бітрейт аудіо (напр. 128k)",
"LabelAudioBitrate": "Бітрейт аудіо (наприклад, 128k)",
"LabelAudioChannels": "Канали аудіо (1 або 2)",
"LabelAudioCodec": "Аудіокодек",
"LabelAuthor": "Автор",
@@ -256,18 +266,18 @@
"LabelBackupLocation": "Розташування резервних копій",
"LabelBackupsEnableAutomaticBackups": "Автоматичне резервне копіювання",
"LabelBackupsEnableAutomaticBackupsHelp": "Резервні копії збережено у /metadata/backups",
"LabelBackupsMaxBackupSize": "Максимальний розмір резервної копії (у ГБ) (0 — необмежене)",
"LabelBackupsMaxBackupSize": "Максимальний розмір резервної копії (у ГБ) (0 — без обмежень)",
"LabelBackupsMaxBackupSizeHelp": "У якості захисту від неправильного налаштування, резервну копію не буде збережено, якщо її розмір перевищуватиме вказаний.",
"LabelBackupsNumberToKeep": "Кількість резервних копій",
"LabelBackupsNumberToKeepHelp": "Лиш 1 резервну копію буде видалено за раз, тож якщо їх багато, то вам варто видалити їх вручну.",
"LabelBackupsNumberToKeepHelp": "Видаляється лише 1 резервна копія за раз, тому якщо у вас більше копій, видаліть їх вручну.",
"LabelBitrate": "Бітрейт",
"LabelBonus": "Бонус",
"LabelBooks": "Книги",
"LabelBooks": "Книг",
"LabelButtonText": "Текст кнопки",
"LabelByAuthor": "від {0}",
"LabelChangePassword": "Змінити пароль",
"LabelChannels": "Канали",
"LabelChapterCount": "{0} Глав",
"LabelChapterCount": "{0} глав",
"LabelChapterTitle": "Назва глави",
"LabelChapters": "Глави",
"LabelChaptersFound": "глав знайдено",
@@ -284,6 +294,7 @@
"LabelContinueListening": "Слухати далі",
"LabelContinueReading": "Читати далі",
"LabelContinueSeries": "Продовжити серії",
"LabelCorsAllowed": "Дозволені джерела CORS",
"LabelCover": "Обкладинка",
"LabelCoverImageURL": "URL-адреса обкладинки",
"LabelCoverProvider": "Постачальник покриття",
@@ -304,9 +315,9 @@
"LabelDiscFromFilename": "Диск за назвою файлу",
"LabelDiscFromMetadata": "Диск за метаданими",
"LabelDiscover": "Огляд",
"LabelDownload": "Завантажити",
"LabelDownloadNEpisodes": "Завантажити епізодів: {0}",
"LabelDownloadable": "Можна завантажити",
"LabelDownload": "Скачати",
"LabelDownloadNEpisodes": "Скачати {0} епізодів",
"LabelDownloadable": "Можна скачати",
"LabelDuration": "Тривалість",
"LabelDurationComparisonExactMatch": "(повний збіг)",
"LabelDurationComparisonLonger": "(на {0} довше)",
@@ -346,16 +357,20 @@
"LabelExample": "Приклад",
"LabelExpandSeries": "Розгорнути серії",
"LabelExpandSubSeries": "Розгорнути підсерії",
"LabelExplicit": "Відверта",
"LabelExpired": "Термін дії минув",
"LabelExpiresAt": "Термін дії закінчується о",
"LabelExpiresInSeconds": "Термін дії закінчується через (секунди)",
"LabelExpiresNever": "Ніколи",
"LabelExplicit": "Відвертий",
"LabelExplicitChecked": "Відверта (з прапорцем)",
"LabelExplicitUnchecked": "Не відверта (без прапорця)",
"LabelExportOPML": "Експорт OPML",
"LabelFeedURL": "Адреса стрічки",
"LabelFetchingMetadata": "Отримання метаданих",
"LabelFile": "Файл",
"LabelFileBirthtime": "Дата створення",
"LabelFileBirthtime": "Дата створення файлу",
"LabelFileBornDate": "Народився {0}",
"LabelFileModified": "Дата змінення",
"LabelFileModified": "Дата зміни файлу",
"LabelFileModifiedDate": "Змінено {0}",
"LabelFilename": "Ім'я файлу",
"LabelFilterByUser": "Фільтрувати за користувачем",
@@ -395,7 +410,7 @@
"LabelIntervalEvery6Hours": "Кожні 6 годин",
"LabelIntervalEveryDay": "Щодня",
"LabelIntervalEveryHour": "Щогодини",
"LabelIntervalEveryMinute": "Кожну хвилину",
"LabelIntervalEveryMinute": "Щохвилини",
"LabelInvert": "Інвертувати",
"LabelItem": "Елемент",
"LabelJumpBackwardAmount": "Час переходу назад",
@@ -405,6 +420,7 @@
"LabelLanguages": "Мови",
"LabelLastBookAdded": "Останню книгу додано",
"LabelLastBookUpdated": "Останню книгу оновлено",
"LabelLastProgressDate": "Останній прогрес: {0}",
"LabelLastSeen": "Активність",
"LabelLastTime": "Останній час",
"LabelLastUpdate": "Останнє оновлення",
@@ -417,6 +433,7 @@
"LabelLibraryFilterSublistEmpty": "Ні {0}",
"LabelLibraryItem": "Елемент бібліотеки",
"LabelLibraryName": "Назва бібліотеки",
"LabelLibrarySortByProgress": "Прогрес оновлено",
"LabelLimit": "Обмеження",
"LabelLineSpacing": "Відстань між рядками",
"LabelListenAgain": "Слухати знову",
@@ -425,12 +442,13 @@
"LabelLogLevelWarn": "Увага",
"LabelLookForNewEpisodesAfterDate": "Шукати нові епізоди після вказаної дати",
"LabelLowestPriority": "Найнижчий пріоритет",
"LabelMatchConfidence": "Впевненість",
"LabelMatchExistingUsersBy": "Шукати наявних користувачів за",
"LabelMatchExistingUsersByDescription": "Використовується для підключення наявних користувачів. Після підключення користувач отримає унікальний id від вашого сервісу SSO",
"LabelMaxEpisodesToDownload": "Максимальна кількість епізодів для завантаження. Використовуйте 0 для необмеженої кількості.",
"LabelMaxEpisodesToDownloadPerCheck": "Максимальна кількість нових епізодів для завантаження за перевірку",
"LabelMaxEpisodesToDownload": "Максимальна кількість епізодів для скачування. Використовуйте 0 для необмеженої кількості.",
"LabelMaxEpisodesToDownloadPerCheck": "Максимальна кількість нових епізодів для скачування за перевірку",
"LabelMaxEpisodesToKeep": "Максимальна кількість епізодів для зберігання",
"LabelMaxEpisodesToKeepHelp": "Значення 0 не встановлює обмеження. Після автоматичного завантаження нового епізоду, буде видалено найстаріший епізод, якщо у вас більше ніж X епізодів. Видаляється лише 1 епізод за одне нове завантаження.",
"LabelMaxEpisodesToKeepHelp": "Значення 0 — без обмежень. Після автоматичного завантаження нового епізоду буде видалено найстаріший, якщо їх більше X. Видаляється лише 1 епізод за одне нове завантаження.",
"LabelMediaPlayer": "Програвач медіа",
"LabelMediaType": "Тип медіа",
"LabelMetaTag": "Метатег",
@@ -455,6 +473,7 @@
"LabelNewestEpisodes": "Нові епізоди",
"LabelNextBackupDate": "Дата наступного резервного копіювання",
"LabelNextScheduledRun": "Наступний запланований запуск",
"LabelNoApiKeys": "Без ключів API",
"LabelNoCustomMetadataProviders": "Без постачальників метаданих",
"LabelNoEpisodesSelected": "Не вибрано жодного епізоду",
"LabelNotFinished": "Незавершені",
@@ -485,7 +504,7 @@
"LabelPermissionsAccessExplicitContent": "Доступ до відвертого вмісту",
"LabelPermissionsCreateEreader": "Можна створити читалку",
"LabelPermissionsDelete": "Може видаляти",
"LabelPermissionsDownload": "Може завантажувати",
"LabelPermissionsDownload": "Може скачувати",
"LabelPermissionsUpdate": "Може оновлювати",
"LabelPermissionsUpload": "Може завантажувати",
"LabelPersonalYearReview": "Ваші підсумки року ({0})",
@@ -514,7 +533,7 @@
"LabelPublishers": "Видавці",
"LabelRSSFeedCustomOwnerEmail": "Користувацька електронна адреса власника",
"LabelRSSFeedCustomOwnerName": "Користувацьке ім'я власника",
"LabelRSSFeedOpen": "RSS-канал відкрито",
"LabelRSSFeedOpen": "RSS-канал відкритий",
"LabelRSSFeedPreventIndexing": "Запобігати індексації",
"LabelRSSFeedSlug": "Назва RSS-каналу",
"LabelRSSFeedURL": "Адреса RSS-каналу",
@@ -542,8 +561,9 @@
"LabelSeason": "Сезон",
"LabelSeasonNumber": "Сезон #{0}",
"LabelSelectAll": "Вибрати все",
"LabelSelectAllEpisodes": "Вибрати всі серії",
"LabelSelectEpisodesShowing": "Обрати показані епізоди: {0}",
"LabelSelectAllEpisodes": "Вибрати всі епізоди",
"LabelSelectEpisodesShowing": "Вибрати {0} показаних епізодів",
"LabelSelectUser": "Виберіть користувача",
"LabelSelectUsers": "Вибрати користувачів",
"LabelSendEbookToDevice": "Надіслати електронну книгу на...",
"LabelSequence": "Послідовність",
@@ -595,7 +615,7 @@
"LabelSettingsStoreMetadataWithItemHelp": "За замовчуванням файли метаданих зберігаються у /metadata/items. Цей параметр увімкне збереження метаданих у теці елемента бібліотеки",
"LabelSettingsTimeFormat": "Формат часу",
"LabelShare": "Поділитися",
"LabelShareDownloadableHelp": "Дозволяє користувачам із посиланням для спільного доступу завантажувати zip-файл елемента бібліотеки.",
"LabelShareDownloadableHelp": "Дозволяє користувачам із посиланням для спільного доступу скачування zip-файлу елемента бібліотеки.",
"LabelShareOpen": "Поділитися відкрито",
"LabelShareURL": "Поділитися URL",
"LabelShowAll": "Показати все",
@@ -640,6 +660,7 @@
"LabelTheme": "Тема",
"LabelThemeDark": "Темна",
"LabelThemeLight": "Світла",
"LabelThemeSepia": "Сепія",
"LabelTimeBase": "Шкала часу",
"LabelTimeDurationXHours": "{0} години",
"LabelTimeDurationXMinutes": "{0} хвилини",
@@ -708,97 +729,103 @@
"MessageAddToPlayerQueue": "Додати до черги відтворення",
"MessageAppriseDescription": "Щоб скористатися цією функцією, вам потрібно мати запущену <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> або API, що оброблятиме ті ж запити. <br />Аби надсилати сповіщення, URL-адреса API Apprise мусить бути повною, наприклад, якщо ваш API розміщено за адресою <code>http://192.168.1.1:8337</code>, то необхідно вказати адресу <code>http://192.168.1.1:8337/notify</code>.",
"MessageAsinCheck": "Переконайтесь, що ви використовуєте ASIN з правильної регіональної Audible зони, а не з Amazon.",
"MessageAuthenticationLegacyTokenWarning": "Застарілі токени API будуть видалені в майбутньому. Натомість використовуйте <a href=\"/config/api-keys\">Ключі API</a>.",
"MessageAuthenticationOIDCChangesRestart": "Перезавантажте сервер після збереження, щоб застосувати зміни OIDC.",
"MessageAuthenticationSecurityMessage": "Автентифікацію покращено для безпеки. Усім користувачам потрібно повторно увійти в систему.",
"MessageBackupsDescription": "Резервні копії містять користувачів, прогрес, подробиці елементів бібліотеки, налаштування сервера та зображення з <code>/metadata/items</code> та <code>/metadata/authors</code>. Резервні копії <strong>не</strong> містять жодних файлів з тек бібліотеки.",
"MessageBackupsLocationEditNote": "Примітка: оновлення розташування резервної копії не переносить та не змінює існуючих копій",
"MessageBackupsLocationNoEditNote": "Примітка: розташування резервної копії встановлюється за допомогою змінної середовища та не може бути змінене тут.",
"MessageBackupsLocationPathEmpty": "Шлях розташування резервної копії не може бути порожнім",
"MessageBatchEditPopulateMapDetailsAllHelp": "Заповнити увімкнені поля даними з усіх елементів. Поля з кількома значеннями буде об’єднано",
"MessageBatchEditPopulateMapDetailsItemHelp": "Заповніть увімкнені поля деталей карти даними з цього елемента",
"MessageBatchEditPopulateMapDetailsItemHelp": "Заповнити увімкнені поля деталізації даними з цього елемента",
"MessageBatchQuickMatchDescription": "Швидкий пошук спробує знайти відсутні обкладинки та метадані обраних елементів. Увімкніть налаштування нижче, аби дозволити заміну наявних обкладинок та/або метаданих під час швидкого пошуку.",
"MessageBookshelfNoCollections": "Ви не створили жодної добірки",
"MessageBookshelfNoCollections": "Ви ще не створили жодної добірки",
"MessageBookshelfNoCollectionsHelp": "Колекції публічні. Їх можуть бачити всі користувачі, які мають доступ до бібліотеки.",
"MessageBookshelfNoRSSFeeds": "Немає відкритих RSS-каналів",
"MessageBookshelfNoResultsForFilter": "Немає результатів з фільтром \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "Немає результатів за запитом",
"MessageBookshelfNoSeries": "Серії відсутні",
"MessageChapterEndIsAfter": "Кінець глави знаходиться після закінчення книги",
"MessageChapterErrorFirstNotZero": "Перша глава мусить починатися з 0",
"MessageChapterErrorStartGteDuration": "Час початку мусить бути меншим за тривалість аудіокниги",
"MessageChapterErrorStartLtPrev": "Неприпустимий час початку, має бути більшим за час початку попередньої глави",
"MessageChapterStartIsAfter": "Початок глави знаходиться після закінчення книги",
"MessageBookshelfNoSeries": "У вас немає серій",
"MessageChapterEndIsAfter": "Кінець глави після завершення аудіокниги",
"MessageChapterErrorFirstNotZero": "Перша глава повинна починатися з 0",
"MessageChapterErrorStartGteDuration": "Час початку має бути меншим за тривалість аудіокниги",
"MessageChapterErrorStartLtPrev": "Час початку має бути більшим або рівним часу початку попередньої глави",
"MessageChapterStartIsAfter": "Початок глави після завершення аудіокниги",
"MessageChaptersNotFound": "Розділи не знайдені",
"MessageCheckingCron": "Перевірка планувальника...",
"MessageConfirmCloseFeed": "Ви дійсно бажаєте закрити цей канал?",
"MessageConfirmDeleteApiKey": "Ви впевнені, що хочете видалити ключ API? \"{0}\"?",
"MessageConfirmDeleteBackup": "Ви дійсно бажаєте видалити резервну копію за {0}?",
"MessageConfirmDeleteDevice": "Ви впевнені, що хочете видалити пристрій для читання \"{0}\"?",
"MessageConfirmDeleteFile": "Файл буде видалено з вашої файлової системи. Ви впевнені?",
"MessageConfirmDeleteLibrary": "Ви дійсно бажаєте назавжди видалити бібліотеку \"{0}\"?",
"MessageConfirmDeleteLibraryItem": "Елемент бібліотеки буде видалено з бази даних та вашої файлової системи. Ви впевнені?",
"MessageConfirmDeleteLibraryItems": "З бази даних та вашої файлової системи будуть видалені елементи бібліотеки: {0}. Ви впевнені?",
"MessageConfirmDeleteLibraryItem": "Елемент бібліотеки буде видалено з бази даних і файлової системи. Ви впевнені?",
"MessageConfirmDeleteLibraryItems": "Буде видалено {0} елементів бібліотеки з бази даних і файлової системи. Ви впевнені?",
"MessageConfirmDeleteMetadataProvider": "Ви впевнені, що хочете видалити користувацького постачальника метаданих \"{0}\"?",
"MessageConfirmDeleteNotification": "Ви впевнені, що хочете видалити це сповіщення?",
"MessageConfirmDeleteSession": "Ви дійсно бажаєте видалити цей сеанс?",
"MessageConfirmEmbedMetadataInAudioFiles": "Ви впевнені, що хочете вставити метадані в {0} аудіофайлів?",
"MessageConfirmEmbedMetadataInAudioFiles": "Ви впевнені, що хочете вбудувати метадані у {0} аудіофайлів?",
"MessageConfirmForceReScan": "Ви дійсно бажаєте примусово пересканувати?",
"MessageConfirmMarkAllEpisodesFinished": "Ви дійсно бажаєте позначити усі епізоди завершеними?",
"MessageConfirmMarkAllEpisodesNotFinished": "Ви дійсно бажаєте позначити усі епізоди незавершеними?",
"MessageConfirmMarkAllEpisodesFinished": "Ви впевнені, що хочете позначити всі епізоди завершеними?",
"MessageConfirmMarkAllEpisodesNotFinished": "Ви впевнені, що хочете позначити всі епізоди незавершеними?",
"MessageConfirmMarkItemFinished": "Ви впевнені, що хочете позначити \"{0}\" як завершене?",
"MessageConfirmMarkItemNotFinished": "Ви впевнені, що хочете позначити \"{0}\" як незавершене?",
"MessageConfirmMarkSeriesFinished": "Ви дійсно бажаєте позначити усі книги серії завершеними?",
"MessageConfirmMarkSeriesNotFinished": "Ви дійсно бажаєте позначити всі книги серії незавершеними?",
"MessageConfirmNotificationTestTrigger": "Активувати це сповіщення з тестовими даними?",
"MessageConfirmPurgeCache": "Очищення кешу видалить усю теку <code>/metadata/cache</code>. <br /><br />Ви дійсно бажаєте видалити теку кешу?",
"MessageConfirmPurgeItemsCache": "Очищення кешу елементів видалить усю теку <code>/metadata/cache/items</code>. <br />Ви певні?",
"MessageConfirmQuickEmbed": "Увага! Швидке вбудування не створює резервних копій ваших аудіо. Переконайтеся, що маєте копію ваших файлів.<br><br>Продовжити?",
"MessageConfirmQuickMatchEpisodes": "При виявленні співпадінь інформація про епізоди швидкого пошуку буде перезаписана. Будуть оновлені тільки несуперечливі епізоди. Ви впевнені?",
"MessageConfirmReScanLibraryItems": "Ви дійсно бажаєте пересканувати елементи: {0}?",
"MessageConfirmPurgeCache": "Очищення кешу видалить всю теку <code>/metadata/cache</code>. <br /><br />Ви впевнені, що хочете видалити теку кешу?",
"MessageConfirmPurgeItemsCache": "Очищення кешу елементів видалить всю теку <code>/metadata/cache/items</code>.<br />Ви впевнені?",
"MessageConfirmQuickEmbed": "Увага! Швидке вбудовування не створює резервних копій ваших аудіофайлів. Переконайтеся, що маєте резервну копію. <br><br>Продовжити?",
"MessageConfirmQuickMatchEpisodes": "Швидке співставлення епізодів перезапише подробиці, якщо знайдено відповідність. Оновлюються лише невідповідні епізоди. Ви впевнені?",
"MessageConfirmReScanLibraryItems": "Ви впевнені, що хочете пересканувати {0} елементів?",
"MessageConfirmRemoveAllChapters": "Ви дійсно бажаєте видалити усі глави?",
"MessageConfirmRemoveAuthor": "Ви дійсно бажаєте видалити автора \"{0}\"?",
"MessageConfirmRemoveCollection": "Ви дійсно бажаєте видалити добірку \"{0}\"?",
"MessageConfirmRemoveEpisode": "Ви дійсно бажаєте видалити епізод \"{0}\"?",
"MessageConfirmRemoveEpisodeNote": "Примітка: Це не видаляє аудіофайл, якщо не перемикає \"файл жорсткого видалення\"",
"MessageConfirmRemoveEpisodes": "Ви дійсно бажаєте видалити епізодів: {0}?",
"MessageConfirmRemoveListeningSessions": "Ви дійсно бажаєте видалити сеанси прослуховування: {0}?",
"MessageConfirmRemoveMetadataFiles": "Ви впевнені, що хочете видалити всі файли metadata.{0} у папках елементів вашої бібліотеки?",
"MessageConfirmRemoveNarrator": "Ви дійсно бажаєте видалити читця \"{0}\"?",
"MessageConfirmRemovePlaylist": "Ви дійсно бажаєте видалити список відтворення \"{0}\"?",
"MessageConfirmRenameGenre": "Ви дійсно бажаєте замінити жанр \"{0}\" на \"{1}\" для усіх елементів?",
"MessageConfirmRenameGenreMergeNote": "Примітка: такий жанр вже існує, тож їх буде об'єднано.",
"MessageConfirmRenameGenreWarning": "Увага! Вже існує схожий жанр у іншому регістрі \"{0}\".",
"MessageConfirmRenameTag": "Ви дійсно бажаєте замінити мітку \"{0}\" на \"{1}\" для усіх елементів?",
"MessageConfirmRenameTagMergeNote": "Примітка: така мітка вже існує, тож їх буде об'єднано.",
"MessageConfirmRenameTagWarning": "Увага! Вже існує схожа мітка у іншому регістрі \"{0}\".",
"MessageConfirmRemovePlaylist": "Ви дійсно бажаєте видалити ваш список відтворення \"{0}\"?",
"MessageConfirmRenameGenre": "Ви впевнені, що хочете перейменувати жанр \"{0}\" на \"{1}\" для всіх елементів?",
"MessageConfirmRenameGenreMergeNote": "Примітка: Такий жанр вже існує, тому вони будуть об'єднані.",
"MessageConfirmRenameGenreWarning": "Увага! Схожий жанр з іншом регістром вже існує \"{0}\".",
"MessageConfirmRenameTag": "Ви впевнені, що хочете перейменувати мітку \"{0}\" на \"{1}\" для всіх елементів?",
"MessageConfirmRenameTagMergeNote": "Примітка: Така мітка вже існує, тому вони будуть об'єднані.",
"MessageConfirmRenameTagWarning": "Увага! Схожа мітка з іншою регістром вже існує \"{0}\".",
"MessageConfirmResetProgress": "Ви впевнені, що хочете скинути свій прогрес?",
"MessageConfirmSendEbookToDevice": "Ви дійсно хочете відправити на пристрій \"{2}\" електроні книги: {0}, \"{1}\"?",
"MessageConfirmUnlinkOpenId": "Ви впевнені, що хочете відв'язати цього користувача від OpenID?",
"MessageDaysListenedInTheLastYear": "{0} днів, прослуханих за останній рік",
"MessageDownloadingEpisode": "Завантаження епізоду",
"MessageDownloadingEpisode": "Скачування епізоду",
"MessageDragFilesIntoTrackOrder": "Перетягніть файли до правильного порядку",
"MessageEmbedFailed": "Не вдалося вбудувати!",
"MessageEmbedFinished": "Вбудовано!",
"MessageEmbedQueue": "В черзі на вбудовування метаданих ({0} в черзі)",
"MessageEpisodesQueuedForDownload": "Епізодів у черзі завантаження: {0}",
"MessageEmbedFinished": "Вбудовування завершено!",
"MessageEmbedQueue": "У черзі на вбудовування метаданих ({0} у черзі)",
"MessageEpisodesQueuedForDownload": "{0} епізод(ів) у черзі на завантаження",
"MessageEreaderDevices": "Аби гарантувати отримання електронних книг, вам може знадобитися додати вказану вище адресу електронної пошти як правильного відправника на кожному з пристроїв зі списку нижче.",
"MessageFeedURLWillBe": "URL-адреса каналу буде {0}",
"MessageFetching": "Отримання...",
"MessageForceReScanDescription": "Просканує усі файли заново, неначе вперше. ID3-мітки, файли OPF та текстові файли будуть проскановані як нові.",
"MessageForceReScanDescription": "Просканує всі файли заново, як при першому скануванні. ID3-мітки, OPF-файли та текстові файли будуть проскановані як нові.",
"MessageHeatmapListeningTimeTooltip": "<strong>{0} прослуховування</strong> на {1}",
"MessageHeatmapNoListeningSessions": "Немає сеансів прослуховування на {0}",
"MessageImportantNotice": "Важливе повідомлення!",
"MessageInsertChapterBelow": "Введіть главу нижче",
"MessageInvalidAsin": "Невірний ASIN",
"MessageItemsSelected": "Вибрано елементів: {0}",
"MessageItemsUpdated": "Оновлено елементів: {0}",
"MessageItemsSelected": "Вибрано {0} елементів",
"MessageItemsUpdated": "Оновлено {0} елементів",
"MessageJoinUsOn": "Приєднуйтесь до",
"MessageLoading": "Завантаження...",
"MessageLoadingFolders": "Завантаження тек...",
"MessageLoadingFolders": "Завантаження папок...",
"MessageLogsDescription": "Журнали зберігаються у <code>/metadata/logs</code> як JSON-файли. Журнали збоїв зберігаються у <code>/metadata/logs/crash_logs.txt</code>.",
"MessageM4BFailed": "Помилка M4B!",
"MessageM4BFinished": "M4B створено!",
"MessageMapChapterTitles": "Встановіть назви глав вашої аудіокниги без визначення налаштувань тривалості",
"MessageMapChapterTitles": "Встановіть назви глав вашої аудіокниги без зміни часових міток",
"MessageMarkAllEpisodesFinished": "Позначити всі епізоди завершеними",
"MessageMarkAllEpisodesNotFinished": "Позначити всі епізоди незавершеними",
"MessageMarkAsFinished": "Позначити завершеним",
"MessageMarkAsNotFinished": "Позначити незавершеним",
"MessageMatchBooksDescription": "Спробує віднайти книгу у вказаному джерелі пошуку та встановити подробиці та обкладинку, яких бракує. Не перезаписує подробиці.",
"MessageMarkAsFinished": "Позначити як завершене",
"MessageMarkAsNotFinished": "Позначити як незавершене",
"MessageMatchBooksDescription": "Спробує знайти книги у бібліотеці у вибраному джерелі пошуку та заповнити порожні подробиці й обкладинку. Не перезаписує подробиці.",
"MessageNoAudioTracks": "Аудіодоріжки відсутні",
"MessageNoAuthors": "Автори відсутні",
"MessageNoBackups": "Резервні копії відсутні",
@@ -808,8 +835,8 @@
"MessageNoCoversFound": "Обкладинок не знайдено",
"MessageNoDescription": "Без опису",
"MessageNoDevices": "Немає пристроїв",
"MessageNoDownloadsInProgress": "Немає активних завантажень",
"MessageNoDownloadsQueued": "Немає завантажень у черзі",
"MessageNoDownloadsInProgress": "Немає активних скачувань",
"MessageNoDownloadsQueued": "Немає скачувань у черзі",
"MessageNoEpisodeMatchesFound": "Відповідних епізодів не знайдено",
"MessageNoEpisodes": "Епізоди відсутні",
"MessageNoFoldersAvailable": "Немає доступних тек",
@@ -818,21 +845,21 @@
"MessageNoItems": "Елементи відсутні",
"MessageNoItemsFound": "Елементів не знайдено",
"MessageNoListeningSessions": "Сеанси прослуховування відсутні",
"MessageNoLogs": "Немає журнали",
"MessageNoLogs": "Немає Журнали",
"MessageNoMediaProgress": "Прогрес відсутній",
"MessageNoNotifications": "Сповіщення відсутні",
"MessageNoPodcastFeed": "Невірний подкаст: Немає каналу",
"MessageNoPodcastFeed": "Некоректний подкаст: немає каналу",
"MessageNoPodcastsFound": "Подкастів не знайдено",
"MessageNoResults": "Немає результатів",
"MessageNoSearchResultsFor": "Немає результатів пошуку для \"{0}\"",
"MessageNoSeries": "Без серії",
"MessageNoTags": "Без міток",
"MessageNoSeries": "Немає серій",
"MessageNoTags": "Немає міток",
"MessageNoTasksRunning": "Немає активних завдань",
"MessageNoUpdatesWereNecessary": "Оновлень не потрібно",
"MessageNoUpdatesWereNecessary": "Оновлення не потрібні",
"MessageNoUserPlaylists": "У вас немає списків відтворення",
"MessageNoUserPlaylistsHelp": "Списки відтворення приватні. Лише користувач, який їх створює, може бачити їх.",
"MessageNoUserPlaylistsHelp": "Списки відтворення приватні. Лише користувач, який їх створив, може їх бачити.",
"MessageNotYetImplemented": "Ще не реалізовано",
"MessageOpmlPreviewNote": "Примітка: це попередній перегляд OPML-файлу. Актуальна назва подкасту буде завантажена з RSS-каналу.",
"MessageOpmlPreviewNote": "Примітка: це попередній перегляд OPML-файлу. Актуальна назва подкасту буде взята з RSS-каналу.",
"MessageOr": "або",
"MessagePauseChapter": "Призупинити відтворення глави",
"MessagePlayChapter": "Слухати початок глави",
@@ -841,7 +868,7 @@
"MessagePodcastHasNoRSSFeedForMatching": "Подкаст не має RSS-каналу для пошуку",
"MessagePodcastSearchField": "Введіть пошуковий запит або URL RSS-стрічки",
"MessageQuickEmbedInProgress": "Швидке вбудовування в процесі",
"MessageQuickEmbedQueue": "В черзі на швидке вбудовування ({0} в черзі)",
"MessageQuickEmbedQueue": "У черзі на швидке вбудовування ({0} в черзі)",
"MessageQuickMatchAllEpisodes": "Швидке співставлення всіх епізодів",
"MessageQuickMatchDescription": "Заповнити відсутні подробиці та обкладинку першим результатом пошуку '{0}'. Не перезаписує подробиці, якщо не увімкнено параметр \"Надавати перевагу віднайденим метаданим\".",
"MessageRemoveChapter": "Видалити главу",
@@ -849,9 +876,9 @@
"MessageRemoveFromPlayerQueue": "Вилучити з черги відтворення",
"MessageRemoveUserWarning": "Ви дійсно бажаєте назавжди видалити користувача \"{0}\"?",
"MessageReportBugsAndContribute": "Повідомляйте про помилки, пропонуйте функції та долучайтеся на",
"MessageResetChaptersConfirm": "Ви дійсно бажаєте скинути глави та скасувати внесені зміни?",
"MessageRestoreBackupConfirm": "Ви дійсно бажаєте відновити резервну копію від",
"MessageRestoreBackupWarning": "Відновлення резервної копії перезапише всю базу даних, розташовану в /config, і зображення обкладинок в /metadata/items та /metadata/authors.<br /><br />Резервні копії не змінюють жодних файлів у теках бібліотеки. Якщо у налаштуваннях сервера увімкнено збереження обкладинок і метаданих у теках бібліотеки, вони не створюються під час резервного копіювання і не перезаписуються..<br /><br />Всі клієнти, що користуються вашим сервером, будуть автоматично оновлені.",
"MessageResetChaptersConfirm": "Ви впевнені, що хочете скинути глави та скасувати внесені зміни?",
"MessageRestoreBackupConfirm": "Ви впевнені, що хочете відновити резервну копію, створену",
"MessageRestoreBackupWarning": "Відновлення резервної копії перезапише всю базу даних у /config і зображення обкладинок у /metadata/items та /metadata/authors.<br /><br />Резервні копії не змінюють файли у теках бібліотеки. Якщо у налаштуваннях сервера увімкнено збереження обкладинок і метаданих у теках бібліотеки, вони не створюються під час резервного копіювання і не перезаписуються.<br /><br />Всі клієнти, що користуються вашим сервером, будуть автоматично оновлені.",
"MessageScheduleLibraryScanNote": "Для більшості користувачів рекомендується залишити цю функцію вимкненою та залишити параметр перегляду папок увімкненим. Засіб спостереження за папками автоматично виявить зміни в папках вашої бібліотеки. Засіб спостереження за папками не працює для кожної файлової системи (наприклад, NFS), тому замість нього можна використовувати сканування бібліотек за розкладом.",
"MessageScheduleRunEveryWeekdayAtTime": "Запуск кожні {0} о {1}",
"MessageSearchResultsFor": "Результати пошуку для",
@@ -860,12 +887,12 @@
"MessageServerCouldNotBeReached": "Не вдалося підключитися до сервера",
"MessageSetChaptersFromTracksDescription": "Створити глави з аудіодоріжок, встановивши назви файлів за заголовки",
"MessageShareExpirationWillBe": "Термін сплине за <strong>{0}</strong>",
"MessageShareExpiresIn": "Сплине за {0}",
"MessageShareURLWillBe": "Поширюваний URL - <strong>{0}</strong>",
"MessageShareExpiresIn": "Спливає через {0}",
"MessageShareURLWillBe": "URL для спільного доступу — <strong>{0}</strong>",
"MessageStartPlaybackAtTime": "Почати відтворення \"{0}\" з {1}?",
"MessageTaskAudioFileNotWritable": "Аудіофайл \"{0}\" недоступний для запису",
"MessageTaskCanceledByUser": "Задача скасована користувачем",
"MessageTaskDownloadingEpisodeDescription": "Завантаження епізоду \"{0}\"",
"MessageTaskCanceledByUser": "Завдання скасовано користувачем",
"MessageTaskDownloadingEpisodeDescription": "Скачування епізоду \"{0}\"",
"MessageTaskEmbeddingMetadata": "Вбудовування метаданих",
"MessageTaskEmbeddingMetadataDescription": "Вбудовування метаданих у аудіокнигу \"{0}\"",
"MessageTaskEncodingM4b": "Кодування M4B",
@@ -880,19 +907,19 @@
"MessageTaskMatchingBooksInLibrary": "Відповідність книг у бібліотеці \"{0}\"",
"MessageTaskNoFilesToScan": "Немає файлів для сканування",
"MessageTaskOpmlImport": "Імпорт OPML",
"MessageTaskOpmlImportDescription": "Створення подкастів з {0} RSS-стрічок",
"MessageTaskOpmlImportFeed": "Канал імпорту OPML",
"MessageTaskOpmlImportDescription": "Створення подкастів з {0} RSS-каналів",
"MessageTaskOpmlImportFeed": "Імпорт RSS-каналу OPML",
"MessageTaskOpmlImportFeedDescription": "Імпорт RSS-каналу \"{0}\"",
"MessageTaskOpmlImportFeedFailed": "Не вдалося отримати подкаст-стрічку",
"MessageTaskOpmlImportFeedFailed": "Не вдалося отримати подкаст-канал",
"MessageTaskOpmlImportFeedPodcastDescription": "Створення подкасту \"{0}\"",
"MessageTaskOpmlImportFeedPodcastExists": "Подкаст вже існує за цим шляхом",
"MessageTaskOpmlImportFeedPodcastFailed": "Не вдалося створити подкаст",
"MessageTaskOpmlImportFinished": "Додано {0} подкастів",
"MessageTaskOpmlParseFailed": "Не вдалося розібрати файл OPML",
"MessageTaskOpmlParseFastFail": "Невірний файл OPML: не знайдено тег <opml> або тег <outline>",
"MessageTaskOpmlParseNoneFound": "У файлі OPML не знайдено жодного канала",
"MessageTaskOpmlParseFailed": "Не вдалося розібрати OPML-файл",
"MessageTaskOpmlParseFastFail": "Некоректний OPML-файл: не знайдено тег <opml> або <outline>",
"MessageTaskOpmlParseNoneFound": "У OPML-файлі не знайдено жодного каналу",
"MessageTaskScanItemsAdded": "{0} додано",
"MessageTaskScanItemsMissing": "{0} відсутній",
"MessageTaskScanItemsMissing": "{0} відсутні",
"MessageTaskScanItemsUpdated": "{0} оновлено",
"MessageTaskScanNoChangesNeeded": "Змін не потрібно",
"MessageTaskScanningFileChanges": "Сканування змін файлів у \"{0}\"",
@@ -902,22 +929,24 @@
"MessageUploaderItemFailed": "Не вдалося завантажити",
"MessageUploaderItemSuccess": "Успішно завантажено!",
"MessageUploading": "Завантаження...",
"MessageValidCronExpression": "Допустима команда cron",
"MessageWatcherIsDisabledGlobally": "Спостерігача вимкнено в налаштуваннях сервера",
"MessageValidCronExpression": "Коректний cron-вираз",
"MessageWatcherIsDisabledGlobally": "Спостерігача вимкнено у глобальних налаштуваннях сервера",
"MessageXLibraryIsEmpty": "Бібліотека {0} порожня!",
"MessageYourAudiobookDurationIsLonger": "Тривалість вашої аудіокниги довша за віднайдену",
"MessageYourAudiobookDurationIsShorter": "Тривалість вашої аудіокниги коротша за віднайдену",
"NoteChangeRootPassword": "Тільки користувач root — єдиний, хто може мати порожній пароль",
"NoteChapterEditorTimes": "Примітка: Перша глава мусить починатися з 0:00, а час початку останньої глави не може бути більшим за зазначену тривалість аудіокниги.",
"NoteFolderPicker": "Примітка: вже обрані теки не буде показано",
"NoteRSSFeedPodcastAppsHttps": "Попередження: Більшість додатків подкастів вимагатимуть використання протоколу HTTPS від RSS-каналу",
"NoteRSSFeedPodcastAppsPubDate": "Попередження: 1 або більше ваших епізодів не мають дати публікації. Деякі додатки подкастів вимагають це.",
"NoteUploaderFoldersWithMediaFiles": "Теки з медіафайлами буде оброблено як окремі елементи бібліотеки.",
"NoteUploaderOnlyAudioFiles": "Якщо завантажувати лише аудіофайли, то кожен файл буде оброблено як окрему книгу.",
"NoteUploaderUnsupportedFiles": "Непідтримувані файли пропущено. Під час вибору або перетягування теки, файли, що знаходяться поза текою, пропускаються.",
"NotificationOnBackupCompletedDescription": "Запускається після завершення резервного копіювання",
"NotificationOnBackupFailedDescription": "Срабатывает при збої резервного копіювання",
"NotificationOnEpisodeDownloadedDescription": "Запускається при автоматичному завантаженні епізоду подкасту",
"MessageYourAudiobookDurationIsLonger": "Тривалість вашої аудіокниги більша за знайдену",
"MessageYourAudiobookDurationIsShorter": "Тривалість вашої аудіокниги менша за знайдену",
"NoteChangeRootPassword": "Тільки користувач root може мати порожній пароль",
"NoteChapterEditorTimes": "Примітка: Перша глава повинна починатися з 0:00, а час початку останньої глави не може перевищувати тривалість цієї аудіокниги.",
"NoteFolderPicker": "Примітка: вже додані папки не відображаються",
"NoteRSSFeedPodcastAppsHttps": "Попередження: більшість додатків подкастів вимагають використання HTTPS для RSS-каналу",
"NoteRSSFeedPodcastAppsPubDate": "Попередження: один або більше ваших епізодів не мають дати публікації. Деякі додатки подкастів цього вимагають.",
"NoteUploaderFoldersWithMediaFiles": "Теки з медіафайлами обробляються як окремі елементи бібліотеки.",
"NoteUploaderOnlyAudioFiles": "Якщо завантажувати лише аудіофайли, кожен файл буде окремою аудіокнигою.",
"NoteUploaderUnsupportedFiles": "Непідтримувані файли ігноруються. При виборі або перетягуванні теки, файли поза теками елементів ігноруються.",
"NotificationOnBackupCompletedDescription": "Виконується після завершення резервного копіювання",
"NotificationOnBackupFailedDescription": "Виконується при помилці резервного копіювання",
"NotificationOnEpisodeDownloadedDescription": "Виконується при автоматичному завантаженні епізоду подкасту",
"NotificationOnRSSFeedDisabledDescription": "Виконується, коли автоматичне завантаження епізодів вимкнено через забагато невдалих спроб",
"NotificationOnRSSFeedFailedDescription": "Виконується, коли запит RSS-каналу не вдається для автоматичного завантаження епізоду",
"NotificationOnTestDescription": "Подія для тестування системи сповіщень",
"PlaceholderNewCollection": "Нова назва добірки",
"PlaceholderNewFolderPath": "Новий шлях до теки",
@@ -995,16 +1024,19 @@
"ToastEncodeCancelFailed": "Не вдалося скасувати кодування",
"ToastEncodeCancelSucces": "Кодування скасовано",
"ToastEpisodeDownloadQueueClearFailed": "Не вдалося очистити чергу",
"ToastEpisodeDownloadQueueClearSuccess": "Чергу на завантаження епізодів очищено",
"ToastEpisodeDownloadQueueClearSuccess": "Чергу на скачування епізодів очищено",
"ToastEpisodeUpdateSuccess": "{0} епізодів оновлено",
"ToastErrorCannotShare": "Не можна типово поширити на цей пристрій",
"ToastFailedToCreate": "Не вдалося створити",
"ToastFailedToDelete": "Не вдалося видалити",
"ToastFailedToLoadData": "Не вдалося завантажити дані",
"ToastFailedToMatch": "Не вдалося знайти відповідність",
"ToastFailedToShare": "Не вдалося поділитися",
"ToastFailedToUpdate": "Не вдалося оновити",
"ToastInvalidImageUrl": "Невірний URL зображення",
"ToastInvalidMaxEpisodesToDownload": "Невірна кількість епізодів для завантаження",
"ToastInvalidMaxEpisodesToDownload": "Невірна кількість епізодів для скачування",
"ToastInvalidUrl": "Невірний URL",
"ToastInvalidUrls": "Одна або декілька URL-адрес недійсні",
"ToastItemCoverUpdateSuccess": "Обкладинку елемента оновлено",
"ToastItemDeletedFailed": "Не вдалося видалити елемент",
"ToastItemDeletedSuccess": "Видалений елемент",
@@ -1029,6 +1061,7 @@
"ToastMustHaveAtLeastOnePath": "Повинен бути хоча б один шлях",
"ToastNameEmailRequired": "Ім'я та електронна пошта обов'язкові",
"ToastNameRequired": "Ім'я обов'язкове",
"ToastNewApiKeyUserError": "Потрібно вибрати користувача",
"ToastNewEpisodesFound": "{0} нових епізодів знайдено",
"ToastNewUserCreatedFailed": "Не вдалося створити акаунт: \"{0}\"",
"ToastNewUserCreatedSuccess": "Новий акаунт створено",
@@ -1063,7 +1096,7 @@
"ToastProviderRemoveSuccess": "Постачальник видалений",
"ToastRSSFeedCloseFailed": "Не вдалося закрити RSS-канал",
"ToastRSSFeedCloseSuccess": "RSS-канал закрито",
"ToastRemoveFailed": "Не вдалося видалити",
"ToastRemoveFailed": "Не вдалося вилучити",
"ToastRemoveItemFromCollectionFailed": "Не вдалося видалити елемент із добірки",
"ToastRemoveItemFromCollectionSuccess": "Елемент видалено з добірки",
"ToastRemoveItemsWithIssuesFailed": "Не вдалося видалити елементи бібліотеки з проблемами",

View File

@@ -1,5 +1,6 @@
{
"ButtonAdd": "添加",
"ButtonAddApiKey": "添加 API 密钥",
"ButtonAddChapters": "添加章节",
"ButtonAddDevice": "添加设备",
"ButtonAddLibrary": "添加库",
@@ -11,7 +12,7 @@
"ButtonAuthors": "作者",
"ButtonBack": "返回",
"ButtonBatchEditPopulateFromExisting": "用现有内容填充",
"ButtonBatchEditPopulateMapDetails": "填充地图详细信息",
"ButtonBatchEditPopulateMapDetails": "填入此项详情",
"ButtonBrowseForFolder": "浏览文件夹",
"ButtonCancel": "取消",
"ButtonCancelEncode": "取消编码",
@@ -20,8 +21,9 @@
"ButtonChooseAFolder": "选择文件夹",
"ButtonChooseFiles": "选择文件",
"ButtonClearFilter": "清除过滤器",
"ButtonClose": "关闭",
"ButtonCloseFeed": "关闭源",
"ButtonCloseSession": "关闭开放会话",
"ButtonCloseSession": "关闭活动会话",
"ButtonCollections": "收藏",
"ButtonConfigureScanner": "配置扫描",
"ButtonCreate": "创建",
@@ -73,7 +75,7 @@
"ButtonQuickMatch": "快速匹配",
"ButtonReScan": "重新扫描",
"ButtonRead": "读取",
"ButtonReadLess": "阅读较少",
"ButtonReadLess": "收起",
"ButtonReadMore": "阅读更多",
"ButtonRefresh": "刷新",
"ButtonRemove": "移除",
@@ -119,6 +121,7 @@
"HeaderAccount": "帐户",
"HeaderAddCustomMetadataProvider": "添加自定义元数据提供商",
"HeaderAdvanced": "高级",
"HeaderApiKeys": "API 密钥",
"HeaderAppriseNotificationSettings": "测试通知设置",
"HeaderAudioTracks": "音轨",
"HeaderAudiobookTools": "有声读物文件管理工具",
@@ -162,12 +165,13 @@
"HeaderMetadataOrderOfPrecedence": "元数据优先级",
"HeaderMetadataToEmbed": "嵌入元数据",
"HeaderNewAccount": "新建帐户",
"HeaderNewApiKey": "新建 API 密钥",
"HeaderNewLibrary": "新建媒体库",
"HeaderNotificationCreate": "创建通知",
"HeaderNotificationUpdate": "更新通知",
"HeaderNotifications": "通知",
"HeaderOpenIDConnectAuthentication": "OpenID 连接身份验证",
"HeaderOpenListeningSessions": "打开收听会话",
"HeaderOpenListeningSessions": "活动中会话",
"HeaderOpenRSSFeed": "打开 RSS 源",
"HeaderOtherFiles": "其他文件",
"HeaderPasswordAuthentication": "密码认证",
@@ -195,6 +199,7 @@
"HeaderSettingsExperimental": "实验功能",
"HeaderSettingsGeneral": "通用",
"HeaderSettingsScanner": "扫描",
"HeaderSettingsSecurity": "安全",
"HeaderSettingsWebClient": "网页客户端",
"HeaderSleepTimer": "睡眠计时",
"HeaderStatsLargestItems": "最大的项目",
@@ -206,13 +211,14 @@
"HeaderTableOfContents": "目录",
"HeaderTools": "工具",
"HeaderUpdateAccount": "更新帐户",
"HeaderUpdateApiKey": "更新 API 密钥",
"HeaderUpdateAuthor": "更新作者",
"HeaderUpdateDetails": "更新详情",
"HeaderUpdateLibrary": "更新媒体库",
"HeaderUsers": "用户",
"HeaderYearReview": "{0} 年回顾",
"HeaderYourStats": "你的统计数据",
"LabelAbridged": "概要",
"LabelAbridged": "删节版",
"LabelAbridgedChecked": "删节版 (已勾选)",
"LabelAbridgedUnchecked": "未删节版 (未勾选)",
"LabelAccessibleBy": "可访问",
@@ -235,6 +241,10 @@
"LabelAllUsersExcludingGuests": "除访客外的所有用户",
"LabelAllUsersIncludingGuests": "包括访客的所有用户",
"LabelAlreadyInYourLibrary": "已存在你的库中",
"LabelApiKeyCreated": "API 密钥 \"{0}\" 创建成功.",
"LabelApiKeyCreatedDescription": "请确保现在就复制 API 密钥, 之后将无法再次查看.",
"LabelApiKeyUser": "代用户操作",
"LabelApiKeyUserDescription": "此 API 密钥将具有与其代理的用户相同的权限. 在日志中, 其请求将被视为由该用户直接发出.",
"LabelApiToken": "API 令牌",
"LabelAppend": "附加",
"LabelAudioBitrate": "音频比特率 (例如: 128k)",
@@ -284,6 +294,7 @@
"LabelContinueListening": "继续收听",
"LabelContinueReading": "继续阅读",
"LabelContinueSeries": "继续收听系列",
"LabelCorsAllowed": "允许的跨域来源",
"LabelCover": "封面",
"LabelCoverImageURL": "封面图像 URL",
"LabelCoverProvider": "封面提供者",
@@ -320,7 +331,7 @@
"LabelEmailSettingsRejectUnauthorized": "拒绝未经授权的证书",
"LabelEmailSettingsRejectUnauthorizedHelp": "禁用SSL证书验证可能会使你的连接面临安全风险, 例如中间人攻击. 只有当你了解其中的含义并信任所连接的邮件服务器时, 才能禁用此选项.",
"LabelEmailSettingsSecure": "安全",
"LabelEmailSettingsSecureHelp": "如果选是, 则连接将在连接服务器时使用TLS. 如果选否, 则若服务器支持STARTTLS扩展, 则使用TLS. 在大多数情况下, 如果连接到端口465, 请将该值设置为是. 对于端口587或25, 请保持为. (来自nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsSecureHelp": "开启此选项时, 将始终通过TLS连接服务器. 关闭此选项时, 仅在服务器支持STARTTLS扩展使用TLS. 在大多数情况下, 如果连接到端口465, 请将此项设为开启. 如果连接到端口587或25, 请将此设置保持为关闭. (来自nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "测试地址",
"LabelEmbeddedCover": "嵌入封面",
"LabelEnable": "启用",
@@ -346,15 +357,19 @@
"LabelExample": "示例",
"LabelExpandSeries": "展开系列",
"LabelExpandSubSeries": "展开子系列",
"LabelExplicit": "信息准确",
"LabelExplicitChecked": "明确(已选中)",
"LabelExplicitUnchecked": "不明确 (未选中)",
"LabelExpired": "已过期",
"LabelExpiresAt": "过期时间",
"LabelExpiresInSeconds": "有效期 (秒)",
"LabelExpiresNever": "从不",
"LabelExplicit": "含成人内容",
"LabelExplicitChecked": "成人内容 (已核实)",
"LabelExplicitUnchecked": "无成人内容 (未核实)",
"LabelExportOPML": "导出 OPML",
"LabelFeedURL": "源 URL",
"LabelFetchingMetadata": "正在获取元数据",
"LabelFile": "文件",
"LabelFileBirthtime": "文件创建时间",
"LabelFileBornDate": "于 {0}",
"LabelFileBornDate": "添加于 {0}",
"LabelFileModified": "文件修改时间",
"LabelFileModifiedDate": "已修改 {0}",
"LabelFilename": "文件名",
@@ -405,6 +420,7 @@
"LabelLanguages": "语言",
"LabelLastBookAdded": "最后添加的书",
"LabelLastBookUpdated": "最后更新的书",
"LabelLastProgressDate": "上次阅读时间: {0}",
"LabelLastSeen": "上次查看时间",
"LabelLastTime": "最近一次",
"LabelLastUpdate": "最近更新",
@@ -417,6 +433,7 @@
"LabelLibraryFilterSublistEmpty": "没有 {0}",
"LabelLibraryItem": "媒体库项目",
"LabelLibraryName": "媒体库名称",
"LabelLibrarySortByProgress": "进度更新时间",
"LabelLimit": "限制",
"LabelLineSpacing": "行间距",
"LabelListenAgain": "再次收听",
@@ -425,6 +442,7 @@
"LabelLogLevelWarn": "警告",
"LabelLookForNewEpisodesAfterDate": "在此日期后查找新剧集",
"LabelLowestPriority": "最低优先级",
"LabelMatchConfidence": "置信度",
"LabelMatchExistingUsersBy": "匹配现有用户",
"LabelMatchExistingUsersByDescription": "用于连接现有用户. 连接后, 用户将通过 SSO 提供商提供的唯一 id 进行匹配",
"LabelMaxEpisodesToDownload": "可下载的最大集数. 输入 0 表示无限制.",
@@ -455,6 +473,7 @@
"LabelNewestEpisodes": "最新剧集",
"LabelNextBackupDate": "下次备份日期",
"LabelNextScheduledRun": "下次任务运行",
"LabelNoApiKeys": "无 API 密钥",
"LabelNoCustomMetadataProviders": "没有自定义元数据提供商",
"LabelNoEpisodesSelected": "未选择任何剧集",
"LabelNotFinished": "未听完",
@@ -482,7 +501,7 @@
"LabelPermanent": "永久的",
"LabelPermissionsAccessAllLibraries": "可以访问所有媒体库",
"LabelPermissionsAccessAllTags": "可以访问所有标签",
"LabelPermissionsAccessExplicitContent": "可以访问显式内容",
"LabelPermissionsAccessExplicitContent": "可以访问成人内容",
"LabelPermissionsCreateEreader": "可以创建电子阅读器",
"LabelPermissionsDelete": "可以删除",
"LabelPermissionsDownload": "可以下载",
@@ -544,6 +563,7 @@
"LabelSelectAll": "全选",
"LabelSelectAllEpisodes": "选择所有剧集",
"LabelSelectEpisodesShowing": "选择正在播放的 {0} 剧集",
"LabelSelectUser": "选择用户",
"LabelSelectUsers": "选择用户",
"LabelSendEbookToDevice": "发送电子书到...",
"LabelSequence": "序列",
@@ -610,15 +630,15 @@
"LabelStart": "开始",
"LabelStartTime": "开始时间",
"LabelStarted": "开始于",
"LabelStartedAt": "从这开始",
"LabelStartedAt": "收听始于",
"LabelStatsAudioTracks": "音轨",
"LabelStatsAuthors": "作者",
"LabelStatsBestDay": "最好的一天",
"LabelStatsBestDay": "单日最高",
"LabelStatsDailyAverage": "每日平均值",
"LabelStatsDays": "",
"LabelStatsDays": "连续",
"LabelStatsDaysListened": "收听天数",
"LabelStatsHours": "小时",
"LabelStatsInARow": "在一行",
"LabelStatsInARow": "",
"LabelStatsItemsFinished": "已完成的项目",
"LabelStatsItemsInLibrary": "媒体库中的项目",
"LabelStatsMinutes": "分钟",
@@ -640,6 +660,7 @@
"LabelTheme": "主题",
"LabelThemeDark": "黑暗",
"LabelThemeLight": "明亮",
"LabelThemeSepia": "棕褐色",
"LabelTimeBase": "时间基准",
"LabelTimeDurationXHours": "{0} 小时",
"LabelTimeDurationXMinutes": "{0} 分钟",
@@ -708,13 +729,15 @@
"MessageAddToPlayerQueue": "添加到播放队列",
"MessageAppriseDescription": "要使用此功能,你需要运行一个 <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> 实例或一个可以处理这些相同请求的 API. <br />Apprise API Url 应该是发送通知的完整 URL 路径, 例如: 如果你的 API 实例运行在 <code>http://192.168.1.1:8337</code>, 那么你可以输入 <code>http://192.168.1.1:8337/notify</code>.",
"MessageAsinCheck": "确保你使用的 ASIN 来自正确的 Audible 地区, 而不是亚马逊.",
"MessageAuthenticationLegacyTokenWarning": "旧版 API 令牌将来会被移除. 请改用 <a href=\"/config/api-keys\">API 密钥</a>.",
"MessageAuthenticationOIDCChangesRestart": "保存后重新启动服务器以应用 OIDC 更改.",
"MessageAuthenticationSecurityMessage": "身份验证安全性已增强, 所有用户都需要重新登录.",
"MessageBackupsDescription": "备份包括用户, 用户进度, 媒体库项目详细信息, 服务器设置和图像, 存储在 <code>/metadata/items</code> & <code>/metadata/authors</code>. 备份不包括存储在你的媒体库文件夹中的任何文件.",
"MessageBackupsLocationEditNote": "注意: 更新备份位置不会移动或修改现有备份",
"MessageBackupsLocationNoEditNote": "注意: 备份位置是通过环境变量设置的, 不能在此处更改.",
"MessageBackupsLocationPathEmpty": "备份位置路径不能为空",
"MessageBatchEditPopulateMapDetailsAllHelp": "使用所有项目的数据填充已启用的字段. 具有多个值的字段将被合并",
"MessageBatchEditPopulateMapDetailsItemHelp": "使用此项目的数据填充已启用的地图详细信息字段",
"MessageBatchEditPopulateMapDetailsItemHelp": "提取此项目的信息, 填入上方所有勾选的编辑框中",
"MessageBatchQuickMatchDescription": "快速匹配将尝试为所选项目添加缺少的封面和元数据. 启用以下选项以允许快速匹配覆盖现有封面和或元数据.",
"MessageBookshelfNoCollections": "你尚未进行任何收藏",
"MessageBookshelfNoCollectionsHelp": "收藏是公开的. 所有有权访问图书馆的用户都可以看到它们.",
@@ -730,6 +753,7 @@
"MessageChaptersNotFound": "未找到章节",
"MessageCheckingCron": "检查计划任务...",
"MessageConfirmCloseFeed": "你确定要关闭此订阅源吗?",
"MessageConfirmDeleteApiKey": "你确定要删除 API 密钥 \"{0}\" 吗?",
"MessageConfirmDeleteBackup": "你确定要删除备份 {0}?",
"MessageConfirmDeleteDevice": "你确定要删除电子阅读器设备 \"{0}\" 吗?",
"MessageConfirmDeleteFile": "这将从文件系统中删除该文件. 你确定吗?",
@@ -757,6 +781,7 @@
"MessageConfirmRemoveAuthor": "你确定要删除作者 \"{0}\"?",
"MessageConfirmRemoveCollection": "你确定要移除收藏 \"{0}\"?",
"MessageConfirmRemoveEpisode": "你确定要移除剧集 \"{0}\"?",
"MessageConfirmRemoveEpisodeNote": "注意: 此操作不会删除音频文件, 除非勾选 \"完全删除文件\" 选项",
"MessageConfirmRemoveEpisodes": "你确定要移除 {0} 剧集?",
"MessageConfirmRemoveListeningSessions": "你确定要移除 {0} 收听会话吗?",
"MessageConfirmRemoveMetadataFiles": "你确实要删除库项目文件夹中的所有 metadata.{0} 文件吗?",
@@ -782,12 +807,14 @@
"MessageFeedURLWillBe": "源 URL 将改为 {0}",
"MessageFetching": "正在获取...",
"MessageForceReScanDescription": "将像重新扫描一样再次扫描所有文件. 音频文件 ID3 标签, OPF 文件和文本文件将被扫描为新文件.",
"MessageHeatmapListeningTimeTooltip": "{1} <strong>收听了 {0}</strong>",
"MessageHeatmapNoListeningSessions": "{0} 没有收听",
"MessageImportantNotice": "重要通知!",
"MessageInsertChapterBelow": "在下面插入章节",
"MessageInvalidAsin": "无效的 ASIN",
"MessageItemsSelected": "已选定 {0} 个项目",
"MessageItemsUpdated": "已更新 {0} 个项目",
"MessageJoinUsOn": "加入我们",
"MessageJoinUsOn": "加入我们",
"MessageLoading": "正在加载...",
"MessageLoadingFolders": "加载文件夹...",
"MessageLogsDescription": "日志以 JSON 文件形式存储在 <code>/metadata/logs</code> 目录中. 崩溃日志存储在 <code>/metadata/logs/crash_logs.txt</code> 目录中.",
@@ -848,12 +875,12 @@
"MessageRemoveEpisodes": "移除 {0} 剧集",
"MessageRemoveFromPlayerQueue": "从播放队列中移除",
"MessageRemoveUserWarning": "是否确实要永久删除用户 \"{0}\"?",
"MessageReportBugsAndContribute": "报告错误、请求功能和贡献在",
"MessageReportBugsAndContribute": "反馈问题, 建议功能或参与贡献, 请访问",
"MessageResetChaptersConfirm": "你确定要重置章节并撤消你所做的更改吗?",
"MessageRestoreBackupConfirm": "你确定要恢复创建的这个备份",
"MessageRestoreBackupWarning": "恢复备份将覆盖位于 /config 的整个数据库并覆盖 /metadata/items & /metadata/authors 中的图像.<br /><br />备份不会修改媒体库文件夹中的任何文件. 如果你已启用服务器设置将封面和元数据存储在库文件夹中,则不会备份或覆盖这些内容.<br /><br />将自动刷新使用服务器的所有客户端.",
"MessageScheduleLibraryScanNote": "对于大多数用户, 建议禁用此功能并保持文件夹监视程序设置启用. 文件夹监视程序将自动检测库文件夹中的更改. 文件夹监视程序不适用于每个文件系统 (如 NFS), 因此可以使用计划库扫描.",
"MessageScheduleRunEveryWeekdayAtTime": "每 {0} {1} 运行一次",
"MessageScheduleRunEveryWeekdayAtTime": "每 {0} {1} 执行",
"MessageSearchResultsFor": "搜索结果",
"MessageSelected": "{0} 已选择",
"MessageSeriesSequenceCannotContainSpaces": "系列序列不能包含空格",
@@ -917,7 +944,9 @@
"NoteUploaderUnsupportedFiles": "不支持的文件将被忽略. 选择或删除文件夹时, 将忽略不在项目文件夹中的其他文件.",
"NotificationOnBackupCompletedDescription": "备份完成时触发",
"NotificationOnBackupFailedDescription": "备份失败时触发",
"NotificationOnEpisodeDownloadedDescription": "当播客节目自动下载时触发",
"NotificationOnEpisodeDownloadedDescription": "当播客节目自动下载完成时触发",
"NotificationOnRSSFeedDisabledDescription": "由于尝试失败次数过多而导致剧集自动下载被禁用时触发",
"NotificationOnRSSFeedFailedDescription": "当用于自动下载剧集的 RSS 源请求失败时触发",
"NotificationOnTestDescription": "测试通知系统的事件",
"PlaceholderNewCollection": "输入收藏夹名称",
"PlaceholderNewFolderPath": "输入文件夹路径",
@@ -998,6 +1027,8 @@
"ToastEpisodeDownloadQueueClearSuccess": "剧集下载队列已清空",
"ToastEpisodeUpdateSuccess": "已更新 {0} 剧集",
"ToastErrorCannotShare": "无法在此设备上本地共享",
"ToastFailedToCreate": "创建失败",
"ToastFailedToDelete": "删除失败",
"ToastFailedToLoadData": "加载数据失败",
"ToastFailedToMatch": "匹配失败",
"ToastFailedToShare": "分享失败",
@@ -1005,6 +1036,7 @@
"ToastInvalidImageUrl": "图片网址无效",
"ToastInvalidMaxEpisodesToDownload": "可下载的最大集数无效",
"ToastInvalidUrl": "网址无效",
"ToastInvalidUrls": "一个或多个 URL 无效",
"ToastItemCoverUpdateSuccess": "项目封面已更新",
"ToastItemDeletedFailed": "删除项目失败",
"ToastItemDeletedSuccess": "已删除项目",
@@ -1029,6 +1061,7 @@
"ToastMustHaveAtLeastOnePath": "必须至少有一个路径",
"ToastNameEmailRequired": "姓名和电子邮件为必填项",
"ToastNameRequired": "姓名为必填项",
"ToastNewApiKeyUserError": "必须选择一个用户",
"ToastNewEpisodesFound": "找到 {0} 个新剧集",
"ToastNewUserCreatedFailed": "无法创建帐户: \"{0}\"",
"ToastNewUserCreatedSuccess": "已创建新帐户",

View File

@@ -4,7 +4,9 @@ const optionDefinitions = [
{ name: 'port', alias: 'p', type: String },
{ name: 'host', alias: 'h', type: String },
{ name: 'source', alias: 's', type: String },
{ name: 'dev', alias: 'd', type: Boolean }
{ name: 'dev', alias: 'd', type: Boolean },
// Run in production mode and use dev.js config
{ name: 'prod-with-dev-env', alias: 'r', type: Boolean }
]
const commandLineArgs = require('./server/libs/commandLineArgs')
@@ -17,7 +19,7 @@ const server = require('./server/Server')
global.appRoot = __dirname
const isDev = process.env.NODE_ENV !== 'production'
if (isDev) {
if (isDev || options['prod-with-dev-env']) {
const devEnv = require('./dev').config
if (devEnv.Port) process.env.PORT = devEnv.Port
if (devEnv.ConfigPath) process.env.CONFIG_PATH = devEnv.ConfigPath
@@ -28,6 +30,7 @@ if (isDev) {
if (devEnv.SkipBinariesCheck) process.env.SKIP_BINARIES_CHECK = '1'
if (devEnv.AllowIframe) process.env.ALLOW_IFRAME = '1'
if (devEnv.BackupPath) process.env.BACKUP_PATH = devEnv.BackupPath
if (devEnv.ReactClientPath) process.env.REACT_CLIENT_PATH = devEnv.ReactClientPath
process.env.SOURCE = 'local'
process.env.ROUTER_BASE_PATH = devEnv.RouterBasePath ?? '/audiobookshelf'
}

20
package-lock.json generated
View File

@@ -1,17 +1,18 @@
{
"name": "audiobookshelf",
"version": "2.23.0",
"version": "2.28.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "audiobookshelf",
"version": "2.23.0",
"version": "2.28.0",
"license": "GPL-3.0",
"dependencies": {
"axios": "^0.27.2",
"cookie-parser": "^1.4.6",
"express": "^4.17.1",
"express-rate-limit": "^7.5.1",
"express-session": "^1.17.3",
"graceful-fs": "^4.2.10",
"htmlparser2": "^8.0.1",
@@ -1893,6 +1894,21 @@
"node": ">= 0.10.0"
}
},
"node_modules/express-rate-limit": {
"version": "7.5.1",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz",
"integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==",
"license": "MIT",
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/express-rate-limit"
},
"peerDependencies": {
"express": ">= 4.11"
}
},
"node_modules/express-session": {
"version": "1.17.3",
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz",

View File

@@ -1,12 +1,13 @@
{
"name": "audiobookshelf",
"version": "2.23.0",
"version": "2.28.0",
"buildNumber": 1,
"description": "Self-hosted audiobook and podcast server",
"main": "index.js",
"scripts": {
"dev": "nodemon --watch server index.js -- --dev",
"start": "node index.js",
"start-dev": "node index.js --prod-with-dev-env",
"client": "cd client && npm ci && npm run generate",
"prod": "npm run client && npm ci && node index.js",
"build-win": "npm run client && pkg -t node20-win-x64 -o ./dist/win/audiobookshelf -C GZip .",
@@ -39,6 +40,7 @@
"axios": "^0.27.2",
"cookie-parser": "^1.4.6",
"express": "^4.17.1",
"express-rate-limit": "^7.5.1",
"express-session": "^1.17.3",
"graceful-fs": "^4.2.10",
"htmlparser2": "^8.0.1",

View File

File diff suppressed because it is too large Load Diff

View File

@@ -42,6 +42,16 @@ class Database {
return this.models.user
}
/** @type {typeof import('./models/Session')} */
get sessionModel() {
return this.models.session
}
/** @type {typeof import('./models/ApiKey')} */
get apiKeyModel() {
return this.models.apiKey
}
/** @type {typeof import('./models/Library')} */
get libraryModel() {
return this.models.library
@@ -311,6 +321,8 @@ class Database {
buildModels(force = false) {
require('./models/User').init(this.sequelize)
require('./models/Session').init(this.sequelize)
require('./models/ApiKey').init(this.sequelize)
require('./models/Library').init(this.sequelize)
require('./models/LibraryFolder').init(this.sequelize)
require('./models/Book').init(this.sequelize)
@@ -656,6 +668,9 @@ class Database {
* Series should have atleast one Book
* Book and Podcast must have an associated LibraryItem (and vice versa)
* Remove playback sessions that are 3 seconds or less
* Remove duplicate mediaProgresses
* Remove expired auth sessions
* Deactivate expired api keys
*/
async cleanDatabase() {
// Remove invalid Podcast records
@@ -765,6 +780,60 @@ class Database {
if (badSessionsRemoved > 0) {
Logger.warn(`Removed ${badSessionsRemoved} sessions that were 3 seconds or less`)
}
// Remove mediaProgresses with duplicate mediaItemId (remove the oldest updatedAt or if updatedAt is the same, remove arbitrary one)
const [duplicateMediaProgresses] = await this.sequelize.query(`SELECT mp1.id, mp1.mediaItemId
FROM mediaProgresses mp1
WHERE EXISTS (
SELECT 1
FROM mediaProgresses mp2
WHERE mp2.mediaItemId = mp1.mediaItemId
AND mp2.userId = mp1.userId
AND (
mp2.updatedAt > mp1.updatedAt
OR (mp2.updatedAt = mp1.updatedAt AND mp2.id < mp1.id)
)
)`)
for (const duplicateMediaProgress of duplicateMediaProgresses) {
Logger.warn(`Found duplicate mediaProgress for mediaItem "${duplicateMediaProgress.mediaItemId}" - removing it`)
await this.mediaProgressModel.destroy({
where: { id: duplicateMediaProgress.id }
})
}
// Remove expired Session records
await this.cleanupExpiredSessions()
// Deactivate expired api keys
await this.deactivateExpiredApiKeys()
}
/**
* Deactivate expired api keys
*/
async deactivateExpiredApiKeys() {
try {
const affectedCount = await this.apiKeyModel.deactivateExpiredApiKeys()
if (affectedCount > 0) {
Logger.info(`[Database] Deactivated ${affectedCount} expired api keys`)
}
} catch (error) {
Logger.error(`[Database] Error deactivating expired api keys: ${error.message}`)
}
}
/**
* Clean up expired sessions from the database
*/
async cleanupExpiredSessions() {
try {
const deletedCount = await this.sessionModel.cleanupExpiredSessions()
if (deletedCount > 0) {
Logger.info(`[Database] Cleaned up ${deletedCount} expired sessions`)
}
} catch (error) {
Logger.error(`[Database] Error cleaning up expired sessions: ${error.message}`)
}
}
async createTextSearchQuery(query) {

View File

@@ -12,6 +12,7 @@ const { version } = require('../package.json')
// Utils
const fileUtils = require('./utils/fileUtils')
const { toNumber } = require('./utils/index')
const Logger = require('./Logger')
const Auth = require('./Auth')
@@ -84,12 +85,8 @@ class Server {
global.DisableSsrfRequestFilter = (url) => whitelistedUrls.includes(new URL(url).hostname)
}
}
if (process.env.PODCAST_DOWNLOAD_TIMEOUT) {
global.PodcastDownloadTimeout = process.env.PODCAST_DOWNLOAD_TIMEOUT
} else {
global.PodcastDownloadTimeout = 30000
}
global.PodcastDownloadTimeout = toNumber(process.env.PODCAST_DOWNLOAD_TIMEOUT, 30000)
global.MaxFailedEpisodeChecks = toNumber(process.env.MAX_FAILED_EPISODE_CHECKS, 24)
if (!fs.pathExistsSync(global.ConfigPath)) {
fs.mkdirSync(global.ConfigPath)
@@ -159,14 +156,11 @@ class Server {
}
await Database.init(false)
// Create or set JWT secret in token manager
await this.auth.tokenManager.initTokenSecret()
await Logger.logManager.init()
// Create token secret if does not exist (Added v2.1.0)
if (!Database.serverSettings.tokenSecret) {
await this.auth.initTokenSecret()
}
await this.cleanUserData() // Remove invalid user item progress
await CacheManager.ensureCachePaths()
@@ -223,6 +217,7 @@ class Server {
async start() {
Logger.info('=== Starting Server ===')
this.initProcessEventListeners()
await this.init()
@@ -234,6 +229,10 @@ class Server {
res.setHeader('Content-Security-Policy', "frame-ancestors 'self'")
}
// Security: Prevent referrer leakage to protect against token exposure
// Using 'no-referrer' to completely prevent token leakage in referer headers
res.setHeader('Referrer-Policy', 'no-referrer')
/**
* @temporary
* This is necessary for the ebook & cover API endpoint in the mobile apps
@@ -245,8 +244,8 @@ class Server {
* Running in development allows cors to allow testing the mobile apps in the browser
* or env variable ALLOW_CORS = '1'
*/
if (Logger.isDev || req.path.match(/\/api\/items\/([a-z0-9-]{36})\/(ebook|cover)(\/[0-9]+)?/)) {
const allowedOrigins = ['capacitor://localhost', 'http://localhost']
if (global.AllowCors || Logger.isDev || req.path.match(/\/api\/items\/([a-z0-9-]{36})\/(ebook|cover)(\/[0-9]+)?/) || global.ServerSettings.allowedOrigins?.length) {
const allowedOrigins = ['capacitor://localhost', 'http://localhost', ...(global.ServerSettings.allowedOrigins ? global.ServerSettings.allowedOrigins : [])]
if (global.AllowCors || Logger.isDev || allowedOrigins.some((o) => o === req.get('origin'))) {
res.header('Access-Control-Allow-Origin', req.get('origin'))
res.header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, DELETE, OPTIONS')
@@ -266,7 +265,7 @@ class Server {
// enable express-session
app.use(
expressSession({
secret: global.ServerSettings.tokenSecret,
secret: this.auth.tokenManager.TokenSecret,
resave: false,
saveUninitialized: false,
cookie: {
@@ -284,6 +283,7 @@ class Server {
await this.auth.initPassportJs()
const router = express.Router()
// if RouterBasePath is set, modify all requests to include the base path
app.use((req, res, next) => {
const urlStartsWithRouterBasePath = req.url.startsWith(global.RouterBasePath)
@@ -310,16 +310,14 @@ class Server {
})
)
router.use(express.urlencoded({ extended: true, limit: '5mb' }))
router.use(express.json({ limit: '10mb' }))
// Skip JSON parsing for internal-api routes
router.use(/^(?!\/internal-api).*/, express.json({ limit: '10mb' }))
router.use('/api', this.auth.ifAuthNeeded(this.authMiddleware.bind(this)), this.apiRouter.router)
router.use('/hls', this.hlsRouter.router)
router.use('/public', this.publicRouter.router)
// Static path to generated nuxt
const distPath = Path.join(global.appRoot, '/client/dist')
router.use(express.static(distPath))
// Static folder
router.use(express.static(Path.join(global.appRoot, 'static')))
@@ -339,32 +337,6 @@ class Server {
// Auth routes
await this.auth.initAuthRoutes(router)
// Client dynamic routes
const dynamicRoutes = [
'/item/:id',
'/author/:id',
'/audiobook/:id/chapters',
'/audiobook/:id/edit',
'/audiobook/:id/manage',
'/library/:library',
'/library/:library/search',
'/library/:library/bookshelf/:id?',
'/library/:library/authors',
'/library/:library/narrators',
'/library/:library/stats',
'/library/:library/series/:id?',
'/library/:library/podcast/search',
'/library/:library/podcast/latest',
'/library/:library/podcast/download-queue',
'/config/users/:id',
'/config/users/:id/sessions',
'/config/item-metadata-utils/:id',
'/collection/:id',
'/playlist/:id',
'/share/:slug'
]
dynamicRoutes.forEach((route) => router.get(route, (req, res) => res.sendFile(Path.join(distPath, 'index.html'))))
router.post('/init', (req, res) => {
if (Database.hasRootUser) {
Logger.error(`[Server] attempt to init server when server already has a root user`)
@@ -395,6 +367,49 @@ class Server {
})
router.get('/healthcheck', (req, res) => res.sendStatus(200))
const ReactClientPath = process.env.REACT_CLIENT_PATH
if (!ReactClientPath) {
// Static path to generated nuxt
const distPath = Path.join(global.appRoot, '/client/dist')
router.use(express.static(distPath))
// Client dynamic routes
const dynamicRoutes = [
'/item/:id',
'/author/:id',
'/audiobook/:id/chapters',
'/audiobook/:id/edit',
'/audiobook/:id/manage',
'/library/:library',
'/library/:library/search',
'/library/:library/bookshelf/:id?',
'/library/:library/authors',
'/library/:library/narrators',
'/library/:library/stats',
'/library/:library/series/:id?',
'/library/:library/podcast/search',
'/library/:library/podcast/latest',
'/library/:library/podcast/download-queue',
'/config/users/:id',
'/config/users/:id/sessions',
'/config/item-metadata-utils/:id',
'/collection/:id',
'/playlist/:id',
'/share/:slug'
]
dynamicRoutes.forEach((route) => router.get(route, (req, res) => res.sendFile(Path.join(distPath, 'index.html'))))
} else {
// This is for using the experimental Next.js client
Logger.info(`Using React client at ${ReactClientPath}`)
const nextPath = Path.join(ReactClientPath, 'node_modules/next')
const next = require(nextPath)
const nextApp = next({ dev: Logger.isDev, dir: ReactClientPath })
const handle = nextApp.getRequestHandler()
await nextApp.prepare()
router.get('*', (req, res) => handle(req, res))
router.post('/internal-api/*', (req, res) => handle(req, res))
}
const unixSocketPrefix = 'unix/'
if (this.Host?.startsWith(unixSocketPrefix)) {
const sockPath = this.Host.slice(unixSocketPrefix.length)
@@ -417,7 +432,7 @@ class Server {
Logger.info(`[Server] Initializing new server`)
const newRoot = req.body.newRoot
const rootUsername = newRoot.username || 'root'
const rootPash = newRoot.password ? await this.auth.hashPass(newRoot.password) : ''
const rootPash = newRoot.password ? await this.auth.localAuthStrategy.hashPassword(newRoot.password) : ''
if (!rootPash) Logger.warn(`[Server] Creating root user with no password`)
await Database.createRootUser(rootUsername, rootPash, this.auth)

View File

@@ -1,7 +1,7 @@
const SocketIO = require('socket.io')
const Logger = require('./Logger')
const Database = require('./Database')
const Auth = require('./Auth')
const TokenManager = require('./auth/TokenManager')
/**
* @typedef SocketClient
@@ -231,18 +231,22 @@ class SocketAuthority {
* When setting up a socket connection the user needs to be associated with a socket id
* for this the client will send a 'auth' event that includes the users API token
*
* Sends event 'init' to the socket. For admins this contains an array of users online.
* For failed authentication it sends event 'auth_failed' with a message
*
* @param {SocketIO.Socket} socket
* @param {string} token JWT
*/
async authenticateSocket(socket, token) {
// we don't use passport to authenticate the jwt we get over the socket connection.
// it's easier to directly verify/decode it.
const token_data = Auth.validateAccessToken(token)
// TODO: Support API keys for web socket connections
const token_data = TokenManager.validateAccessToken(token)
if (!token_data?.userId) {
// Token invalid
Logger.error('Cannot validate socket - invalid token')
return socket.emit('invalid_token')
return socket.emit('auth_failed', { message: 'Invalid token' })
}
// get the user via the id from the decoded jwt.
@@ -250,7 +254,11 @@ class SocketAuthority {
if (!user) {
// user not found
Logger.error('Cannot validate socket - invalid token')
return socket.emit('invalid_token')
return socket.emit('auth_failed', { message: 'Invalid token' })
}
if (!user.isActive) {
Logger.error('Cannot validate socket - user is not active')
return socket.emit('auth_failed', { message: 'Invalid user' })
}
const client = this.clients[socket.id]
@@ -260,13 +268,18 @@ class SocketAuthority {
}
if (client.user !== undefined) {
Logger.debug(`[SocketAuthority] Authenticating socket client already has user`, client.user.username)
if (client.user.id === user.id) {
// Allow re-authentication of a socket to the same user
Logger.info(`[SocketAuthority] Authenticating socket already associated to user "${client.user.username}"`)
} else {
// Allow re-authentication of a socket to a different user but shouldn't happen
Logger.warn(`[SocketAuthority] Authenticating socket to user "${user.username}", but is already associated with a different user "${client.user.username}"`)
}
} else {
Logger.debug(`[SocketAuthority] Authenticating socket to user "${user.username}"`)
}
client.user = user
Logger.debug(`[SocketAuthority] User Online ${client.user.username}`)
this.adminEmitter('user_online', client.user.toJSONForPublic(this.Server.playbackSessionManager.sessions))
// Update user lastSeen without firing sequelize bulk update hooks

View File

@@ -0,0 +1,186 @@
const passport = require('passport')
const LocalStrategy = require('../libs/passportLocal')
const Database = require('../Database')
const Logger = require('../Logger')
const bcrypt = require('../libs/bcryptjs')
const requestIp = require('../libs/requestIp')
/**
* Local authentication strategy using username/password
*/
class LocalAuthStrategy {
constructor() {
this.name = 'local'
this.strategy = null
}
/**
* Get the passport strategy instance
* @returns {LocalStrategy}
*/
getStrategy() {
if (!this.strategy) {
this.strategy = new LocalStrategy({ passReqToCallback: true }, this.verifyCredentials.bind(this))
}
return this.strategy
}
/**
* Initialize the strategy with passport
*/
init() {
passport.use(this.name, this.getStrategy())
}
/**
* Remove the strategy from passport
*/
unuse() {
passport.unuse(this.name)
this.strategy = null
}
/**
* Verify user credentials
* @param {import('express').Request} req
* @param {string} username
* @param {string} password
* @param {Function} done - Passport callback
*/
async verifyCredentials(req, username, password, done) {
// Load the user given it's username
const user = await Database.userModel.getUserByUsername(username.toLowerCase())
if (!user?.isActive) {
if (user) {
this.logFailedLoginAttempt(req, user.username, 'User is not active')
} else {
this.logFailedLoginAttempt(req, username, 'User not found')
}
done(null, null)
return
}
// Check passwordless root user
if (user.type === 'root' && !user.pash) {
if (password) {
// deny login
this.logFailedLoginAttempt(req, user.username, 'Root user has no password set')
done(null, null)
return
}
// approve login
Logger.info(`[LocalAuth] User "${user.username}" logged in from ip ${requestIp.getClientIp(req)}`)
done(null, user)
return
} else if (!user.pash) {
this.logFailedLoginAttempt(req, user.username, 'User has no password set. Might have been created with OpenID')
done(null, null)
return
}
// Check password match
const compare = await bcrypt.compare(password, user.pash)
if (compare) {
// approve login
Logger.info(`[LocalAuth] User "${user.username}" logged in from ip ${requestIp.getClientIp(req)}`)
done(null, user)
return
}
// deny login
this.logFailedLoginAttempt(req, user.username, 'Invalid password')
done(null, null)
}
/**
* Log failed login attempts
* @param {import('express').Request} req
* @param {string} username
* @param {string} message
*/
logFailedLoginAttempt(req, username, message) {
if (!req || !username || !message) return
Logger.error(`[LocalAuth] Failed login attempt for username "${username}" from ip ${requestIp.getClientIp(req)} (${message})`)
}
/**
* Hash a password with bcrypt
* @param {string} password
* @returns {Promise<string>} hash
*/
hashPassword(password) {
return new Promise((resolve) => {
bcrypt.hash(password, 8, (err, hash) => {
if (err) {
resolve(null)
} else {
resolve(hash)
}
})
})
}
/**
* Compare password with user's hashed password
* @param {string} password
* @param {import('../models/User')} user
* @returns {Promise<boolean>}
*/
comparePassword(password, user) {
if (user.type === 'root' && !password && !user.pash) return true
if (!password || !user.pash) return false
return bcrypt.compare(password, user.pash)
}
/**
* Change user password
* @param {import('../models/User')} user
* @param {string} password
* @param {string} newPassword
*/
async changePassword(user, password, newPassword) {
// Only root can have an empty password
if (user.type !== 'root' && !newPassword) {
return {
error: 'Invalid new password - Only root can have an empty password'
}
}
// Check password match
const compare = await this.comparePassword(password, user)
if (!compare) {
return {
error: 'Invalid password'
}
}
let pw = ''
if (newPassword) {
pw = await this.hashPassword(newPassword)
if (!pw) {
return {
error: 'Hash failed'
}
}
}
try {
await user.update({ pash: pw })
Logger.info(`[LocalAuth] User "${user.username}" changed password`)
return {
success: true
}
} catch (error) {
Logger.error(`[LocalAuth] User "${user.username}" failed to change password`, error)
return {
error: 'Unknown error'
}
}
}
}
module.exports = LocalAuthStrategy

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