Compare commits

..

315 Commits

Author SHA1 Message Date
advplyr f2aed08d51 Version bump v2.4.4 2023-09-30 16:04:06 -05:00
advplyr c2c8cf919e Fix:Bad backup causing other backup files to not be displayed #1961 2023-09-30 16:01:10 -05:00
advplyr 9ebe23e91b Merge pull request #2162 from 92Kev/master
Update nl.json
2023-09-30 15:25:36 -05:00
advplyr 3d96749d38 Fix:Downloading podcasts with watcher causing duplicate episodes #2122 2023-09-30 15:12:37 -05:00
advplyr 1dc369180c Fix:Home page recent series shelf respect hide single book series library setting #2134 2023-09-30 14:32:40 -05:00
advplyr 8d3a326216 Fix:Newest episodes home page shelf #2119 2023-09-30 14:19:10 -05:00
advplyr 1b22205f74 Update:Add libraryItems table index to improve performance #2073 2023-09-30 12:39:16 -05:00
92Kev 826fee4590 Update nl.json
Added Dutch translations where they were missing
2023-09-30 16:42:28 +02:00
advplyr f0929729a3 Fix:Adding new podcast with auto download episodes not setting the schedule #2160 2023-09-29 14:52:04 -05:00
advplyr 98ed2e01cc Fix:Scanner overwriting metadata when metadata file is not stored with items #2155 2023-09-28 17:23:52 -05:00
advplyr ed82a5aa19 Update:Library folder path editable in library edit modal until submit #2150 2023-09-27 17:50:32 -05:00
advplyr d7b2476473 Merge pull request #2146 from JBlond/master
Update German translation strings.
2023-09-26 17:18:18 -05:00
JBlond ee162f468a Adjust Message according to https://de.wikipedia.org/wiki/Durchkopplung#Fremdsprachliche_Begriffe
as suggested by https://github.com/vanto
2023-09-26 09:51:34 +02:00
JBlond cb6678fa71 Update German translation strings. 2023-09-25 11:16:57 +02:00
advplyr 10011d3886 Add:Remove option for authors & show authors with 0 books on authors page #2124 2023-09-24 17:06:32 -05:00
advplyr 0367d9ec2a Fix:OPF files creating empty tags and genres #2142 2023-09-24 16:15:42 -05:00
advplyr 26f520ca4a Fix:Listening sessions page showing filtered user for open listening sessions #2136 2023-09-24 15:59:29 -05:00
advplyr 8683fc9fe4 Fix:Show series name when collapsing sub-series #2140 2023-09-23 14:38:30 -05:00
advplyr fd0920c808 Fix:Updating RSS feeds with new episodes #2139 2023-09-23 14:27:13 -05:00
advplyr a446fc0f20 Merge pull request #2138 from husjon/add-norwegian_translation
Added Norwegian translation
2023-09-23 09:37:55 -05:00
Jon Erling Hustadnes 202c26acf5 translation progress 2023-09-23 16:31:23 +02:00
Jon Erling Hustadnes f0b2acb4c7 added 'no' to languageCodeMap i18n.js 2023-09-23 16:29:54 +02:00
advplyr 102c90c4e8 Merge pull request #2133 from mfcar/mf/backup
Add more information to the backup page
2023-09-22 16:56:12 -05:00
advplyr 7c484d8e96 Remove commented out backup location 2023-09-22 16:53:59 -05:00
advplyr e9f0f7d1bc Add LabelBackupLocation translation strings 2023-09-22 16:51:35 -05:00
advplyr f37ab53eff Update get all backups api endpoint to return backupLocation, display location above backup settings 2023-09-22 16:49:01 -05:00
advplyr 97b0b98605 Merge pull request #2102 from selfhost-alt/sqlite-query-logging
Add ability to enable DEV logs of Sqlite queries
2023-09-22 16:17:32 -05:00
advplyr 1ab34fa77f Update server/Database.js 2023-09-22 16:14:12 -05:00
advplyr b64ecc7c6f Update server/Database.js 2023-09-22 16:14:00 -05:00
advplyr a11fc214e9 Merge pull request #2099 from mikiher/Fuzzy-Matching
Fuzzy Matching V1
2023-09-22 16:07:17 -05:00
advplyr 61c48602e8 Add jsdocs to BookFinder search functions 2023-09-22 16:03:41 -05:00
Jon Erling Hustadnes 452d59dcf6 copy of en-us.json to no.json 2023-09-22 12:31:38 +02:00
advplyr 5e976c08af Update cover API endpoint to only load necessary data from DB #2073 2023-09-21 16:57:48 -05:00
advplyr f1cce76e2c Merge pull request #2121 from Hallo951/master
Update de.json
2023-09-20 17:32:03 -05:00
advplyr 872fba1103 Merge pull request #2129 from mikiher/URI-encoding-2
Use encodeURIComponent for text inputs in Match.vue
2023-09-20 16:49:18 -05:00
mfcar 944f5950ca File missing 2023-09-20 22:36:30 +01:00
mfcar bfa87a2131 Add a way to see the backup location 2023-09-20 22:33:58 +01:00
mikiher 6eab985b1e Use encodeURIComponent for text inputs 2023-09-20 11:25:21 +00:00
mikiher 81a9b8d158 Merge branch 'advplyr:master' into Fuzzy-Matching 2023-09-20 13:12:18 +03:00
mfcar 9519f6418d Now, whenever someone requests a backup file, it will automatically suggest a default file name for the downloaded file. 2023-09-19 22:37:57 +01:00
advplyr 9967a5dc66 Fix:Set ebookFormat on scans #2126 2023-09-19 15:42:38 -05:00
Hallo951 9382055bf2 Update de.json 2023-09-19 09:39:46 +02:00
advplyr 604f52762b Merge pull request #2120 from itzexor/x-accel-encode
[server] x-accel: encode all paths to URIs
2023-09-18 17:51:53 -05:00
advplyr ae88a4d20a Fix:Matching a library with no items not removing library scan #2118 2023-09-18 17:38:45 -05:00
advplyr b5a27226cc Fix:Misleading log on cover manager 2023-09-18 16:45:30 -05:00
advplyr 2c71324381 Fix:Book re-scan properly checking if existing coverPath exists #2110 2023-09-18 16:43:43 -05:00
James Ross 207ba7ec8e x-accel: encode all paths to URIs
updates util function  encodeUriPath to use node:url with a file:// path
prefix, and updates all instances x-accel redirection to use this helper
util instead of sending unencoded paths into the header.
2023-09-18 13:08:19 -07:00
advplyr e56b8edc0a Version bump 2.4.3 2023-09-17 16:13:19 -05:00
advplyr 8ab0a0a14d Update personalized shelves logs to dev logs 2023-09-17 16:09:21 -05:00
advplyr 4e01722ba6 Merge pull request #2103 from selfhost-alt/faster-scan-for-empty-series
Scan for empty book series more efficiently
2023-09-17 15:54:33 -05:00
advplyr 87eaacea22 Fix empty podcast and empty book queries when cleaning db on init 2023-09-17 15:53:25 -05:00
advplyr 3ad4f05449 Merge branch 'master' into faster-scan-for-empty-series 2023-09-17 15:47:06 -05:00
advplyr 817be40959 Merge pull request #2101 from selfhost-alt/fix-parse-full-name-typo
Fix typo in fixParsedNameCase
2023-09-17 15:43:25 -05:00
advplyr d18592eaeb Fix:Duplicate series and authors being added on matches and scans #2106 2023-09-17 15:29:39 -05:00
advplyr 0aae672e19 Fix:Scanner purge cover cache when extracting from audio file 2023-09-17 14:53:25 -05:00
advplyr cfd9a01da7 Fix:Server crash when removing item from playlist #2115 2023-09-17 12:40:13 -05:00
Selfhost Alt 19cf3bfb9f Fix query to actually return empty series 2023-09-15 13:32:21 -07:00
mikiher 67bbe21513 Make quick-match more conservative 2023-09-15 09:24:19 +00:00
Selfhost Alt b668c6e37a Remove stray quote 2023-09-14 23:04:47 -07:00
Selfhost Alt 71762ef837 Newline before printing query 2023-09-14 23:01:40 -07:00
Selfhost Alt b1524d245e Add ability to enable DEV logs of Sqlite queries 2023-09-14 22:52:43 -07:00
Selfhost Alt 8b39b01269 Scan for empty book series more efficiently 2023-09-14 22:35:33 -07:00
Selfhost Alt f7849d2956 Fix typo in fixParsedNameCase 2023-09-14 22:12:22 -07:00
mikiher ac746f199b Fuzzy Matching V1 2023-09-14 21:32:20 +00:00
advplyr fea28351f9 Version bump 2.4.2 2023-09-13 16:48:28 -05:00
advplyr bb124d3274 Merge pull request #2089 from Lionfox2/patch-2
Update de.json
2023-09-13 16:46:39 -05:00
advplyr 6cd1b82ada Merge pull request #2083 from Machou/patch-1
Update fr.json
2023-09-13 16:46:23 -05:00
advplyr c701617fbb Merge pull request #2079 from Nab0y/master
Update Russian localization
2023-09-13 16:46:02 -05:00
Lionfox2 5d84c426fe Update de.json
The more suitable translation for "discover" is "Entdecken", same wording as in other media apps like Spotify
2023-09-12 23:30:58 +02:00
advplyr 083ba2fe19 Fix:Podcast download queue page available on refresh #2088 2023-09-12 15:35:14 -05:00
advplyr 1024bc5a75 Fix:Podcast library stat for total size #2072 2023-09-12 13:43:28 -05:00
advplyr 9553c19b33 Fix:Authors dropdown to use filter data instead of API endpoint #2077 2023-09-12 12:33:41 -05:00
Machou 2cbc9a07cb Update fr.json 2023-09-12 18:11:38 +02:00
advplyr ab97a9d613 Fix:Crash when updating book author or series that includes an apostrophe #2070 2023-09-12 10:41:39 -05:00
advplyr f1a7fd0d50 Fix:Podcast library include number of incomplete episodes in home page shelf api request #2081 2023-09-11 17:51:39 -05:00
Dmitry Naboychenko e9d7efbc5c Update russian localization 2023-09-11 21:35:36 +03:00
advplyr 6e5d334874 Version bump 2.4.1 2023-09-09 15:47:17 -05:00
advplyr 6822628994 Fix:Missing narrators library filter 2023-09-09 15:46:33 -05:00
advplyr 98d9fd8c32 Fix:Get all items api endpoint support providing no limit #2067 2023-09-09 15:01:58 -05:00
advplyr e2cca60853 Fix:Crash on podcast library page sort by title #2069 2023-09-09 14:56:36 -05:00
advplyr e80b313a7b Fix:Server crash when quick match with find covers setting enabled #2068 2023-09-09 08:57:59 -05:00
advplyr b09b95ef24 Fix:Browse folders when adding new library folder crashing server #2065 2023-09-09 07:47:17 -05:00
advplyr aec45d04f7 Version bump 2.4.0 2023-09-08 17:26:21 -05:00
advplyr 87d037cb0a Fix clean database method and version bump 2.3.5 2023-09-08 17:20:39 -05:00
advplyr f6baf06164 Version bump 2.3.4 2023-09-08 16:20:03 -05:00
advplyr 7e75845851 Ignore podcast directory from watcher for additional 5s after downloading new episode 2023-09-08 15:12:39 -05:00
advplyr 2a11932822 Scanner ignore .part files #2063 2023-09-08 14:50:59 -05:00
advplyr 80fee92037 Update "disable watcher" server setting to display as "enable watcher" #2055 2023-09-08 14:28:21 -05:00
advplyr d0c02a801a Update open rss feed prevent indexing - dont include block tags when not preventing indexing 2023-09-08 14:03:12 -05:00
advplyr 9e13c64408 Handle sorting when collapsing by series and filtering by series on library page 2023-09-08 13:42:19 -05:00
advplyr 826963bf00 Add api route for changing sorting prefixes, update default sorting prefixes to include a 2023-09-08 12:32:30 -05:00
advplyr 39b6ede1e9 Add support for hide from continue listening 2023-09-08 11:20:22 -05:00
advplyr 066d853156 Add support for hide from continue listening on new home page shelves route 2023-09-07 17:49:35 -05:00
advplyr efae529fac Add cover finder to new book scanner 2023-09-06 17:48:50 -05:00
advplyr 934c0b9093 Fix watcher scanner detecting existing items 2023-09-06 15:43:59 -05:00
advplyr f02992dd4d Remove the setting of file permissions #2057 2023-09-06 07:12:11 -05:00
advplyr 10011bd6a3 Add startup function to remove invalid records from DB 2023-09-05 17:58:13 -05:00
advplyr a44ee913c4 Fix crash on get recent series home page shelf endpoint 2023-09-05 16:10:46 -05:00
advplyr adccccbd7a Remove index creation from migration file 2023-09-05 15:36:19 -05:00
advplyr 05b1b2be36 Merge branch 'master' of https://github.com/advplyr/audiobookshelf 2023-09-05 15:07:49 -05:00
advplyr 7cc35a2cbe Remove indexes for columns that didnt exist in 2.3.3 2023-09-05 15:07:41 -05:00
advplyr 8d479b6e34 Merge pull request #2054 from JBlond/master
Follow-up update for German strings
2023-09-05 08:23:04 -05:00
JBlond 74d300f048 Follow up update for German string to 469167df66.
Plus addtional string translation
2023-09-05 11:36:41 +02:00
advplyr 1dd1fe8994 Update match all books to load items from DB, remove library items loading to memory on init 2023-09-04 16:33:55 -05:00
advplyr 03115e5e53 Replace old items filter/sort api endpoint with new, handle collapse sub-series 2023-09-04 15:26:07 -05:00
advplyr b1c07834be Remove force re-scan and old scanner logic 2023-09-04 13:59:37 -05:00
advplyr b9da3fa30e Add new podcast scanner and remove old scanner 2023-09-04 11:50:55 -05:00
advplyr 42ff3d8314 Add new library item scanner 2023-09-03 17:51:58 -05:00
advplyr e63aab95d8 Update new library scanner to handle metadata file changes 2023-09-03 15:14:58 -05:00
advplyr 9123dcb365 Remove series search api endpoint, update authors and series to load from db 2023-09-03 10:49:02 -05:00
advplyr 7567e91878 Update get library item api endpoint to remove unnecessary authors include query param 2023-09-03 10:04:14 -05:00
advplyr 1b1bdea3c8 Remove authors search api endpoint 2023-09-03 09:54:23 -05:00
advplyr 2df95c1712 Updates for new book scanner 2023-09-02 17:49:28 -05:00
advplyr 4ad1cd2968 Fix:Batch API endpoints crash on reset library filter data 2023-09-02 10:46:47 -05:00
advplyr 0ecfdab463 Update new library scanner for scanning in new books 2023-09-01 18:01:17 -05:00
advplyr 75276f5a44 Fix:Server crash when updating cover to a directory #2007 2023-08-30 18:05:52 -05:00
advplyr 4585d2816b Fix:Comic reader not detecting file sort order when number is more than 5-digit #2036 2023-08-29 15:47:34 -05:00
advplyr f8f94f2a6d Update new library scanner to check for cover images and ebooks 2023-08-28 17:50:21 -05:00
advplyr 2c8448d147 Updates to new library scanner and adding jsdoc types 2023-08-27 17:19:57 -05:00
advplyr ea1d051cfb Merge branch 'master' of https://github.com/advplyr/audiobookshelf 2023-08-26 16:33:34 -05:00
advplyr a38e43213d Fix:Server crash when deleting library item #2031 2023-08-26 16:33:27 -05:00
advplyr 6cac8fcd6e Merge pull request #2030 from bluecmd/debian-tar-owner
Fix system file ownership for Debian package
2023-08-25 16:19:26 -05:00
Christian Svensson 8e65c78869 Fix system file ownership for Debian package
Extract ffmpeg and tone but ignore the ownership information from the tar archive. This will ensure that those files are owned by root, not the UIDs/GIDs the tar files happen to contain.
2023-08-25 18:14:17 +02:00
advplyr a3899b68e1 Merge branch 'master' of https://github.com/advplyr/audiobookshelf 2023-08-24 17:55:35 -05:00
advplyr 1187f91063 Update jsdoc defs for models 2023-08-24 17:55:29 -05:00
advplyr 7c288a5ff9 Merge pull request #2027 from realmain/docker-compose
Added podcasts volume to docker compose
2023-08-24 15:22:24 -05:00
advplyr e0dae44c7d Update:Show published year on library page when sorting books by published year #2017 2023-08-23 18:01:58 -05:00
realmain 754498958d Added podcasts volume 2023-08-23 15:55:07 -07:00
advplyr ec15978e26 Merge pull request #2026 from shawnphoffman/shawn/rss-feeds
Add config page for all RSS feeds
2023-08-22 16:42:31 -05:00
advplyr 469167df66 Update get all feeds route to be admin-only, map translation strings 2023-08-22 16:37:22 -05:00
advplyr e7c43a3f32 Merge pull request #2009 from JBlond/master
Update German strings
2023-08-22 16:08:47 -05:00
Shawn Hoffman 24989e73ae Merge branch 'master' into shawn/rss-feeds 2023-08-22 10:30:16 -07:00
Shawn Hoffman 13427b9f70 Add RSS feeds config page 2023-08-22 10:11:10 -07:00
Mario adafefecd4 Merge branch 'advplyr:master' into master 2023-08-22 11:39:13 +02:00
advplyr 6f96b069b5 Fix search query 2023-08-21 16:33:16 -05:00
advplyr 6c1b4e3a36 Update db model references 2023-08-20 13:34:03 -05:00
advplyr 21343ffbd1 Update numIssues on filter data, fix watcher scanning in new items 2023-08-20 13:16:53 -05:00
advplyr 4f94deefa0 Fix remove items with issues API route & remove old endpoints 2023-08-19 17:12:24 -05:00
advplyr 332078e6c1 Update library stats API route to load from db 2023-08-19 16:53:33 -05:00
advplyr ff0d6326d3 Update OPML api route to load podcasts from db 2023-08-19 15:19:27 -05:00
advplyr 8d451217a3 Update recent-episodes API route to load from db 2023-08-19 14:49:06 -05:00
advplyr f21d69339f Update search query to use user permissions 2023-08-19 14:11:34 -05:00
advplyr c77cead9ae Update search endpoints to search db directly 2023-08-19 13:59:22 -05:00
advplyr b334d40998 Update library routes to middlewareNew 2023-08-18 17:12:15 -05:00
advplyr 4e4a976050 Update get library series api endpoint to load from db 2023-08-18 17:08:34 -05:00
advplyr 9d7d4c6902 Update filterData for authors/series when added/removed 2023-08-18 14:40:36 -05:00
advplyr 7222171c5b Update checking empty series to load from Db 2023-08-17 17:58:57 -05:00
advplyr 361732a463 Update get User API endpoint to load media progress from db 2023-08-17 17:26:12 -05:00
advplyr 1ebe8a6f4c Update scanner to load library items from db 2023-08-16 18:08:00 -05:00
advplyr a98942a361 Add jsdoc types to remaining models 2023-08-16 16:38:48 -05:00
advplyr 0bc89cd40f Fix collapse series and sort by title without ignore prefix 2023-08-16 15:24:56 -05:00
advplyr 2ae86ab5bb Fix Library undefined sequelize 2023-08-16 14:49:06 -05:00
advplyr c707bcf0f6 Add jsdoc types for models 2023-08-15 18:03:43 -05:00
JBlond 10040ba9fa Update German strings as follow up of 09eefae808 2023-08-15 15:38:27 +02:00
advplyr 7afda1295b Update Author model to define types 2023-08-14 18:22:38 -05:00
advplyr 6d6e8613cf Update library API endpoints to load library items from db 2023-08-13 17:45:53 -05:00
advplyr 3651fffbee Update library filter data to load from db and cache, update rss feed routes to load library items from db 2023-08-13 15:10:26 -05:00
advplyr 8d03b23f46 Update MiscController api routes to load library items from db 2023-08-13 13:10:34 -05:00
advplyr fc44c801f2 Update playlist API endpoints to load library items from DB 2023-08-13 11:22:38 -05:00
advplyr 6056c14926 Update podcast controller to load library items from db 2023-08-12 17:29:08 -05:00
advplyr f465193b9c Update User.toJSONForPublic to remove mostRecent key and session key only includes the PlaybackSession 2023-08-12 16:11:58 -05:00
advplyr 09c9c28028 Remove test API endpoint for albums 2023-08-12 15:54:59 -05:00
advplyr f1130eb63a Update MeController api endpoints to load library items from DB 2023-08-12 15:52:09 -05:00
advplyr db80cec168 Update collection API routes to load libraryItems from DB 2023-08-12 15:01:27 -05:00
advplyr 38029d1202 Update library collections api endpoint to use libraryItems from db 2023-08-11 17:49:06 -05:00
advplyr aac2879652 Fix library query sort by title, add indexes for books and libraryItems 2023-08-10 17:46:27 -05:00
advplyr 8c9fc3ddb5 Fix discover home page shelf query, add indexes for libraryItems and mediaProgresses table 2023-08-09 17:48:31 -05:00
advplyr 33e04d0cbb Update home page queries merging listen/read shelves, limit recent shelves to 60 days out 2023-08-07 17:59:04 -05:00
advplyr fbb5fd41fb Merge pull request #1994 from NiclasHaderer/fix-backup-server-crash
Fix: server crash when uploading invalid backup file
2023-08-07 17:17:57 -05:00
advplyr 43a5296dd7 Update server/managers/BackupManager.js 2023-08-07 17:14:47 -05:00
advplyr 345ff1aa66 Update author API endpoints to load library items from DB 2023-08-06 15:06:45 -05:00
advplyr 56e3449db6 Remove media progress for podcast episodes when episode is removed 2023-08-06 14:18:51 -05:00
advplyr 1372c24535 Update queries to account for user permissions 2023-08-06 13:36:58 -05:00
Niclas Haderer 409c5f7b75 fix: the server does not crash any more when an invalid backup file is uploaded 2023-08-06 10:05:53 +02:00
advplyr 83d0db0607 Fix getting default library id for user 2023-08-05 16:37:26 -05:00
advplyr 91b6c4412d Add remaining personalized shelf queries for podcasts 2023-08-05 15:28:16 -05:00
advplyr 09eefae808 Add remaining personalized shelf queries, update book libraries home page to use new API endpoint 2023-08-05 14:01:16 -05:00
advplyr 80b3bfea51 Add recent series home page shelf query 2023-08-04 18:07:55 -05:00
advplyr 516298b5b2 Update continue series shelf to include rss feed 2023-08-04 17:26:43 -05:00
advplyr 8edab98163 Update continue series shelf queries 2023-08-04 17:24:06 -05:00
advplyr 58da095bcf Update query for continue series shelf 2023-08-03 18:14:25 -05:00
advplyr b9633691f4 Add new personalized home page shelves API endpoint 2023-08-02 18:29:28 -05:00
advplyr 7ec1d8ee5f Fix socket authority check for valid client 2023-08-01 16:34:01 -05:00
advplyr 83a1374e79 Merge pull request #1985 from tomazed/translation-fr
fr translation update
2023-08-01 16:23:28 -05:00
Tomazed 5ef00bac92 fr translation update 2023-08-01 11:51:15 +02:00
advplyr 95c4b3862b Include library item podcast queries 2023-07-31 17:59:51 -05:00
advplyr eeaf012cdc Update new library item API endpoint to handle collapse series 2023-07-30 17:51:44 -05:00
advplyr 11120a3765 Update version specific db migration check 2023-07-30 11:09:49 -05:00
advplyr 4d0acb30ba Update bookSeries & bookAuthors table to include createdAt timestamp 2023-07-29 17:25:11 -05:00
advplyr 4dbe8d29d9 Update db migration for duration, size, lastFirst, and ignore prefix columns 2023-07-28 18:03:31 -05:00
advplyr 0ca4ff4fca Update readme 2023-07-27 18:17:29 -05:00
advplyr 8be1651c6b Fix:Sync local media progress when library item not found #1971 2023-07-26 18:08:55 -05:00
advplyr af2db86d1a Merge pull request #1965 from petras-sukys/l10n/lt
Added Lithuanian translation
2023-07-25 15:03:07 -05:00
Petras Šukys 57c834f88d Added EOL at EOF 2023-07-25 22:20:13 +03:00
Petras Šukys 65fdebde20 Added language entry for Lithuanian (Lietuvių) 2023-07-25 22:16:13 +03:00
Petras Šukys b58e42ebf3 Lithuanian translation, part 5 2023-07-25 22:11:12 +03:00
Petras Šukys b2d45f598b Merge branch 'master' into l10n/lt 2023-07-25 08:03:19 +03:00
Petras Šukys 09c4e690c6 Lithuanian translation, part 4 2023-07-25 07:57:51 +03:00
Petras Šukys 67ba481dca Lithuanian translation, part 3 2023-07-24 22:49:44 +03:00
advplyr 710a62c2af Update:Load playlists only when needed & remove podcast episode from playlist when deleted 2023-07-23 09:42:57 -05:00
advplyr 5a9eed0a5a Update:Only load collections when needed 2023-07-22 16:18:55 -05:00
advplyr 354e16e462 Update:Only load Users when needed 2023-07-22 15:32:20 -05:00
advplyr 1d974375a0 Update:Only load libraries from db when needed 2023-07-22 14:25:20 -05:00
advplyr 1c40af3eef Update:Sequelize transactionType to IMMEDIATE to fix SQLITE_BUSY #1910 2023-07-22 11:30:29 -05:00
advplyr daa8c4cd67 Update:Remove sort index from podcast episodes 2023-07-22 09:24:46 -05:00
advplyr d5da4441cd Fix:Set podcast episode audio file index to 1 on scans 2023-07-22 09:05:43 -05:00
advplyr 80aea0c82d Fix:Save metadata files when updating library items #1952 2023-07-22 07:50:47 -05:00
Petras Šukys 14836eeb0d Lithuanian translation, part 2 2023-07-22 12:00:29 +03:00
Petras Šukys 85e9883d3e Lithuanian translation, part 1 2023-07-22 11:53:37 +03:00
Petras Šukys 80ca73e491 Copied en-us language file to lt 2023-07-22 10:52:06 +03:00
advplyr 22323f606d Fix:RSS feed covers #1948 2023-07-21 16:59:00 -05:00
advplyr 01b65eb678 Fix:Initialize Feed entityUpdatedAt to prevent updated RSS feed every request 2023-07-21 16:18:58 -05:00
advplyr d1d94c37a7 Update:Remove --max-old-space-size from Dockerfile 2023-07-20 17:00:08 -05:00
advplyr 838a24c8a5 Update:Remove healthcheck from Dockerfile 2023-07-20 16:59:46 -05:00
advplyr 3f380b0839 Fix:Parsing authors from meta tags removes duplicates #1932 2023-07-20 16:55:49 -05:00
advplyr 7fdf1a1d7f Merge pull request #1946 from rasmuslos/master
Fix byte conversion
2023-07-20 15:55:16 -05:00
advplyr c2793fe29b Fix:Crash when author is set without a name #1934 2023-07-19 17:13:57 -05:00
Rasmus Krämer 38596d017f Fix byte conversion 2023-07-19 23:59:00 +02:00
advplyr 24b9ac6a68 Version bump 2.3.3 2023-07-19 16:32:41 -05:00
advplyr 9a5ed64fae Update database loading library items incrementally to reduce mem usage 2023-07-19 15:36:18 -05:00
advplyr c2af96e7cd Fix:New user setting tags array #1933 2023-07-18 17:43:33 -05:00
advplyr 104cadb0b3 Version bump 2.3.2 2023-07-17 17:49:12 -05:00
advplyr 6814adffcc Update:Only load feeds when needed 2023-07-17 16:48:46 -05:00
advplyr 20c11e381e Update docker file heap size 2023-07-17 14:41:21 -05:00
advplyr b5952f16eb Merge branch 'master' of https://github.com/advplyr/audiobookshelf 2023-07-17 13:58:25 -05:00
advplyr 5b6878e5de Fix:Crash on local playback sessions #1912 2023-07-17 13:58:19 -05:00
advplyr 89a25bcf39 Merge pull request #1917 from burghy86/patch-10
Update it.json
2023-07-17 08:09:28 -05:00
advplyr d0cd512be8 Fix:Crash when updating sequence on series #1919 2023-07-17 08:09:08 -05:00
advplyr 3543dea0fb Merge pull request #1923 from JBlond/master
Update German language file
2023-07-17 08:09:07 -05:00
advplyr 1949e25ccb Merge pull request #1925 from Machou/patch-1
Update fr.json
2023-07-17 08:08:43 -05:00
advplyr b715ef3bfc Increase heap size to 4gb in Dockerfile 2023-07-17 07:48:23 -05:00
Machou 954050df81 Update fr.json 2023-07-17 14:28:56 +02:00
JBlond e4aa7f10fa Update German language file 2023-07-17 10:02:54 +02:00
advplyr 2afd0e2acd Update dbMigration for old main library ids 2023-07-16 16:39:59 -05:00
advplyr 0829237166 Fix:Libraries out of order #1911 2023-07-16 15:43:46 -05:00
advplyr 541975f038 Version bump 2.3.1 2023-07-16 15:34:35 -05:00
advplyr 01bf58ab97 Fix createAuthor 2023-07-16 15:29:43 -05:00
advplyr d99b2c25e8 Fixes for db migration & local playback sessions 2023-07-16 15:05:51 -05:00
burghy86 a31df5ff81 Update it.json
traslate new string and fix error
2023-07-16 21:50:15 +02:00
advplyr 63e5cf2e60 Fix:Accessing series page for some users #787 2023-07-16 08:39:08 -05:00
advplyr 7beca048e7 Version bump v2.3.0 2023-07-15 15:29:25 -05:00
advplyr ec998dc1ac Update:Podcast library item covers show number of episodes incomplete #782 2023-07-15 14:45:08 -05:00
advplyr ddc54c8811 Update:Downloading library item shows log on the server with username #1461 2023-07-15 13:39:12 -05:00
advplyr 72e306935f Update:Support and as separator between multiple authors #1790 2023-07-15 13:28:31 -05:00
advplyr 96a7c7f4d1 Fix:Embedded chapters with invalid IDs, update chapter ids to always be the index #1783 2023-07-15 12:46:51 -05:00
advplyr 9c65d655b8 Fix:Realtime update cover on cover tab in item edit modal 2023-07-15 12:37:33 -05:00
advplyr b108f2241b Add:Library filter for publishers & link to publisher filter on book page #1813 2023-07-15 12:22:13 -05:00
advplyr 9439acf300 Merge pull request #1906 from warnwar/master
stop opf importer from adding duplicate info
2023-07-15 11:44:41 -05:00
advplyr d181e66d83 Update server/utils/parsers/parseOpfMetadata.js 2023-07-15 11:41:44 -05:00
advplyr a87c3f2c77 Update server/utils/parsers/parseOpfMetadata.js 2023-07-15 11:41:40 -05:00
advplyr 2834f6077e Update server/utils/parsers/parseOpfMetadata.js 2023-07-15 11:41:35 -05:00
advplyr 918013ccb3 Add:Option on podcast page to mark all episodes as finished/unfinished #1862 2023-07-15 11:27:06 -05:00
advplyr 4c4672c6c1 Update:Item page UI for details that take up multiple lines 2023-07-15 11:00:07 -05:00
advplyr b3991574c7 Merge pull request #1907 from advplyr/sqlite_2
Migration to use sqlite3
2023-07-14 15:11:23 -05:00
advplyr c881bcbe59 Update logs for cache purge 2023-07-14 15:04:27 -05:00
advplyr 89aa4a8bdc Update logger to support dev only log, remove old model docs 2023-07-14 14:50:37 -05:00
advplyr c5a4f63670 Update Backup to use key to check for old backups no longer supported 2023-07-14 14:20:35 -05:00
advplyr 1b97582975 Update dbMigration mappings 2023-07-14 14:04:47 -05:00
advplyr 9b7aacf3ea Update dbMigration mappings 2023-07-14 14:04:28 -05:00
WarWar 47b9ee557e stop opf importer from adding duplicate info 2023-07-14 05:15:29 +00:00
advplyr e40e0bfa25 Update:Listening session modal UI 2023-07-13 17:44:20 -05:00
advplyr d56e3a3617 Merge branch 'master' into sqlite_2 2023-07-11 17:07:13 -05:00
advplyr 78fe6d47ba Fix:Library settings context menu actions for mobile view #1886 2023-07-11 17:06:14 -05:00
advplyr 995cf51ae3 Update:Default m4b encoding bitrate to 128k #1892 2023-07-11 16:57:30 -05:00
advplyr d838ff2f2e Merge branch 'master' into sqlite_2 2023-07-10 17:37:47 -05:00
advplyr f2f07ff534 Update:Show num episodes on podcast item page #1891 2023-07-10 17:37:35 -05:00
advplyr 8cff68ca64 Fix purge metadata/items paths 2023-07-10 17:00:31 -05:00
advplyr eb5331d34a Update playlist & collection models to use sort order 2023-07-10 16:07:22 -05:00
advplyr f425185575 Merge branch 'master' into sqlite_2 2023-07-09 15:50:50 -05:00
advplyr 9fc352a5a4 Fix:Download episode from rss feed with very long description #1893 2023-07-09 15:50:40 -05:00
advplyr e85ddc1aa1 Update package.json pkg assets, remove njodb and dependencies 2023-07-09 14:22:30 -05:00
advplyr b9be7510f8 Remove purge-media-progress api route 2023-07-09 14:08:14 -05:00
advplyr f4497acd48 Remove API routes for removing all items and purging media progress 2023-07-09 14:07:30 -05:00
advplyr f73a0cce72 Update Dockerfile for sqlite3, update models for cascade delete, fix backup schedule 2023-07-09 11:39:15 -05:00
advplyr 254ba1f089 Migrate backups manager 2023-07-08 14:40:49 -05:00
advplyr 0a179e4eed Update author and series to include libraryId 2023-07-08 10:07:57 -05:00
advplyr 0ac63b2678 Update Series and Author model to be library specific 2023-07-08 09:57:32 -05:00
advplyr 1d13d0a553 Merge master 2023-07-08 08:25:33 -05:00
advplyr fc6ff016a7 Update:Playback sync request timeout to 9s and show sync alerts after 4 failed syncs #1884 2023-07-08 08:08:14 -05:00
advplyr e378b79fbc Fix:Access series that are in multiple libraries and user does not have access to all #1899, new libraries/series endpoint 2023-07-07 17:59:17 -05:00
advplyr 7e377297d7 Update:Remove toast notifications for marking items as finished #1900 2023-07-07 17:22:38 -05:00
advplyr 00a02921dd Fix:RSS feeds that include an id as a query string #1896 2023-07-06 18:06:26 -05:00
advplyr b5d4c11f6f Fix RSS feeds to use slug instead of id 2023-07-06 17:07:10 -05:00
advplyr a0bc959850 Add feed migration and cleanup 2023-07-05 18:18:37 -05:00
advplyr a4b0f6c202 Merge branch 'master' into sqlite_2 2023-07-04 18:15:52 -05:00
advplyr 65cf928afe Fix:Delete ereader device 2023-07-04 18:15:43 -05:00
advplyr cf7fd315b6 Init sqlite take 2 2023-07-04 18:14:44 -05:00
advplyr d86a3b3dc2 Update:Filter out podcasts from search that dont have an RSS feed url #1514 2023-07-01 09:00:40 -05:00
advplyr e07e2cd359 Update:Select all episodes showing option #1878 & add translations to episodes modal 2023-06-30 17:30:15 -05:00
advplyr 8140d7021a Update:Increase timeout for progress sync to 6s and sync interval to 10s #1884 2023-06-30 16:28:02 -05:00
advplyr bdbc5e3161 Add:Library setting to hide single book series #1433 2023-06-29 17:55:17 -05:00
advplyr bb9013541b Update:Get all users api endpoint to include latest session, display device info on users table #724 2023-06-28 17:57:46 -05:00
advplyr 1668153acd Merge branch 'master' of https://github.com/advplyr/audiobookshelf 2023-06-27 17:13:38 -05:00
advplyr aeba7674f8 Add new api route for downloading backup, remove static metadata route 2023-06-27 16:41:32 -05:00
advplyr 5b0d105e21 Remove deprecated /s/ and /ebook/ api routes 2023-06-27 15:56:33 -05:00
advplyr feb54d0629 Merge pull request #1874 from springsunx/master
update zh-cn.json
2023-06-27 08:53:23 -05:00
SunX 3284fe8f31 update zh-cn.json
update zh-cn.json
2023-06-27 21:23:20 +08:00
advplyr 18cb394884 Update:Remove episodes from newest shelf when finished #1871 2023-06-26 17:32:45 -05:00
advplyr d0bce2949e Add:FFProbe api endpoint 2023-06-25 16:16:11 -05:00
advplyr a0e80772cd Merge branch 'master' of https://github.com/advplyr/audiobookshelf 2023-06-23 17:32:09 -05:00
advplyr e44595521d Update:Cleanup collections edit modal ui for mobile 2023-06-23 17:32:03 -05:00
advplyr fdf647eb32 Update:Cleanup chapters page ui on mobile 2023-06-23 17:28:35 -05:00
advplyr 71369bd2a0 Update:Podcast rss feed fetch timeout to 12s #1856 2023-06-22 17:27:09 -05:00
advplyr 36b1f43f4c Fix:epub ereader on mobile #1854 2023-06-18 14:10:01 -05:00
advplyr a8bc1df3e7 Fix epub ereader theme sticking for other ebook formats 2023-06-18 12:56:32 -05:00
advplyr a96869f547 Add ereader translations 2023-06-16 17:00:40 -05:00
advplyr 77b030199e Fix:Non-admin access to config pages #1848 and dev proxy #1848 2023-06-15 17:41:27 -05:00
advplyr 0e1c6c0ba7 Merge pull request #1849 from Nab0y/master
Update Russian localization
2023-06-15 16:10:24 -05:00
Dmitry Naboychenko c397422d3b Update russian localization 2023-06-15 23:28:14 +03:00
advplyr 15313826bf Add:Epub ereader settings for font scale, line spacing, theme and spread 2023-06-14 17:30:08 -05:00
advplyr c6405b9013 Merge pull request #1838 from daVinci2793/master
Updates to Email settings/manager to include test email
2023-06-12 17:16:18 -05:00
advplyr d748d43efc Fallback to using from address if test address is not set, add reset button when form has changes 2023-06-12 17:12:52 -05:00
daVinci2793 d54edb93d6 Updates to Email settings/manager to include test email 2023-06-12 04:53:51 +00:00
advplyr b8ca6671fc Minor cleanup 2023-06-11 13:22:58 -05:00
advplyr cb7fb646ba Fix:Comic reader next/prev buttons 2023-06-11 11:37:28 -05:00
257 changed files with 23003 additions and 9719 deletions
+1
View File
@@ -15,3 +15,4 @@ test/
sw.*
.DS_STORE
.idea/*
+8 -6
View File
@@ -10,11 +10,15 @@ FROM sandreas/tone:v0.1.5 AS tone
FROM node:16-alpine
ENV NODE_ENV=production
RUN apk update && \
apk add --no-cache --update \
curl \
tzdata \
ffmpeg
ffmpeg \
make \
python3 \
g++
COPY --from=tone /usr/local/bin/tone /usr/local/bin/
COPY --from=build /client/dist /client/dist
@@ -23,10 +27,8 @@ COPY server server
RUN npm ci --only=production
RUN apk del make python3 g++
EXPOSE 80
HEALTHCHECK \
--interval=30s \
--timeout=3s \
--start-period=10s \
CMD curl -f http://127.0.0.1/healthcheck || exit 1
CMD ["node", "index.js"]
+2 -2
View File
@@ -60,13 +60,13 @@ install_ffmpeg() {
fi
$WGET
tar xvf ffmpeg-git-amd64-static.tar.xz --strip-components=1
tar xvf ffmpeg-git-amd64-static.tar.xz --strip-components=1 --no-same-owner
rm ffmpeg-git-amd64-static.tar.xz
# Temp downloading tone library to the ffmpeg dir
echo "Getting tone.."
$WGET_TONE
tar xvf tone-0.1.5-linux-x64.tar.gz --strip-components=1
tar xvf tone-0.1.5-linux-x64.tar.gz --strip-components=1 --no-same-owner
rm tone-0.1.5-linux-x64.tar.gz
echo "Good to go on Ffmpeg (& tone)... hopefully"
+2 -2
View File
@@ -303,13 +303,13 @@ export default {
this.$axios
.patch(`/api/me/progress/batch/update`, updateProgressPayloads)
.then(() => {
this.$toast.success('Batch update success!')
this.$toast.success(this.$strings.ToastBatchUpdateSuccess)
this.$store.commit('setProcessingBatch', false)
this.$store.commit('globals/resetSelectedMediaItems', [])
this.$eventBus.$emit('bookshelf_clear_selection')
})
.catch((error) => {
this.$toast.error('Batch update failed')
this.$toast.error(this.$strings.ToastBatchUpdateFailed)
console.error('Failed to batch update read/not read', error)
this.$store.commit('setProcessingBatch', false)
})
@@ -68,6 +68,9 @@ export default {
currentLibraryId() {
return this.$store.state.libraries.currentLibraryId
},
currentLibraryMediaType() {
return this.$store.getters['libraries/getCurrentLibraryMediaType']
},
libraryName() {
return this.$store.getters['libraries/getCurrentLibraryName']
},
@@ -168,7 +171,7 @@ export default {
},
async fetchCategories() {
const categories = await this.$axios
.$get(`/api/libraries/${this.currentLibraryId}/personalized?include=rssfeed`)
.$get(`/api/libraries/${this.currentLibraryId}/personalized?include=rssfeed,numEpisodesIncomplete`)
.then((data) => {
return data
})
@@ -346,8 +349,6 @@ export default {
})
},
episodeAdded(episodeWithLibraryItem) {
console.log('Podcast episode added', episodeWithLibraryItem)
const isThisLibrary = episodeWithLibraryItem.libraryItem?.libraryId === this.currentLibraryId
if (!this.search && isThisLibrary) {
this.fetchCategories()
+5
View File
@@ -99,6 +99,11 @@ export default {
id: 'config-item-metadata-utils',
title: this.$strings.HeaderItemMetadataUtils,
path: '/config/item-metadata-utils'
},
{
id: 'config-rss-feeds',
title: this.$strings.HeaderRSSFeeds,
path: '/config/rss-feeds'
}
]
+8 -3
View File
@@ -313,12 +313,12 @@ export default {
this.currentSFQueryString = this.buildSearchParams()
}
const entityPath = this.entityName === 'series-books' ? 'items' : this.entityName
let entityPath = this.entityName === 'series-books' ? 'items' : this.entityName
const sfQueryString = this.currentSFQueryString ? this.currentSFQueryString + '&' : ''
const fullQueryString = `?${sfQueryString}limit=${this.booksPerFetch}&page=${page}&minified=1&include=rssfeed`
const fullQueryString = `?${sfQueryString}limit=${this.booksPerFetch}&page=${page}&minified=1&include=rssfeed,numEpisodesIncomplete`
const payload = await this.$axios.$get(`/api/libraries/${this.currentLibraryId}/${entityPath}${fullQueryString}`).catch((error) => {
console.error('failed to fetch books', error)
console.error('failed to fetch items', error)
return null
})
@@ -623,6 +623,11 @@ export default {
return entitiesPerShelfBefore < this.entitiesPerShelf // Books per shelf has changed
},
async init(bookshelf) {
if (this.entityName === 'series') {
this.booksPerFetch = 50
} else {
this.booksPerFetch = 100
}
this.checkUpdateSearchParams()
this.initSizeData(bookshelf)
+17 -5
View File
@@ -89,7 +89,7 @@
<!-- Series name overlay -->
<div v-if="booksInSeries && libraryItem && isHovering" class="w-full h-full absolute top-0 left-0 z-10 bg-black bg-opacity-60 rounded flex items-center justify-center" :style="{ padding: sizeMultiplier + 'rem' }">
<p class="text-gray-200 text-center" :style="{ fontSize: 1.1 * sizeMultiplier + 'rem' }">{{ series }}</p>
<p v-if="seriesName" class="text-gray-200 text-center" :style="{ fontSize: 1.1 * sizeMultiplier + 'rem' }">{{ seriesName }}</p>
</div>
<!-- Error widget -->
@@ -116,9 +116,14 @@
</div>
<!-- Podcast Num Episodes -->
<div v-else-if="numEpisodes && !isHovering && !isSelectionMode" class="absolute rounded-full bg-black bg-opacity-90 box-shadow-md z-10 flex items-center justify-center" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', width: 1.25 * sizeMultiplier + 'rem', height: 1.25 * sizeMultiplier + 'rem' }">
<div v-else-if="!numEpisodesIncomplete && numEpisodes && !isHovering && !isSelectionMode" class="absolute rounded-full bg-black bg-opacity-90 box-shadow-md z-10 flex items-center justify-center" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', width: 1.25 * sizeMultiplier + 'rem', height: 1.25 * sizeMultiplier + 'rem' }">
<p :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">{{ numEpisodes }}</p>
</div>
<!-- Podcast Num Episodes -->
<div v-else-if="numEpisodesIncomplete && !isHovering && !isSelectionMode" class="absolute rounded-full bg-yellow-400 text-black font-semibold box-shadow-md z-10 flex items-center justify-center" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', width: 1.25 * sizeMultiplier + 'rem', height: 1.25 * sizeMultiplier + 'rem' }">
<p :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">{{ numEpisodesIncomplete }}</p>
</div>
</div>
</template>
@@ -213,8 +218,11 @@ export default {
// Only included when filtering by series or collapse series or Continue Series shelf on home page
return this.mediaMetadata.series
},
seriesName() {
return this.series?.name || null
},
seriesSequence() {
return this.series ? this.series.sequence : null
return this.series?.sequence || null
},
libraryId() {
return this._libraryItem.libraryId
@@ -227,9 +235,11 @@ export default {
return this.media.numTracks || 0 // toJSONMinified
},
numEpisodes() {
if (!this.isPodcast) return 0
return this.media.numEpisodes || 0
},
numEpisodesIncomplete() {
return this._libraryItem.numEpisodesIncomplete || 0
},
processingBatch() {
return this.store.state.processingBatch
},
@@ -311,6 +321,7 @@ export default {
if (this.orderBy === 'media.duration') return 'Duration: ' + this.$elapsedPrettyExtended(this.media.duration, false)
if (this.orderBy === 'size') return 'Size: ' + this.$bytesPretty(this._libraryItem.size)
if (this.orderBy === 'media.numTracks') return `${this.numEpisodes} Episodes`
if (this.orderBy === 'media.metadata.publishedYear' && this.mediaMetadata.publishedYear) return 'Published ' + this.mediaMetadata.publishedYear
return null
},
episodeProgress() {
@@ -680,7 +691,6 @@ export default {
.$patch(apiEndpoint, updatePayload)
.then(() => {
this.processing = false
toast.success(updatePayload.isFinished ? this.$strings.ToastItemMarkedAsFinishedSuccess : this.$strings.ToastItemMarkedAsNotFinishedSuccess)
})
.catch((error) => {
console.error('Failed', error)
@@ -757,6 +767,8 @@ export default {
this.store.commit('globals/setConfirmPrompt', payload)
},
removeSeriesFromContinueListening() {
if (!this.series) return
const axios = this.$axios || this.$nuxt.$axios
this.processing = true
axios
+1 -1
View File
@@ -36,7 +36,7 @@ export default {
return this.narrator?.name || ''
},
numBooks() {
return this.narrator?.books?.length || 0
return this.narrator?.numBooks || this.narrator?.books?.length || 0
},
userCanUpdate() {
return this.$store.getters['user/getUserCanUpdate']
@@ -1,7 +1,7 @@
<template>
<div>
<div v-if="narrators?.length" class="flex py-0.5 mt-4">
<div class="w-32">
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelNarrators }}</span>
</div>
<div class="max-w-[calc(100vw-10rem)] overflow-hidden overflow-ellipsis">
@@ -12,7 +12,7 @@
</div>
</div>
<div v-if="publishedYear" class="flex py-0.5">
<div class="w-32">
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelPublishYear }}</span>
</div>
<div>
@@ -20,15 +20,15 @@
</div>
</div>
<div v-if="publisher" class="flex py-0.5">
<div class="w-32">
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelPublisher }}</span>
</div>
<div>
{{ publisher }}
<nuxt-link :to="`/library/${libraryId}/bookshelf?filter=publishers.${$encode(publisher)}`" class="hover:underline">{{ publisher }}</nuxt-link>
</div>
</div>
<div v-if="musicAlbum" class="flex py-0.5">
<div class="w-32">
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
<span class="text-white text-opacity-60 uppercase text-sm">Album</span>
</div>
<div>
@@ -36,7 +36,7 @@
</div>
</div>
<div v-if="musicAlbumArtist" class="flex py-0.5">
<div class="w-32">
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
<span class="text-white text-opacity-60 uppercase text-sm">Album Artist</span>
</div>
<div>
@@ -44,7 +44,7 @@
</div>
</div>
<div v-if="musicTrackPretty" class="flex py-0.5">
<div class="w-32">
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
<span class="text-white text-opacity-60 uppercase text-sm">Track</span>
</div>
<div>
@@ -52,7 +52,7 @@
</div>
</div>
<div v-if="musicDiscPretty" class="flex py-0.5">
<div class="w-32">
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
<span class="text-white text-opacity-60 uppercase text-sm">Disc</span>
</div>
<div>
@@ -60,7 +60,7 @@
</div>
</div>
<div v-if="podcastType" class="flex py-0.5">
<div class="w-32">
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelPodcastType }}</span>
</div>
<div class="capitalize">
@@ -68,7 +68,7 @@
</div>
</div>
<div class="flex py-0.5" v-if="genres.length">
<div class="w-32">
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelGenres }}</span>
</div>
<div class="max-w-[calc(100vw-10rem)] overflow-hidden overflow-ellipsis">
@@ -79,7 +79,7 @@
</div>
</div>
<div class="flex py-0.5" v-if="tags.length">
<div class="w-32">
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelTags }}</span>
</div>
<div class="max-w-[calc(100vw-10rem)] overflow-hidden overflow-ellipsis">
@@ -90,7 +90,7 @@
</div>
</div>
<div v-if="tracks.length || audioFile || (isPodcast && totalPodcastDuration)" class="flex py-0.5">
<div class="w-32">
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelDuration }}</span>
</div>
<div>
@@ -98,7 +98,7 @@
</div>
</div>
<div class="flex py-0.5">
<div class="w-32">
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelSize }}</span>
</div>
<div>
+1 -1
View File
@@ -103,7 +103,7 @@ export default {
return this.$store.state.libraries.currentLibraryId
},
totalResults() {
return this.bookResults.length + this.seriesResults.length + this.authorResults.length + this.tagResults.length + this.podcastResults.length
return this.bookResults.length + this.seriesResults.length + this.authorResults.length + this.tagResults.length + this.podcastResults.length + this.narratorResults.length
}
},
methods: {
@@ -124,6 +124,11 @@ export default {
value: 'narrators',
sublist: true
},
{
text: this.$strings.LabelPublisher,
value: 'publishers',
sublist: true
},
{
text: this.$strings.LabelLanguage,
value: 'languages',
@@ -167,6 +172,11 @@ export default {
value: 'narrators',
sublist: true
},
{
text: this.$strings.LabelPublisher,
value: 'publishers',
sublist: true
},
{
text: this.$strings.LabelLanguage,
value: 'languages',
@@ -271,12 +281,16 @@ export default {
let filterValue = null
if (parts.length > 1) {
const decoded = this.$decode(parts[1])
if (decoded.startsWith('aut_')) {
if (parts[0] === 'authors') {
const author = this.authors.find((au) => au.id == decoded)
if (author) filterValue = author.name
} else if (decoded.startsWith('ser_')) {
const series = this.series.find((se) => se.id == decoded)
if (series) filterValue = series.name
} else if (parts[0] === 'series') {
if (decoded === 'no-series') {
filterValue = this.$strings.MessageNoSeries
} else {
const series = this.series.find((se) => se.id == decoded)
if (series) filterValue = series.name
}
} else {
filterValue = decoded
}
@@ -309,6 +323,9 @@ export default {
languages() {
return this.filterData.languages || []
},
publishers() {
return this.filterData.publishers || []
},
progress() {
return [
{
@@ -331,6 +348,10 @@ export default {
},
tracks() {
return [
{
id: 'none',
name: this.$strings.LabelTracksNone
},
{
id: 'single',
name: this.$strings.LabelTracksSingleTrack
+5 -2
View File
@@ -13,8 +13,8 @@
<div v-if="imageFailed" class="absolute top-0 left-0 right-0 bottom-0 w-full h-full bg-red-100" :style="{ padding: placeholderCoverPadding + 'rem' }">
<div class="w-full h-full border-2 border-error flex flex-col items-center justify-center">
<img src="/Logo.png" class="mb-2" :style="{ height: 64 * sizeMultiplier + 'px' }" />
<p class="text-center text-error" :style="{ fontSize: sizeMultiplier + 'rem' }">Invalid Cover</p>
<img v-if="width > 100" src="/Logo.png" class="mb-2" :style="{ height: 40 * sizeMultiplier + 'px' }" />
<p class="text-center text-error" :style="{ fontSize: invalidCoverFontSize + 'rem' }">Invalid Cover</p>
</div>
</div>
@@ -58,6 +58,9 @@ export default {
sizeMultiplier() {
return this.width / 120
},
invalidCoverFontSize() {
return Math.max(this.sizeMultiplier * 0.8, 0.5)
},
placeholderCoverPadding() {
return 0.8 * this.sizeMultiplier
},
+3 -3
View File
@@ -6,7 +6,7 @@
</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="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">
@@ -103,7 +103,6 @@
<ui-toggle-switch labeledBy="selected-tags-not-accessible--permissions-toggle" v-model="newUser.permissions.selectedTagsNotAccessible" />
</div>
</div>
</div>
</div>
@@ -353,7 +352,8 @@ export default {
accessAllTags: true,
selectedTagsNotAccessible: false
},
librariesAccessible: []
librariesAccessible: [],
itemTagsSelected: []
}
}
}
+132 -76
View File
@@ -1,84 +1,99 @@
<template>
<modals-modal v-model="show" name="audiofile-data-modal" :width="700" :height="'unset'">
<div v-if="audioFile" ref="container" class="w-full rounded-lg bg-bg box-shadow-md overflow-y-auto overflow-x-hidden p-6" style="max-height: 80vh">
<p class="text-base text-gray-200">{{ metadata.filename }}</p>
<div class="w-full h-px bg-white bg-opacity-10 my-4" />
<ui-text-input-with-label :value="metadata.path" readonly :label="$strings.LabelPath" class="mb-4 text-sm" />
<div class="flex flex-col sm:flex-row text-sm">
<div class="w-full sm:w-1/2">
<div class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelSize }}
</p>
<p>{{ $bytesPretty(metadata.size) }}</p>
</div>
<div class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelDuration }}
</p>
<p>{{ $secondsToTimestamp(audioFile.duration) }}</p>
</div>
<div class="flex mb-1">
<p class="w-32 text-black-50">{{ $strings.LabelFormat }}</p>
<p>{{ audioFile.format }}</p>
</div>
<div class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelChapters }}
</p>
<p>{{ audioFile.chapters?.length || 0 }}</p>
</div>
<div v-if="audioFile.embeddedCoverArt" class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelEmbeddedCover }}
</p>
<p>{{ audioFile.embeddedCoverArt || '' }}</p>
</div>
</div>
<div class="w-full sm:w-1/2">
<div class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelCodec }}
</p>
<p>{{ audioFile.codec }}</p>
</div>
<div class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelChannels }}
</p>
<p>{{ audioFile.channels }} ({{ audioFile.channelLayout }})</p>
</div>
<div class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelBitrate }}
</p>
<p>{{ $bytesPretty(audioFile.bitRate || 0, 0) }}</p>
</div>
<div class="flex mb-1">
<p class="w-32 text-black-50">{{ $strings.LabelTimeBase }}</p>
<p>{{ audioFile.timeBase }}</p>
</div>
<div v-if="audioFile.language" class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelLanguage }}
</p>
<p>{{ audioFile.language || '' }}</p>
</div>
</div>
<div class="flex items-center justify-between">
<p class="text-base text-gray-200 truncate">{{ metadata.filename }}</p>
<ui-btn v-if="ffprobeData" small class="ml-2" @click="ffprobeData = null">{{ $strings.ButtonReset }}</ui-btn>
<ui-btn v-else-if="userIsAdminOrUp" small :loading="probingFile" class="ml-2" @click="getFFProbeData">Probe Audio File</ui-btn>
</div>
<div class="w-full h-px bg-white bg-opacity-10 my-4" />
<p class="font-bold mb-2">{{ $strings.LabelMetaTags }}</p>
<template v-if="!ffprobeData">
<ui-text-input-with-label :value="metadata.path" readonly :label="$strings.LabelPath" class="mb-4 text-sm" />
<div v-for="(value, key) in metaTags" :key="key" class="flex mb-1 text-sm">
<p class="w-32 min-w-32 text-black-50 mb-1">
{{ key.replace('tag', '') }}
</p>
<p>{{ value }}</p>
<div class="flex flex-col sm:flex-row text-sm">
<div class="w-full sm:w-1/2">
<div class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelSize }}
</p>
<p>{{ $bytesPretty(metadata.size) }}</p>
</div>
<div class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelDuration }}
</p>
<p>{{ $secondsToTimestamp(audioFile.duration) }}</p>
</div>
<div class="flex mb-1">
<p class="w-32 text-black-50">{{ $strings.LabelFormat }}</p>
<p>{{ audioFile.format }}</p>
</div>
<div class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelChapters }}
</p>
<p>{{ audioFile.chapters?.length || 0 }}</p>
</div>
<div v-if="audioFile.embeddedCoverArt" class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelEmbeddedCover }}
</p>
<p>{{ audioFile.embeddedCoverArt || '' }}</p>
</div>
</div>
<div class="w-full sm:w-1/2">
<div class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelCodec }}
</p>
<p>{{ audioFile.codec }}</p>
</div>
<div class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelChannels }}
</p>
<p>{{ audioFile.channels }} ({{ audioFile.channelLayout }})</p>
</div>
<div class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelBitrate }}
</p>
<p>{{ $bytesPretty(audioFile.bitRate || 0, 0) }}</p>
</div>
<div class="flex mb-1">
<p class="w-32 text-black-50">{{ $strings.LabelTimeBase }}</p>
<p>{{ audioFile.timeBase }}</p>
</div>
<div v-if="audioFile.language" class="flex mb-1">
<p class="w-32 text-black-50">
{{ $strings.LabelLanguage }}
</p>
<p>{{ audioFile.language || '' }}</p>
</div>
</div>
</div>
<div class="w-full h-px bg-white bg-opacity-10 my-4" />
<p class="font-bold mb-2">{{ $strings.LabelMetaTags }}</p>
<div v-for="(value, key) in metaTags" :key="key" class="flex mb-1 text-sm">
<p class="w-32 min-w-32 text-black-50 mb-1">
{{ key.replace('tag', '') }}
</p>
<p>{{ value }}</p>
</div>
</template>
<div v-else class="w-full">
<div class="relative">
<ui-textarea-with-label :value="prettyFfprobeData" readonly :rows="30" class="text-xs" />
<button class="absolute top-4 right-4" :class="copiedToClipboard ? 'text-success' : 'text-white/50 hover:text-white/80'" @click.stop="copyFfprobeData">
<span class="material-icons">{{ copiedToClipboard ? 'check' : 'content_copy' }}</span>
</button>
</div>
</div>
</div>
</modals-modal>
@@ -91,10 +106,24 @@ export default {
audioFile: {
type: Object,
default: () => {}
}
},
libraryItemId: String
},
data() {
return {}
return {
probingFile: false,
ffprobeData: null,
copiedToClipboard: false
}
},
watch: {
show(newVal) {
if (newVal) {
this.ffprobeData = null
this.copiedToClipboard = false
this.probingFile = false
}
}
},
computed: {
show: {
@@ -110,9 +139,36 @@ export default {
},
metaTags() {
return this.audioFile?.metaTags || {}
},
userIsAdminOrUp() {
return this.$store.getters['user/getIsAdminOrUp']
},
prettyFfprobeData() {
if (!this.ffprobeData) return ''
return JSON.stringify(this.ffprobeData, null, 2)
}
},
methods: {
getFFProbeData() {
this.probingFile = true
this.$axios
.$get(`/api/items/${this.libraryItemId}/ffprobe/${this.audioFile.ino}`)
.then((data) => {
console.log('Got ffprobe data', data)
this.ffprobeData = data
})
.catch((error) => {
console.error('Failed to get ffprobe data', error)
this.$toast.error('FFProbe failed')
})
.finally(() => {
this.probingFile = false
})
},
async copyFfprobeData() {
this.copiedToClipboard = await this.$copyToClipboard(this.prettyFfprobeData)
}
},
methods: {},
mounted() {}
}
</script>
+1 -1
View File
@@ -48,7 +48,7 @@ export default {
},
methods: {
clickedOption(action) {
this.$emit('action', action)
this.$emit('action', { action })
}
},
mounted() {}
@@ -2,7 +2,7 @@
<modals-modal v-model="show" name="listening-session-modal" :processing="processing" :width="700" :height="'unset'">
<template #outer>
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
<p class="text-3xl text-white truncate">{{ $strings.HeaderSession }} {{ _session.id }}</p>
<p class="text-lg md:text-2xl text-white truncate">{{ $strings.HeaderSession }} {{ _session.id }}</p>
</div>
</template>
<div ref="container" class="w-full rounded-lg bg-bg box-shadow-md overflow-y-auto overflow-x-hidden p-6" style="max-height: 80vh">
@@ -50,19 +50,19 @@
<p class="font-semibold uppercase text-xs text-gray-400 tracking-wide mt-6 mb-2">{{ $strings.LabelItem }}</p>
<div v-if="_session.libraryId" class="flex items-center -mx-1 mb-1">
<div class="w-40 px-1 text-gray-200">{{ $strings.LabelLibrary }} Id</div>
<div class="px-1">
<div class="px-1 text-xs">
{{ _session.libraryId }}
</div>
</div>
<div class="flex items-center -mx-1 mb-1">
<div class="w-40 px-1 text-gray-200">{{ $strings.LabelLibraryItem }} Id</div>
<div class="px-1">
<div class="px-1 text-xs">
{{ _session.libraryItemId }}
</div>
</div>
<div v-if="_session.episodeId" class="flex items-center -mx-1 mb-1">
<div class="w-40 px-1 text-gray-200">{{ $strings.LabelEpisode }} Id</div>
<div class="px-1">
<div class="px-1 text-xs">
{{ _session.episodeId }}
</div>
</div>
@@ -81,7 +81,7 @@
</div>
<div class="w-full md:w-1/3">
<p class="font-semibold uppercase text-xs text-gray-400 tracking-wide mb-2 mt-6 md:mt-0">{{ $strings.LabelUser }}</p>
<p class="mb-1">{{ _session.userId }}</p>
<p class="mb-1 text-xs">{{ _session.userId }}</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>
+3 -3
View File
@@ -2,11 +2,11 @@
<div ref="wrapper" class="modal modal-bg w-full h-full fixed top-0 left-0 bg-primary items-center justify-center opacity-0 hidden" :class="`z-${zIndex} bg-opacity-${bgOpacity}`">
<div class="absolute top-0 left-0 right-0 w-full h-36 bg-gradient-to-t from-transparent via-black-500 to-black-700 opacity-90 pointer-events-none" />
<div class="absolute top-3 right-3 landscape:top-2 landscape:right-2 md:portrait:top-5 md:portrait:right-5 lg:top-5 lg:right-5 h-8 w-8 landscape:h-8 landscape:w-8 md:portrait:h-12 md:portrait:w-12 lg:w-12 lg:h-12 flex items-center justify-center cursor-pointer text-white hover:text-gray-300" @click="clickClose">
<button class="absolute top-4 right-4 landscape:top-4 landscape:right-4 md:portrait:top-5 md:portrait:right-5 lg:top-5 lg:right-5 inline-flex text-gray-200 hover:text-white" aria-label="Close modal" @click="clickClose">
<span class="material-icons text-2xl landscape:text-2xl md:portrait:text-4xl lg:text-4xl">close</span>
</div>
</button>
<slot name="outer" />
<div ref="content" style="min-width: 380px; min-height: 200px; max-width: 100vw" class="relative text-white" :style="{ height: modalHeight, width: modalWidth, marginTop: contentMarginTop + 'px' }" @mousedown="mousedownModal" @mouseup="mouseupModal" v-click-outside="clickBg">
<div ref="content" style="min-width: 380px; min-height: 200px; max-width: 100vw" class="relative text-white" aria-modal="true" :style="{ height: modalHeight, width: modalWidth, marginTop: contentMarginTop + 'px' }" @mousedown="mousedownModal" @mouseup="mouseupModal" v-click-outside="clickBg">
<slot />
<div v-if="processing" class="absolute top-0 left-0 right-0 bottom-0 w-full h-full bg-black bg-opacity-60 rounded-lg flex items-center justify-center">
<ui-loading-indicator />
+31 -1
View File
@@ -33,8 +33,10 @@
</div>
<div class="flex pt-2 px-2">
<ui-btn type="button" @click="searchAuthor">{{ $strings.ButtonQuickMatch }}</ui-btn>
<ui-btn v-if="userCanDelete" small color="error" type="button" @click.stop="removeClick">{{ $strings.ButtonRemove }}</ui-btn>
<div class="flex-grow" />
<ui-btn type="button" class="mx-2" @click="searchAuthor">{{ $strings.ButtonQuickMatch }}</ui-btn>
<ui-btn type="submit">{{ $strings.ButtonSave }}</ui-btn>
</div>
</div>
@@ -91,6 +93,9 @@ export default {
},
libraryProvider() {
return this.$store.getters['libraries/getLibraryProvider'](this.currentLibraryId) || 'google'
},
userCanDelete() {
return this.$store.getters['user/getUserCanDelete']
}
},
methods: {
@@ -100,6 +105,31 @@ export default {
this.authorCopy.description = this.author.description
this.authorCopy.imagePath = this.author.imagePath
},
removeClick() {
const payload = {
message: this.$getString('MessageConfirmRemoveAuthor', [this.author.name]),
callback: (confirmed) => {
if (confirmed) {
this.processing = true
this.$axios
.$delete(`/api/authors/${this.authorId}`)
.then(() => {
this.$toast.success('Author removed')
this.show = false
})
.catch((error) => {
console.error('Failed to remove author', error)
this.$toast.error('Failed to remove author')
})
.finally(() => {
this.processing = false
})
}
},
type: 'yesNo'
}
this.$store.commit('globals/setConfirmPrompt', payload)
},
async submitForm() {
var keysToCheck = ['name', 'asin', 'description', 'imagePath']
var updatePayload = {}
@@ -8,10 +8,9 @@
<div class="p-4 w-full text-sm py-6 rounded-lg bg-bg shadow-lg border border-black-300 relative overflow-hidden" style="min-height: 400px; max-height: 80vh">
<template v-if="!showImageUploader">
<form @submit.prevent="submitForm">
<div class="flex">
<div>
<div class="flex flex-wrap">
<div class="w-full flex justify-center mb-2 md:w-auto md:mb-0 md:block">
<covers-collection-cover :book-items="books" :width="200" :height="100 * bookCoverAspectRatio" :book-cover-aspect-ratio="bookCoverAspectRatio" />
<!-- <ui-btn type="button" @click="showImageUploader = true">Upload</ui-btn> -->
</div>
<div class="flex-grow px-4">
<ui-text-input-with-label v-model="newCollectionName" :label="$strings.LabelName" class="mb-2" />
@@ -41,7 +40,6 @@
<ui-btn color="success">Upload</ui-btn>
</div>
</template>
<!-- <modals-upload-image-modal v-model="showUploadImageModal" entity="collection" :entity-id="collection.id" /> -->
</div>
</modals-modal>
</template>
+11 -9
View File
@@ -1,8 +1,8 @@
<template>
<div class="w-full h-full overflow-hidden overflow-y-auto px-2 sm:px-4 py-6 relative">
<div class="flex flex-wrap">
<div class="flex flex-wrap mb-4">
<div class="relative">
<covers-preview-cover :src="$store.getters['globals/getLibraryItemCoverSrcById'](libraryItemId, null, true)" :width="120" :book-cover-aspect-ratio="bookCoverAspectRatio" />
<covers-preview-cover :src="$store.getters['globals/getLibraryItemCoverSrcById'](libraryItemId, libraryItemUpdatedAt, true)" :width="120" :book-cover-aspect-ratio="bookCoverAspectRatio" />
<!-- book cover overlay -->
<div v-if="media.coverPath" class="absolute top-0 left-0 w-full h-full z-10 opacity-0 hover:opacity-100 transition-opacity duration-100">
@@ -139,16 +139,19 @@ export default {
return this.$store.getters['libraries/getBookCoverAspectRatio']
},
libraryItemId() {
return this.libraryItem ? this.libraryItem.id : null
return this.libraryItem?.id || null
},
libraryItemUpdatedAt() {
return this.libraryItem?.updatedAt || null
},
mediaType() {
return this.libraryItem ? this.libraryItem.mediaType : null
return this.libraryItem?.mediaType || null
},
isPodcast() {
return this.mediaType == 'podcast'
},
media() {
return this.libraryItem ? this.libraryItem.media || {} : {}
return this.libraryItem?.media || {}
},
coverPath() {
return this.media.coverPath
@@ -157,7 +160,7 @@ export default {
return this.media.metadata || {}
},
libraryFiles() {
return this.libraryItem ? this.libraryItem.libraryFiles || [] : []
return this.libraryItem?.libraryFiles || []
},
userCanUpload() {
return this.$store.getters['user/getUserCanUpload']
@@ -280,9 +283,8 @@ export default {
}
if (success) {
this.$toast.success('Update Successful')
// this.$emit('close')
} else {
this.imageUrl = this.media.coverPath || ''
} else if (this.media.coverPath) {
this.imageUrl = this.media.coverPath
}
this.isProcessing = false
},
@@ -20,18 +20,14 @@
<div v-if="!episodes.length" class="flex my-4 text-center justify-center text-xl">{{ $strings.MessageNoEpisodes }}</div>
<table v-else class="text-sm tracksTable">
<tr>
<th class="text-left">Sort #</th>
<th class="text-left whitespace-nowrap">{{ $strings.LabelEpisode }}</th>
<th class="text-left">{{ $strings.EpisodeTitle }}</th>
<th class="text-center w-28">{{ $strings.EpisodeDuration }}</th>
<th class="text-center w-28">{{ $strings.EpisodeSize }}</th>
<th class="text-center w-20 min-w-20">{{ $strings.LabelEpisode }}</th>
<th class="text-left">{{ $strings.LabelEpisodeTitle }}</th>
<th class="text-center w-28">{{ $strings.LabelEpisodeDuration }}</th>
<th class="text-center w-28">{{ $strings.LabelEpisodeSize }}</th>
</tr>
<tr v-for="episode in episodes" :key="episode.id">
<td class="text-left">
<p class="px-4">{{ episode.index }}</p>
</td>
<td class="text-left">
<p class="px-4">{{ episode.episode }}</p>
<td class="text-center w-20 min-w-20">
<p>{{ episode.episode }}</p>
</td>
<td>
{{ episode.title }}
+6 -5
View File
@@ -205,7 +205,7 @@ export default {
processing: Boolean,
libraryItem: {
type: Object,
default: () => {}
default: () => { }
}
},
data() {
@@ -305,7 +305,7 @@ export default {
const filterData = this.$store.state.libraries.filterData || {}
const currentGenres = filterData.genres || []
const selectedMatchGenres = this.selectedMatch.genres || []
return [...new Set([...currentGenres ,...selectedMatchGenres])]
return [...new Set([...currentGenres, ...selectedMatchGenres])]
}
},
methods: {
@@ -325,9 +325,9 @@ export default {
}
},
getSearchQuery() {
if (this.isPodcast) return `term=${this.searchTitle}`
var searchQuery = `provider=${this.provider}&fallbackTitleOnly=1&title=${this.searchTitle}`
if (this.searchAuthor) searchQuery += `&author=${this.searchAuthor}`
if (this.isPodcast) return `term=${encodeURIComponent(this.searchTitle)}`
var searchQuery = `provider=${this.provider}&fallbackTitleOnly=1&title=${encodeURIComponent(this.searchTitle)}`
if (this.searchAuthor) searchQuery += `&author=${encodeURIComponent(this.searchAuthor)}`
return searchQuery
},
submitSearch() {
@@ -580,6 +580,7 @@ export default {
.matchListWrapper {
height: calc(100% - 124px);
}
@media (min-width: 768px) {
.matchListWrapper {
height: calc(100% - 80px);
@@ -20,7 +20,7 @@
<p class="px-1 text-sm font-semibold">{{ $strings.LabelFolders }}</p>
<div v-for="(folder, index) in folders" :key="index" class="w-full flex items-center py-1 px-2">
<span class="material-icons bg-opacity-50 mr-2 text-yellow-200" style="font-size: 1.2rem">folder</span>
<ui-editable-text ref="folderInput" v-model="folder.fullPath" readonly type="text" class="w-full" />
<ui-editable-text ref="folderInput" v-model="folder.fullPath" :readonly="!!folder.id" type="text" class="w-full" @blur="existingFolderInputBlurred(folder)" />
<span v-show="folders.length > 1" class="material-icons text-2xl ml-2 cursor-pointer hover:text-error" @click="removeFolder(folder)">close</span>
</div>
<div class="flex py-1 px-2 items-center w-full">
@@ -67,10 +67,6 @@ export default {
value: 'podcast',
text: this.$strings.LabelPodcasts
}
// {
// value: 'music',
// text: 'Music'
// }
]
},
folderPaths() {
@@ -110,6 +106,11 @@ export default {
formUpdated() {
this.$emit('update', this.getLibraryData())
},
existingFolderInputBlurred(folder) {
if (!folder.fullPath) {
this.removeFolder(folder)
}
},
newFolderInputBlurred() {
if (this.newFolderPath) {
this.folders.push({ fullPath: this.newFolderPath })
@@ -149,6 +150,7 @@ export default {
this.folders = this.library ? this.library.folders.map((p) => ({ ...p })) : []
this.icon = this.library ? this.library.icon : 'default'
this.mediaType = this.library ? this.library.mediaType : 'book'
this.showDirectoryPicker = false
}
},
@@ -120,7 +120,7 @@ export default {
for (const key in this.libraryCopy) {
if (library[key] !== undefined) {
if (key === 'folders') {
this.libraryCopy.folders = library.folders.map((f) => ({ ...f }))
this.libraryCopy.folders = library.folders.map((f) => ({ ...f })).filter((f) => !!f.fullPath?.trim())
} else if (key === 'settings') {
for (const settingKey in library.settings) {
this.libraryCopy.settings[settingKey] = library.settings[settingKey]
@@ -11,9 +11,9 @@
</div>
<div class="py-3">
<div class="flex items-center">
<ui-toggle-switch v-if="!globalWatcherDisabled" v-model="disableWatcher" @input="formUpdated" />
<ui-toggle-switch v-if="!globalWatcherDisabled" v-model="enableWatcher" @input="formUpdated" />
<ui-toggle-switch v-else disabled :value="false" />
<p class="pl-4 text-base">{{ $strings.LabelSettingsDisableWatcherForLibrary }}</p>
<p class="pl-4 text-base">{{ $strings.LabelSettingsEnableWatcherForLibrary }}</p>
</div>
<p v-if="globalWatcherDisabled" class="text-xs text-warning">*{{ $strings.MessageWatcherIsDisabledGlobally }}</p>
</div>
@@ -38,6 +38,17 @@
<p class="pl-4 text-base">{{ $strings.LabelSettingsSkipMatchingBooksWithISBN }}</p>
</div>
</div>
<div v-if="isBookLibrary" class="py-3">
<div class="flex items-center">
<ui-toggle-switch v-model="hideSingleBookSeries" @input="formUpdated" />
<ui-tooltip :text="$strings.LabelSettingsHideSingleBookSeriesHelp">
<p class="pl-4 text-base">
{{ $strings.LabelSettingsHideSingleBookSeries }}
<span class="material-icons icon-text text-sm">info_outlined</span>
</p>
</ui-tooltip>
</div>
</div>
</div>
</template>
@@ -54,10 +65,11 @@ export default {
return {
provider: null,
useSquareBookCovers: false,
disableWatcher: false,
enableWatcher: false,
skipMatchingMediaWithAsin: false,
skipMatchingMediaWithIsbn: false,
audiobooksOnly: false
audiobooksOnly: false,
hideSingleBookSeries: false
}
},
computed: {
@@ -83,10 +95,11 @@ export default {
return {
settings: {
coverAspectRatio: this.useSquareBookCovers ? this.$constants.BookCoverAspectRatio.SQUARE : this.$constants.BookCoverAspectRatio.STANDARD,
disableWatcher: !!this.disableWatcher,
disableWatcher: !this.enableWatcher,
skipMatchingMediaWithAsin: !!this.skipMatchingMediaWithAsin,
skipMatchingMediaWithIsbn: !!this.skipMatchingMediaWithIsbn,
audiobooksOnly: !!this.audiobooksOnly
audiobooksOnly: !!this.audiobooksOnly,
hideSingleBookSeries: !!this.hideSingleBookSeries
}
}
},
@@ -95,10 +108,11 @@ export default {
},
init() {
this.useSquareBookCovers = this.librarySettings.coverAspectRatio === this.$constants.BookCoverAspectRatio.SQUARE
this.disableWatcher = !!this.librarySettings.disableWatcher
this.enableWatcher = !this.librarySettings.disableWatcher
this.skipMatchingMediaWithAsin = !!this.librarySettings.skipMatchingMediaWithAsin
this.skipMatchingMediaWithIsbn = !!this.librarySettings.skipMatchingMediaWithIsbn
this.audiobooksOnly = !!this.librarySettings.audiobooksOnly
this.hideSingleBookSeries = !!this.librarySettings.hideSingleBookSeries
}
},
mounted() {
@@ -39,7 +39,7 @@
</div>
</div>
<div class="flex justify-end pt-4">
<ui-checkbox v-if="!allDownloaded" v-model="selectAll" @input="toggleSelectAll" label="Select all episodes" small checkbox-bg="primary" border-color="gray-600" class="mx-8" />
<ui-checkbox v-if="!allDownloaded" v-model="selectAll" @input="toggleSelectAll" :label="selectAllLabel" small checkbox-bg="primary" border-color="gray-600" class="mx-8" />
<ui-btn v-if="!allDownloaded" :disabled="!episodesSelected.length" @click="submit">{{ buttonText }}</ui-btn>
<p v-else class="text-success text-base px-2 py-4">All episodes are downloaded</p>
</div>
@@ -99,46 +99,82 @@ export default {
return Object.keys(this.selectedEpisodes).filter((key) => !!this.selectedEpisodes[key])
},
buttonText() {
if (!this.episodesSelected.length) return 'No Episodes Selected'
return `Download ${this.episodesSelected.length} Episode${this.episodesSelected.length > 1 ? 's' : ''}`
if (!this.episodesSelected.length) return this.$strings.LabelNoEpisodesSelected
if (this.episodesSelected.length === 1) return `${this.$strings.LabelDownload} ${this.$strings.LabelEpisode.toLowerCase()}`
return this.$getString('LabelDownloadNEpisodes', [this.episodesSelected.length])
},
itemEpisodes() {
if (!this.libraryItem) return []
return this.libraryItem.media.episodes || []
},
itemEpisodeMap() {
var map = {}
const map = {}
this.itemEpisodes.forEach((item) => {
if (item.enclosure) map[item.enclosure.url.split('?')[0]] = true
if (item.enclosure) {
const cleanUrl = this.getCleanEpisodeUrl(item.enclosure.url)
map[cleanUrl] = true
}
})
return map
},
episodesList() {
return this.episodesCleaned.filter((episode) => {
if (!this.searchText) return true
return (episode.title && episode.title.toLowerCase().includes(this.searchText)) || (episode.subtitle && episode.subtitle.toLowerCase().includes(this.searchText))
return episode.title?.toLowerCase().includes(this.searchText) || episode.subtitle?.toLowerCase().includes(this.searchText)
})
},
selectAllLabel() {
if (this.episodesList.length === this.episodesCleaned.length) {
return this.$strings.LabelSelectAllEpisodes
}
const episodesNotDownloaded = this.episodesList.filter((ep) => !this.itemEpisodeMap[ep.cleanUrl]).length
return this.$getString('LabelSelectEpisodesShowing', [episodesNotDownloaded])
}
},
methods: {
/**
* RSS feed episode url is used for matching with existing downloaded episodes.
* Some RSS feeds include timestamps in the episode url (e.g. patreon) that can change on requests.
* These need to be removed in order to detect the same episode each time the feed is pulled.
*
* An RSS feed may include an `id` in the query string. In these cases we want to leave the `id`.
* @see https://github.com/advplyr/audiobookshelf/issues/1896
*
* @param {string} url - rss feed episode url
* @returns {string} rss feed episode url without dynamic query strings
*/
getCleanEpisodeUrl(url) {
let queryString = url.split('?')[1]
if (!queryString) return url
const searchParams = new URLSearchParams(queryString)
for (const p of Array.from(searchParams.keys())) {
if (p !== 'id') searchParams.delete(p)
}
if (!searchParams.toString()) return url
return `${url}?${searchParams.toString()}`
},
inputUpdate() {
clearTimeout(this.searchTimeout)
this.searchTimeout = setTimeout(() => {
if (!this.search || !this.search.trim()) {
if (!this.search?.trim()) {
this.searchText = ''
this.checkSetIsSelectedAll()
return
}
this.searchText = this.search.toLowerCase().trim()
this.checkSetIsSelectedAll()
}, 500)
},
toggleSelectAll(val) {
for (const episode of this.episodesCleaned) {
for (const episode of this.episodesList) {
if (this.itemEpisodeMap[episode.cleanUrl]) this.selectedEpisodes[episode.cleanUrl] = false
else this.$set(this.selectedEpisodes, episode.cleanUrl, val)
}
},
checkSetIsSelectedAll() {
for (const episode of this.episodesCleaned) {
for (const episode of this.episodesList) {
if (!this.itemEpisodeMap[episode.cleanUrl] && !this.selectedEpisodes[episode.cleanUrl]) {
this.selectAll = false
return
@@ -147,19 +183,19 @@ export default {
this.selectAll = true
},
toggleSelectEpisode(episode) {
if (this.itemEpisodeMap[episode.enclosure.url?.split('?')[0]]) return
if (this.itemEpisodeMap[episode.cleanUrl]) return
this.$set(this.selectedEpisodes, episode.cleanUrl, !this.selectedEpisodes[episode.cleanUrl])
this.checkSetIsSelectedAll()
},
submit() {
var episodesToDownload = []
let episodesToDownload = []
if (this.episodesSelected.length) {
episodesToDownload = this.episodesSelected.map((cleanUrl) => this.episodesCleaned.find((ep) => ep.cleanUrl == cleanUrl))
}
var payloadSize = JSON.stringify(episodesToDownload).length
var sizeInMb = payloadSize / 1024 / 1024
var sizeInMbPretty = sizeInMb.toFixed(2) + 'MB'
const payloadSize = JSON.stringify(episodesToDownload).length
const sizeInMb = payloadSize / 1024 / 1024
const sizeInMbPretty = sizeInMb.toFixed(2) + 'MB'
console.log('Request size', sizeInMb)
if (sizeInMb > 4.99) {
return this.$toast.error(`Request is too large (${sizeInMbPretty}) should be < 5Mb`)
@@ -174,10 +210,9 @@ export default {
this.show = false
})
.catch((error) => {
var errorMsg = error.response && error.response.data ? error.response.data : 'Failed to download episodes'
console.error('Failed to download episodes', error)
this.processing = false
this.$toast.error(errorMsg)
this.$toast.error(error.response?.data || 'Failed to download episodes')
this.selectedEpisodes = {}
this.selectAll = false
@@ -189,7 +224,7 @@ export default {
.map((_ep) => {
return {
..._ep,
cleanUrl: _ep.enclosure.url.split('?')[0]
cleanUrl: this.getCleanEpisodeUrl(_ep.enclosure.url)
}
})
this.episodesCleaned.sort((a, b) => (a.publishedAt < b.publishedAt ? 1 : -1))
@@ -132,6 +132,8 @@ export default {
return
}
this.processing = true
const payload = {
serverAddress: window.origin,
slug: this.newFeedSlug,
@@ -151,6 +153,9 @@ export default {
const errorMsg = error.response ? error.response.data : null
this.$toast.error(errorMsg || 'Failed to open RSS Feed')
})
.finally(() => {
this.processing = false
})
},
copyToClipboard(str) {
this.$copyToClipboard(str, this)
@@ -0,0 +1,124 @@
<template>
<modals-modal v-model="show" name="rss-feed-view-modal" :processing="processing" :width="700" :height="'unset'">
<div ref="wrapper" class="px-8 py-6 w-full text-sm rounded-lg bg-bg shadow-lg border border-black-300 relative overflow-hidden">
<div v-if="feed" class="w-full">
<p class="text-lg font-semibold mb-4">{{ $strings.HeaderRSSFeedGeneral }}</p>
<div class="w-full relative">
<ui-text-input v-model="feed.feedUrl" readonly />
<span class="material-icons absolute right-2 bottom-2 p-0.5 text-base transition-transform duration-100 text-gray-300 hover:text-white transform hover:scale-125 cursor-pointer" @click="copyToClipboard(feed.feedUrl)">content_copy</span>
</div>
<div v-if="feed.meta" class="mt-5">
<div class="flex py-0.5">
<div class="w-48">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelRSSFeedPreventIndexing }}</span>
</div>
<div>{{ feed.meta.preventIndexing ? 'Yes' : 'No' }}</div>
</div>
<div v-if="feed.meta.ownerName" class="flex py-0.5">
<div class="w-48">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelRSSFeedCustomOwnerName }}</span>
</div>
<div>{{ feed.meta.ownerName }}</div>
</div>
<div v-if="feed.meta.ownerEmail" class="flex py-0.5">
<div class="w-48">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelRSSFeedCustomOwnerEmail }}</span>
</div>
<div>{{ feed.meta.ownerEmail }}</div>
</div>
</div>
<!-- -->
<div class="episodesTable mt-2">
<div class="bg-primary bg-opacity-40 h-12 header">
{{ $strings.LabelEpisodeTitle }}
</div>
<div class="scroller">
<div v-for="episode in feed.episodes" :key="episode.id" class="h-8 text-xs truncate">
{{ episode.title }}
</div>
</div>
</div>
</div>
</div>
</modals-modal>
</template>
<script>
export default {
props: {
value: Boolean,
feed: {
type: Object,
default: () => {}
}
},
data() {
return {
processing: false
}
},
computed: {
show: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
},
_feed() {
return this.feed || {}
}
},
methods: {
copyToClipboard(str) {
this.$copyToClipboard(str, this)
}
},
mounted() {}
}
</script>
<style scoped>
.episodesTable {
width: 100%;
max-width: 100%;
border: 1px solid #474747;
display: flex;
flex-direction: column;
}
.episodesTable div.header {
background-color: #272727;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
padding: 4px 8px;
}
.episodesTable .scroller {
display: flex;
flex-direction: column;
max-height: 250px;
overflow-x: hidden;
overflow-y: scroll;
}
.episodesTable .scroller div {
background-color: #373838;
padding: 4px 8px;
display: flex;
align-items: center;
justify-content: flex-start;
height: 32px;
flex: 0 0 32px;
}
.episodesTable .scroller div:nth-child(even) {
background-color: #2f2f2f;
}
</style>
+4 -4
View File
@@ -109,10 +109,10 @@ export default {
return this.comicMetadata ? Object.keys(this.comicMetadata) : []
},
canGoNext() {
return this.page < this.numPages - 1
return this.page < this.numPages
},
canGoPrev() {
return this.page > 0
return this.page > 1
},
userMediaProgress() {
if (!this.libraryItemId) return
@@ -303,8 +303,8 @@ export default {
},
parseImageFilename(filename) {
var basename = Path.basename(filename, Path.extname(filename))
var numbersinpath = basename.match(/\d{1,5}/g)
if (!numbersinpath || !numbersinpath.length) {
var numbersinpath = basename.match(/\d+/g)
if (!numbersinpath?.length) {
return {
index: -1,
filename
+64 -23
View File
@@ -1,15 +1,15 @@
<template>
<div id="epub-reader" class="h-full w-full">
<div class="h-full flex items-center justify-center">
<div style="width: 100px; max-width: 100px" class="h-full hidden sm:flex items-center overflow-x-hidden justify-center">
<span v-if="hasPrev" class="material-icons text-white text-opacity-50 hover:text-opacity-80 cursor-pointer text-6xl" @mousedown.prevent @click="prev">chevron_left</span>
</div>
<button type="button" aria-label="Previous page" class="w-24 max-w-24 h-full hidden sm:flex items-center overflow-x-hidden justify-center opacity-50 hover:opacity-100">
<span v-if="hasPrev" class="material-icons text-6xl" @mousedown.prevent @click="prev">chevron_left</span>
</button>
<div id="frame" class="w-full" style="height: 80%">
<div id="viewer"></div>
</div>
<div style="width: 100px; max-width: 100px" class="h-full hidden sm:flex items-center justify-center overflow-x-hidden">
<span v-if="hasNext" class="material-icons text-white text-opacity-50 hover:text-opacity-80 cursor-pointer text-6xl" @mousedown.prevent @click="next">chevron_right</span>
</div>
<button type="button" aria-label="Next page" class="w-24 max-w-24 h-full hidden sm:flex items-center justify-center overflow-x-hidden opacity-50 hover:opacity-100">
<span v-if="hasNext" class="material-icons text-6xl" @mousedown.prevent @click="next">chevron_right</span>
</button>
</div>
</div>
</template>
@@ -39,7 +39,13 @@ export default {
/** @type {ePub.Book} */
book: null,
/** @type {ePub.Rendition} */
rendition: null
rendition: null,
ereaderSettings: {
theme: 'dark',
fontScale: 100,
lineSpacing: 115,
spread: 'auto'
}
}
},
watch: {
@@ -63,7 +69,7 @@ export default {
},
/** @returns {Array<ePub.NavItem>} */
chapters() {
return this.book ? this.book.navigation.toc : []
return this.book?.navigation?.toc || []
},
userMediaProgress() {
if (!this.libraryItemId) return
@@ -92,16 +98,50 @@ export default {
return `/api/items/${this.libraryItemId}/ebook/${this.fileId}`
}
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 lineSpacing = this.ereaderSettings.lineSpacing / 100
const fontScale = this.ereaderSettings.fontScale / 100
return {
'*': {
color: `${fontColor}!important`,
'background-color': `${backgroundColor}!important`,
'line-height': lineSpacing * fontScale + 'rem!important'
},
a: {
color: `${fontColor}!important`
}
}
}
},
methods: {
updateSettings(settings) {
this.ereaderSettings = settings
if (!this.rendition) return
this.applyTheme()
const fontScale = settings.fontScale || 100
this.rendition.themes.fontSize(`${fontScale}%`)
this.rendition.spread(settings.spread || 'auto')
},
prev() {
if (!this.rendition?.manager) return
return this.rendition?.prev()
},
next() {
if (!this.rendition?.manager) return
return this.rendition?.next()
},
goToChapter(href) {
if (!this.rendition?.manager) return
return this.rendition?.display(href)
},
keyUp(e) {
@@ -242,35 +282,30 @@ export default {
/** @type {ePub.Rendition} */
reader.rendition = reader.book.renderTo('viewer', {
width: this.readerWidth,
height: this.readerHeight * 0.8
height: this.readerHeight * 0.8,
spread: 'auto',
snap: true,
manager: 'continuous',
flow: 'paginated'
})
// load saved progress
reader.rendition.display(this.savedEbookLocation || reader.book.locations.start)
// load style
reader.rendition.themes.default({ '*': { color: '#fff!important', 'background-color': 'rgb(35 35 35)!important' }, a: { color: '#fff!important' } })
reader.rendition.on('rendered', () => {
this.applyTheme()
})
reader.book.ready.then(() => {
// set up event listeners
reader.rendition.on('relocated', reader.relocated)
reader.rendition.on('keydown', reader.keyUp)
let touchStart = 0
let touchEnd = 0
reader.rendition.on('touchstart', (event) => {
touchStart = event.changedTouches[0].screenX
this.$emit('touchstart', event)
})
reader.rendition.on('touchend', (event) => {
touchEnd = event.changedTouches[0].screenX
const touchDistanceX = Math.abs(touchEnd - touchStart)
if (touchStart < touchEnd && touchDistanceX > 120) {
this.next()
}
if (touchStart > touchEnd && touchDistanceX > 120) {
this.prev()
}
this.$emit('touchend', event)
})
// load ebook cfi locations
@@ -288,6 +323,12 @@ export default {
this.windowWidth = window.innerWidth
this.windowHeight = window.innerHeight
this.rendition?.resize(this.readerWidth, this.readerHeight * 0.8)
},
applyTheme() {
if (!this.rendition) return
this.rendition.getContents().forEach((c) => {
c.addStylesheetRules(this.themeRules)
})
}
},
mounted() {
+2 -2
View File
@@ -11,10 +11,10 @@
</div>
</div>
<div class="absolute top-0 right-20 bg-bg text-gray-100 border-b border-l border-r border-gray-400 z-20 rounded-b-md px-2 h-9 flex items-center text-center">
<div class="absolute top-0 right-20 bg-bg text-gray-100 border-b border-l border-r border-gray-400 z-20 rounded-b-md px-2 h-9 hidden md:flex items-center text-center">
<p class="font-mono">{{ page }} / {{ numPages }}</p>
</div>
<div class="absolute top-0 right-40 bg-bg text-gray-100 border-b border-l border-r border-gray-400 z-20 rounded-b-md px-2 h-9 flex items-center text-center">
<div class="absolute top-0 right-40 bg-bg text-gray-100 border-b border-l border-r border-gray-400 z-20 rounded-b-md px-2 h-9 hidden md:flex items-center text-center">
<ui-icon-btn icon="zoom_out" :size="8" :disabled="!canScaleDown" borderless class="mr-px" @click="zoomOut" />
<ui-icon-btn icon="zoom_in" :size="8" :disabled="!canScaleUp" borderless class="ml-px" @click="zoomIn" />
</div>
+179 -19
View File
@@ -1,36 +1,48 @@
<template>
<div v-if="show" id="reader" class="absolute top-0 left-0 w-full z-60 bg-primary text-white" :class="{ 'reader-player-open': !!streamLibraryItem }">
<div class="absolute top-4 left-4 z-20">
<span v-if="hasToC && !tocOpen" ref="tocButton" class="material-icons cursor-pointer text-2xl" @click="toggleToC">menu</span>
<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 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-icons text-2xl">menu</span>
</button>
<button v-if="hasSettings" @click="openSettings" type="button" aria-label="Ereader settings" class="mx-4 inline-flex opacity-80 hover:opacity-100">
<span class="material-icons text-1.5xl">settings</span>
</button>
</div>
<div class="absolute top-4 left-1/2 transform -translate-x-1/2">
<h1 class="text-lg sm:text-xl md:text-2xl mb-1" style="line-height: 1.15; font-weight: 100">
<h1 :data-type="ebookType" class="text-lg sm:text-xl md:text-2xl mb-1 data-[type=comic]:hidden" style="line-height: 1.15; font-weight: 100">
<span style="font-weight: 600">{{ abTitle }}</span>
<span v-if="abAuthor" style="display: inline"> </span>
<span v-if="abAuthor">{{ abAuthor }}</span>
<span v-if="abAuthor" class="hidden md:inline"> </span>
<span v-if="abAuthor" class="hidden md:inline">{{ abAuthor }}</span>
</h1>
</div>
<div class="absolute top-4 right-4 z-20">
<span v-if="hasSettings" class="material-icons cursor-pointer text-2xl" @click="openSettings">settings</span>
<span class="material-icons cursor-pointer text-2xl" @click="close">close</span>
<button @click="close" type="button" aria-label="Close ereader" class="inline-flex opacity-80 hover:opacity-100">
<span class="material-icons text-2xl">close</span>
</button>
</div>
<component v-if="componentName" ref="readerComponent" :is="componentName" :library-item="selectedLibraryItem" :player-open="!!streamLibraryItem" :keep-progress="keepProgress" :file-id="ebookFileId" />
<component v-if="componentName" ref="readerComponent" :is="componentName" :library-item="selectedLibraryItem" :player-open="!!streamLibraryItem" :keep-progress="keepProgress" :file-id="ebookFileId" @touchstart="touchstart" @touchend="touchend" @hook:mounted="readerMounted" />
<!-- TOC side nav -->
<div v-if="tocOpen" class="w-full h-full fixed inset-0 bg-black/20 z-20" @click.stop.prevent="toggleToC"></div>
<div v-if="hasToC" class="w-96 h-full max-h-full absolute top-0 left-0 bg-bg shadow-xl transition-transform z-30" :class="tocOpen ? 'translate-x-0' : '-translate-x-96'" @click.stop.prevent="toggleToC">
<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="toggleToC">
<div class="p-4 h-full">
<p class="text-lg font-semibold mb-2">Table of Contents</p>
<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">
<span class="material-icons text-2xl">arrow_back</span>
</button>
<p class="text-lg font-semibold ml-2">{{ $strings.HeaderTableOfContents }}</p>
</div>
<div class="tocContent">
<ul>
<li v-for="chapter in chapters" :key="chapter.id" class="py-1">
<a :href="chapter.href" class="text-white/70 hover:text-white" @click.prevent="$refs.readerComponent.goToChapter(chapter.href)">{{ chapter.label }}</a>
<a :href="chapter.href" class="opacity-80 hover:opacity-100" @click.prevent="$refs.readerComponent.goToChapter(chapter.href)">{{ chapter.label }}</a>
<ul v-if="chapter.subitems.length">
<li v-for="subchapter in chapter.subitems" :key="subchapter.id" class="py-1 pl-4">
<a :href="subchapter.href" class="text-white/70 hover:text-white" @click.prevent="$refs.readerComponent.goToChapter(subchapter.href)">{{ subchapter.label }}</a>
<a :href="subchapter.href" class="opacity-80 hover:opacity-100" @click.prevent="$refs.readerComponent.goToChapter(subchapter.href)">{{ subchapter.label }}</a>
</li>
</ul>
</li>
@@ -38,6 +50,41 @@
</div>
</div>
</div>
<!-- ereader settings modal -->
<modals-modal v-model="showSettings" name="ereader-settings-modal" :width="500" :height="'unset'" :processing="false">
<template #outer>
<div class="absolute top-0 left-0 p-5 w-3/4 overflow-hidden">
<p class="text-xl md:text-3xl text-white truncate">{{ $strings.HeaderEreaderSettings }}</p>
</div>
</template>
<div class="px-2 py-4 md:p-8 w-full text-base rounded-lg bg-bg shadow-lg border border-black-300 relative overflow-x-hidden overflow-y-auto" style="max-height: 80vh">
<div class="flex items-center mb-4">
<div class="w-40">
<p class="text-lg">{{ $strings.LabelTheme }}:</p>
</div>
<ui-toggle-btns v-model="ereaderSettings.theme" :items="themeItems" @input="settingsUpdated" />
</div>
<div class="flex items-center mb-4">
<div class="w-40">
<p class="text-lg">{{ $strings.LabelFontScale }}:</p>
</div>
<ui-range-input v-model="ereaderSettings.fontScale" :min="5" :max="300" :step="5" @input="settingsUpdated" />
</div>
<div class="flex items-center mb-4">
<div class="w-40">
<p class="text-lg">{{ $strings.LabelLineSpacing }}:</p>
</div>
<ui-range-input v-model="ereaderSettings.lineSpacing" :min="100" :max="300" :step="5" @input="settingsUpdated" />
</div>
<div class="flex items-center">
<div class="w-40">
<p class="text-lg">{{ $strings.LabelLayout }}:</p>
</div>
<ui-toggle-btns v-model="ereaderSettings.spread" :items="spreadItems" @input="settingsUpdated" />
</div>
</div>
</modals-modal>
</div>
</template>
@@ -45,8 +92,21 @@
export default {
data() {
return {
touchstartX: 0,
touchstartY: 0,
touchendX: 0,
touchendY: 0,
touchstartTime: 0,
touchIdentifier: null,
chapters: [],
tocOpen: false
tocOpen: false,
showSettings: false,
ereaderSettings: {
theme: 'dark',
fontScale: 100,
lineSpacing: 115,
spread: 'auto'
}
}
},
watch: {
@@ -65,6 +125,34 @@ export default {
this.$store.commit('setShowEReader', val)
}
},
ereaderTheme() {
if (this.isEpub) return this.ereaderSettings.theme
return 'dark'
},
spreadItems() {
return [
{
text: this.$strings.LabelLayoutSinglePage,
value: 'none'
},
{
text: this.$strings.LabelLayoutSplitPage,
value: 'auto'
}
]
},
themeItems() {
return [
{
text: this.$strings.LabelThemeDark,
value: 'dark'
},
{
text: this.$strings.LabelThemeLight,
value: 'light'
}
]
},
componentName() {
if (this.ebookType === 'epub') return 'readers-epub-reader'
else if (this.ebookType === 'mobi') return 'readers-mobi-reader'
@@ -75,11 +163,8 @@ export default {
streamLibraryItem() {
return this.$store.state.streamLibraryItem
},
hasToC() {
return this.isEpub
},
hasSettings() {
return false
return this.isEpub
},
abTitle() {
return this.mediaMetadata.title
@@ -144,14 +229,28 @@ export default {
},
ebookFileId() {
return this.$store.state.ereaderFileId
},
isDarkTheme() {
return this.ereaderSettings.theme === 'dark'
}
},
methods: {
readerMounted() {
if (this.isEpub) {
this.loadEreaderSettings()
}
},
settingsUpdated() {
this.$refs.readerComponent?.updateSettings?.(this.ereaderSettings)
localStorage.setItem('ereaderSettings', JSON.stringify(this.ereaderSettings))
},
toggleToC() {
this.tocOpen = !this.tocOpen
this.chapters = this.$refs.readerComponent.chapters
},
openSettings() {},
openSettings() {
this.showSettings = true
},
hotkey(action) {
if (!this.$refs.readerComponent) return
@@ -169,11 +268,72 @@ export default {
prev() {
if (this.$refs.readerComponent?.prev) this.$refs.readerComponent.prev()
},
handleGesture() {
// Touch must be less than 1s. Must be > 60px drag and X distance > Y distance
const touchTimeMs = Date.now() - this.touchstartTime
if (touchTimeMs >= 1000) {
console.log('Touch too long', touchTimeMs)
return
}
const touchDistanceX = Math.abs(this.touchendX - this.touchstartX)
const touchDistanceY = Math.abs(this.touchendY - this.touchstartY)
const touchDistance = Math.sqrt(Math.pow(this.touchstartX - this.touchendX, 2) + Math.pow(this.touchstartY - this.touchendY, 2))
if (touchDistance < 60) {
return
}
if (touchDistanceX < 60 || touchDistanceY > touchDistanceX) {
return
}
if (this.touchendX < this.touchstartX) {
this.next()
}
if (this.touchendX > this.touchstartX) {
this.prev()
}
},
touchstart(e) {
// Ignore rapid touch
if (this.touchstartTime && Date.now() - this.touchstartTime < 250) {
return
}
this.touchstartX = e.touches[0].screenX
this.touchstartY = e.touches[0].screenY
this.touchstartTime = Date.now()
this.touchIdentifier = e.touches[0].identifier
},
touchend(e) {
if (this.touchIdentifier !== e.changedTouches[0].identifier) {
return
}
this.touchendX = e.changedTouches[0].screenX
this.touchendY = e.changedTouches[0].screenY
this.handleGesture()
},
registerListeners() {
this.$eventBus.$on('reader-hotkey', this.hotkey)
document.body.addEventListener('touchstart', this.touchstart)
document.body.addEventListener('touchend', this.touchend)
},
unregisterListeners() {
this.$eventBus.$off('reader-hotkey', this.hotkey)
document.body.removeEventListener('touchstart', this.touchstart)
document.body.removeEventListener('touchend', this.touchend)
},
loadEreaderSettings() {
try {
const settings = localStorage.getItem('ereaderSettings')
if (settings) {
this.ereaderSettings = JSON.parse(settings)
this.settingsUpdated()
}
} catch (error) {
console.error('Failed to load ereader settings', error)
}
},
init() {
this.registerListeners()
-1
View File
@@ -235,7 +235,6 @@ export default {
style: `transform:translate(${x}px,${y}px);background-color:${bgColor};outline:1px solid ${outlineColor};outline-offset:-1px;`
})
}
console.log('Data', this.data)
this.monthLabels = []
var lastMonth = null
+12 -6
View File
@@ -18,7 +18,7 @@
</div>
</div>
<div class="flex px-4">
<div v-if="isBookLibrary" class="flex px-4">
<svg class="h-14 w-14 md:h-18 md:w-18" viewBox="0 0 24 24">
<path fill="currentColor" d="M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,6A2,2 0 0,0 10,8A2,2 0 0,0 12,10A2,2 0 0,0 14,8A2,2 0 0,0 12,6M12,13C14.67,13 20,14.33 20,17V20H4V17C4,14.33 9.33,13 12,13M12,14.9C9.03,14.9 5.9,16.36 5.9,17V18.1H18.1V17C18.1,16.36 14.97,14.9 12,14.9Z" />
</svg>
@@ -58,26 +58,32 @@ export default {
return {}
},
computed: {
currentLibraryMediaType() {
return this.$store.getters['libraries/getCurrentLibraryMediaType']
},
isBookLibrary() {
return this.currentLibraryMediaType === 'book'
},
user() {
return this.$store.state.user.user
},
totalItems() {
return this.libraryStats ? this.libraryStats.totalItems : 0
return this.libraryStats?.totalItems || 0
},
totalAuthors() {
return this.libraryStats ? this.libraryStats.totalAuthors : 0
return this.libraryStats?.totalAuthors || 0
},
numAudioTracks() {
return this.libraryStats ? this.libraryStats.numAudioTracks : 0
return this.libraryStats?.numAudioTracks || 0
},
totalDuration() {
return this.libraryStats ? this.libraryStats.totalDuration : 0
return this.libraryStats?.totalDuration || 0
},
totalHours() {
return Math.round(this.totalDuration / (60 * 60))
},
totalSizePretty() {
var totalSize = this.libraryStats ? this.libraryStats.totalSize : 0
var totalSize = this.libraryStats?.totalSize || 0
return this.$bytesPretty(totalSize, 1)
},
totalSizeNum() {
+11 -6
View File
@@ -21,14 +21,14 @@
<td class="hidden sm:table-cell font-mono md:text-sm text-xs">{{ $bytesPretty(backup.fileSize) }}</td>
<td>
<div class="w-full flex flex-row items-center justify-center">
<ui-btn v-if="backup.serverVersion" small color="primary" @click="applyBackup(backup)">{{ $strings.ButtonRestore }}</ui-btn>
<a v-if="backup.serverVersion" :href="`/metadata/${$encodeUriPath(backup.path)}?token=${userToken}`" class="mx-1 pt-1 hover:text-opacity-100 text-opacity-70 text-white" download><span class="material-icons text-xl">download</span></a>
<ui-btn v-if="backup.serverVersion && backup.key" small color="primary" @click="applyBackup(backup)">{{ $strings.ButtonRestore }}</ui-btn>
<ui-tooltip v-else text="This backup was created with an old version of audiobookshelf no longer supported" direction="bottom" class="mx-2 flex items-center">
<span class="material-icons-outlined text-2xl text-error">error_outline</span>
</ui-tooltip>
<span class="material-icons text-xl hover:text-error hover:text-opacity-100 text-opacity-70 text-white cursor-pointer mx-1" @click="deleteBackupClick(backup)">delete</span>
<button aria-label="Download Backup" class="inline-flex material-icons text-xl mx-1 mt-1 text-white/70 hover:text-white/100" @click.stop="downloadBackup(backup)">download</button>
<button aria-label="Delete Backup" class="inline-flex material-icons text-xl mx-1 text-white/70 hover:text-error" @click="deleteBackupClick(backup)">delete</button>
</div>
</td>
</tr>
@@ -80,6 +80,9 @@ export default {
}
},
methods: {
downloadBackup(backup) {
this.$downloadFile(`${process.env.serverUrl}/api/backups/${backup.id}/download?token=${this.userToken}`)
},
confirm() {
this.showConfirmApply = false
@@ -91,8 +94,9 @@ export default {
})
.catch((error) => {
this.isBackingUp = false
console.error('Failed', error)
this.$toast.error(this.$strings.ToastBackupRestoreFailed)
console.error('Failed to apply backup', error)
const errorMsg = error.response.data || this.$strings.ToastBackupRestoreFailed
this.$toast.error(errorMsg)
})
},
deleteBackupClick(backup) {
@@ -160,6 +164,7 @@ export default {
this.$axios
.$get('/api/backups')
.then((data) => {
this.$emit('loaded', data.backupLocation)
this.setBackups(data.backups || [])
})
.catch((error) => {
+10 -10
View File
@@ -20,7 +20,7 @@
<th class="text-left px-4 w-24">
{{ $strings.LabelRead }} <ui-tooltip :text="$strings.LabelReadEbookWithoutProgress" direction="top" class="inline-block"><span class="material-icons-outlined text-sm align-middle">info</span></ui-tooltip>
</th>
<th v-if="userCanDelete || userCanDownload || userIsAdmin" class="text-center w-16"></th>
<th v-if="showMoreColumn" class="text-center w-16"></th>
</tr>
<template v-for="file in ebookFiles">
<tables-ebook-files-table-row :key="file.path" :libraryItemId="libraryItemId" :showFullPath="showFullPath" :file="file" @read="readEbook" />
@@ -58,20 +58,20 @@ export default {
userCanDelete() {
return this.$store.getters['user/getUserCanDelete']
},
userCanUpdate() {
return this.$store.getters['user/getUserCanUpdate']
},
userIsAdmin() {
return this.$store.getters['user/getIsAdminOrUp']
},
libraryIsAudiobooksOnly() {
return this.$store.getters['libraries/getLibraryIsAudiobooksOnly']
},
showMoreColumn() {
return this.userCanDelete || this.userCanDownload || (this.userCanUpdate && !this.libraryIsAudiobooksOnly)
},
ebookFiles() {
return (this.libraryItem.libraryFiles || []).filter((lf) => lf.fileType === 'ebook')
},
ebookFileIno() {
return this.libraryItem.media.ebookFile?.ino
},
audioFiles() {
if (this.libraryItem.mediaType === 'podcast') {
return this.libraryItem.media?.episodes.map((ep) => ep.audioFile) || []
}
return this.libraryItem.media?.audioFiles || []
}
},
methods: {
@@ -27,7 +27,7 @@
</div>
</transition>
<modals-audio-file-data-modal v-model="showAudioFileDataModal" :audio-file="selectedAudioFile" />
<modals-audio-file-data-modal v-model="showAudioFileDataModal" :library-item-id="libraryItemId" :audio-file="selectedAudioFile" />
</div>
</template>
+1 -1
View File
@@ -33,7 +33,7 @@
</div>
</transition>
<modals-audio-file-data-modal v-model="showAudioFileDataModal" :audio-file="selectedAudioFile" />
<modals-audio-file-data-modal v-model="showAudioFileDataModal" :library-item-id="libraryItemId" :audio-file="selectedAudioFile" />
</div>
</template>
+15 -4
View File
@@ -19,9 +19,13 @@
</td>
<td class="text-sm">{{ user.type }}</td>
<td class="hidden lg:table-cell">
<div v-if="usersOnline[user.id]">
<p v-if="usersOnline[user.id].session && usersOnline[user.id].session.libraryItem" class="truncate text-xs">Listening: {{ usersOnline[user.id].session.libraryItem.media.metadata.title || '' }}</p>
<p v-else-if="usersOnline[user.id].mostRecent && usersOnline[user.id].mostRecent.media" class="truncate text-xs">Last: {{ usersOnline[user.id].mostRecent.media.metadata.title }}</p>
<div v-if="usersOnline[user.id]?.session?.displayTitle">
<p class="truncate text-xs">Listening: {{ usersOnline[user.id].session.displayTitle || '' }}</p>
<p class="truncate text-xs text-gray-300">{{ getDeviceInfoString(usersOnline[user.id].session.deviceInfo) }}</p>
</div>
<div v-else-if="user.latestSession?.displayTitle">
<p class="truncate text-xs">Last: {{ user.latestSession.displayTitle || '' }}</p>
<p class="truncate text-xs text-gray-300">{{ getDeviceInfoString(user.latestSession.deviceInfo) }}</p>
</div>
</td>
<td class="text-xs font-mono hidden sm:table-cell">
@@ -83,6 +87,12 @@ export default {
}
},
methods: {
getDeviceInfoString(deviceInfo) {
if (!deviceInfo) return ''
if (deviceInfo.manufacturer && deviceInfo.model) return `${deviceInfo.manufacturer} ${deviceInfo.model}`
return `${deviceInfo.osName || 'Unknown'} ${deviceInfo.osVersion || ''} ${deviceInfo.browserName || ''}`
},
deleteUserClick(user) {
if (this.isDeletingUser) return
if (confirm(this.$getString('MessageRemoveUserWarning', [user.username]))) {
@@ -114,11 +124,12 @@ export default {
},
loadUsers() {
this.$axios
.$get('/api/users')
.$get('/api/users?include=latestSession')
.then((res) => {
this.users = res.users.sort((a, b) => {
return a.createdAt - b.createdAt
})
console.log('Loaded users', this.users)
})
.catch((error) => {
console.error('Failed', error)
@@ -188,7 +188,6 @@ export default {
.$patch(`/api/me/progress/${this.book.id}`, updatePayload)
.then(() => {
this.isProcessingReadUpdate = false
this.$toast.success(updatePayload.isFinished ? this.$strings.ToastItemMarkedAsFinishedSuccess : this.$strings.ToastItemMarkedAsNotFinishedSuccess)
})
.catch((error) => {
console.error('Failed', error)
@@ -11,10 +11,6 @@
<ui-btn @click="clickAddLibrary">{{ $strings.ButtonAddYourFirstLibrary }}</ui-btn>
</div>
<p v-if="libraries.length" class="text-xs mt-4 text-gray-200">
*<strong>{{ $strings.ButtonForceReScan }}</strong> {{ $strings.MessageForceReScanDescription }}
</p>
<p v-if="libraries.length && libraries.some((li) => li.mediaType === 'book')" class="text-xs mt-4 text-gray-200">
**<strong>{{ $strings.ButtonMatchBooks }}</strong> {{ $strings.MessageMatchBooksDescription }}
</p>
@@ -71,11 +71,6 @@ export default {
text: this.$strings.ButtonScan,
action: 'scan',
value: 'scan'
},
{
text: this.$strings.ButtonForceReScan,
action: 'force-scan',
value: 'force-scan'
}
]
if (this.isBookLibrary) {
@@ -137,26 +132,6 @@ export default {
this.$toast.error(this.$strings.ToastLibraryScanFailedToStart)
})
},
forceScan() {
const payload = {
message: this.$strings.MessageConfirmForceReScan,
callback: (confirmed) => {
if (confirmed) {
this.$store
.dispatch('libraries/requestLibraryScan', { libraryId: this.library.id, force: 1 })
.then(() => {
this.$toast.success(this.$strings.ToastLibraryScanStarted)
})
.catch((error) => {
console.error('Failed to start scan', error)
this.$toast.error(this.$strings.ToastLibraryScanFailedToStart)
})
}
},
type: 'yesNo'
}
this.$store.commit('globals/setConfirmPrompt', payload)
},
deleteClick() {
const payload = {
message: this.$getString('MessageConfirmDeleteLibrary', [this.library.name]),
@@ -198,7 +198,6 @@ export default {
.$patch(routepath, updatePayload)
.then(() => {
this.isProcessingReadUpdate = false
this.$toast.success(updatePayload.isFinished ? this.$strings.ToastItemMarkedAsFinishedSuccess : this.$strings.ToastItemMarkedAsNotFinishedSuccess)
})
.catch((error) => {
console.error('Failed', error)
@@ -183,7 +183,6 @@ export default {
.$patch(`/api/me/progress/${this.libraryItemId}/${this.episode.id}`, updatePayload)
.then(() => {
this.isProcessingReadUpdate = false
this.$toast.success(updatePayload.isFinished ? this.$strings.ToastItemMarkedAsFinishedSuccess : this.$strings.ToastItemMarkedAsNotFinishedSuccess)
})
.catch((error) => {
console.error('Failed', error)
@@ -1,22 +1,29 @@
<template>
<div class="w-full py-6">
<p class="text-lg mb-2 font-semibold md:hidden">{{ $strings.HeaderEpisodes }}</p>
<div class="flex items-center mb-4">
<p class="text-lg mb-0 font-semibold hidden md:block">{{ $strings.HeaderEpisodes }}</p>
<div class="flex flex-wrap flex-col md:flex-row md:items-center mb-4">
<div class="flex items-center flex-nowrap whitespace-nowrap mb-2 md:mb-0">
<p class="text-lg mb-0 font-semibold">{{ $strings.HeaderEpisodes }}</p>
<div class="inline-flex bg-white/5 px-1 mx-2 rounded-md text-sm text-gray-100">
<p v-if="episodesList.length === episodes.length">{{ episodes.length }}</p>
<p v-else>{{ episodesList.length }} / {{ episodes.length }}</p>
</div>
</div>
<div class="flex-grow hidden md:block" />
<template v-if="isSelectionMode">
<ui-tooltip :text="selectedIsFinished ? $strings.MessageMarkAsNotFinished : $strings.MessageMarkAsFinished" direction="bottom">
<ui-read-icon-btn :disabled="processing" :is-read="selectedIsFinished" @click="toggleBatchFinished" class="mx-1.5" />
</ui-tooltip>
<ui-btn color="error" :disabled="processing" small class="h-9" @click="removeSelectedEpisodes">{{ $getString('MessageRemoveEpisodes', [selectedEpisodes.length]) }}</ui-btn>
<ui-btn :disabled="processing" small class="ml-2 h-9" @click="clearSelected">{{ $strings.ButtonCancel }}</ui-btn>
</template>
<template v-else>
<controls-filter-select v-model="filterKey" :items="filterItems" class="w-36 h-9 sm:ml-4" />
<controls-sort-select v-model="sortKey" :descending.sync="sortDesc" :items="sortItems" class="w-44 md:w-48 h-9 ml-1 sm:ml-4" />
<div class="flex-grow md:hidden" />
<ui-context-menu-dropdown v-if="contextMenuItems.length" :items="contextMenuItems" class="ml-1" @action="contextMenuAction" />
</template>
<div class="flex items-center">
<template v-if="isSelectionMode">
<ui-tooltip :text="selectedIsFinished ? $strings.MessageMarkAsNotFinished : $strings.MessageMarkAsFinished" direction="bottom">
<ui-read-icon-btn :disabled="processing" :is-read="selectedIsFinished" @click="toggleBatchFinished" class="mx-1.5" />
</ui-tooltip>
<ui-btn color="error" :disabled="processing" small class="h-9" @click="removeSelectedEpisodes">{{ $getString('MessageRemoveEpisodes', [selectedEpisodes.length]) }}</ui-btn>
<ui-btn :disabled="processing" small class="ml-2 h-9" @click="clearSelected">{{ $strings.ButtonCancel }}</ui-btn>
</template>
<template v-else>
<controls-filter-select v-model="filterKey" :items="filterItems" class="w-36 h-9 md:ml-4" />
<controls-sort-select v-model="sortKey" :descending.sync="sortDesc" :items="sortItems" class="w-44 md:w-48 h-9 ml-1 sm:ml-4" />
<div class="flex-grow md:hidden" />
<ui-context-menu-dropdown v-if="contextMenuItems.length" :items="contextMenuItems" class="ml-1" @action="contextMenuAction" />
</template>
</div>
</div>
<p v-if="!episodes.length" class="py-4 text-center text-lg">{{ $strings.MessageNoEpisodes }}</p>
<div v-if="episodes.length" class="w-full py-3 mx-auto flex">
@@ -51,7 +58,6 @@ export default {
selectedEpisodes: [],
episodesToRemove: [],
processing: false,
quickMatchingEpisodes: false,
search: null,
searchTimeout: null,
searchText: null
@@ -71,6 +77,10 @@ export default {
{
text: 'Quick match all episodes',
action: 'quick-match-episodes'
},
{
text: this.allEpisodesFinished ? this.$strings.MessageMarkAllEpisodesNotFinished : this.$strings.MessageMarkAllEpisodesFinished,
action: 'batch-mark-as-finished'
}
]
},
@@ -157,14 +167,20 @@ export default {
episodesList() {
return this.episodesSorted.filter((episode) => {
if (!this.searchText) return true
return (episode.title && episode.title.toLowerCase().includes(this.searchText)) || (episode.subtitle && episode.subtitle.toLowerCase().includes(this.searchText))
return episode.title?.toLowerCase().includes(this.searchText) || episode.subtitle?.toLowerCase().includes(this.searchText)
})
},
selectedIsFinished() {
// Find an item that is not finished, if none then all items finished
return !this.selectedEpisodes.find((episode) => {
var itemProgress = this.$store.getters['user/getUserMediaProgress'](this.libraryItem.id, episode.id)
return !itemProgress || !itemProgress.isFinished
return !this.selectedEpisodes.some((episode) => {
const itemProgress = this.$store.getters['user/getUserMediaProgress'](this.libraryItem.id, episode.id)
return !itemProgress?.isFinished
})
},
allEpisodesFinished() {
return !this.episodesSorted.some((episode) => {
const itemProgress = this.$store.getters['user/getUserMediaProgress'](this.libraryItem.id, episode.id)
return !itemProgress?.isFinished
})
},
dateFormat() {
@@ -175,6 +191,7 @@ export default {
}
},
methods: {
submit() {},
inputUpdate() {
clearTimeout(this.searchTimeout)
this.searchTimeout = setTimeout(() => {
@@ -187,17 +204,34 @@ export default {
},
contextMenuAction({ action }) {
if (action === 'quick-match-episodes') {
if (this.quickMatchingEpisodes) return
if (this.processing) return
this.quickMatchAllEpisodes()
} else if (action === 'batch-mark-as-finished') {
if (this.processing) return
this.markAllEpisodesFinished()
}
},
markAllEpisodesFinished() {
const newIsFinished = !this.allEpisodesFinished
const payload = {
message: newIsFinished ? this.$strings.MessageConfirmMarkAllEpisodesFinished : this.$strings.MessageConfirmMarkAllEpisodesNotFinished,
callback: (confirmed) => {
if (confirmed) {
this.batchUpdateEpisodesFinished(this.episodesSorted, newIsFinished)
}
},
type: 'yesNo'
}
this.$store.commit('globals/setConfirmPrompt', payload)
},
quickMatchAllEpisodes() {
if (!this.mediaMetadata.feedUrl) {
this.$toast.error(this.$strings.MessagePodcastHasNoRSSFeedForMatching)
return
}
this.quickMatchingEpisodes = true
this.processing = true
const payload = {
message: 'Quick matching episodes will overwrite details if a match is found. Only unmatched episodes will be updated. Are you sure?',
@@ -217,7 +251,7 @@ export default {
this.$toast.error('Failed to match episodes')
})
}
this.quickMatchingEpisodes = false
this.processing = false
},
type: 'yesNo'
}
@@ -241,17 +275,19 @@ export default {
this.$store.commit('addItemToQueue', queueItem)
},
toggleBatchFinished() {
this.batchUpdateEpisodesFinished(this.selectedEpisodes, !this.selectedIsFinished)
},
batchUpdateEpisodesFinished(episodes, newIsFinished) {
this.processing = true
var newIsFinished = !this.selectedIsFinished
var updateProgressPayloads = this.selectedEpisodes.map((episode) => {
const updateProgressPayloads = episodes.map((episode) => {
return {
libraryItemId: this.libraryItem.id,
episodeId: episode.id,
isFinished: newIsFinished
}
})
this.$axios
return this.$axios
.patch(`/api/me/progress/batch/update`, updateProgressPayloads)
.then(() => {
this.$toast.success(this.$strings.ToastBatchUpdateSuccess)
+1 -1
View File
@@ -73,7 +73,7 @@ export default {
}
</script>
<style>
<style scoped>
.btn::before {
content: '';
position: absolute;
+10 -13
View File
@@ -46,7 +46,7 @@ export default {
type: Array,
default: () => []
},
endpoint: String,
filterKey: String,
label: String,
disabled: Boolean,
readonly: Boolean,
@@ -60,7 +60,6 @@ export default {
return {
textInput: null,
currentSearch: null,
searching: false,
typingTimeout: null,
isFocused: false,
menu: null,
@@ -97,6 +96,9 @@ export default {
},
itemsToShow() {
return this.items
},
filterData() {
return this.$store.state.libraries.filterData || {}
}
},
methods: {
@@ -109,20 +111,15 @@ export default {
getIsSelected(itemValue) {
return !!this.selected.find((i) => i.id === itemValue)
},
async search() {
if (this.searching) return
search() {
this.currentSearch = this.textInput
this.searching = true
const results = await this.$axios
.$get(`/api/${this.endpoint}?q=${this.currentSearch}&limit=15&token=${this.userToken}`)
.then((res) => res.results || res)
.catch((error) => {
console.error('Failed to get search results', error)
return []
})
const dataToSearch = this.filterData[this.filterKey] || []
const results = dataToSearch.filter((au) => {
return au.name.toLowerCase().includes(this.currentSearch.toLowerCase().trim())
})
this.items = results || []
this.searching = false
},
keydownInput() {
clearTimeout(this.typingTimeout)
+86
View File
@@ -0,0 +1,86 @@
<template>
<div class="inline-flex">
<input v-model="input" type="range" :min="min" :max="max" :step="step" />
<p class="text-sm ml-2">{{ input }}%</p>
</div>
</template>
<script>
export default {
props: {
value: [String, Number],
min: Number,
max: Number,
step: Number
},
data() {
return {}
},
computed: {
input: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
}
},
methods: {},
mounted() {}
}
</script>
<style scoped>
input[type='range'] {
-webkit-appearance: none;
appearance: none;
background: transparent;
cursor: pointer;
}
input[type='range']:focus {
outline: none;
}
/* chromium */
input[type='range']::-webkit-slider-runnable-track {
background-color: rgb(0 0 0 / 0.25);
border-radius: 9999px;
height: 0.75rem;
}
input[type='range']::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
margin-top: -0.25rem;
border-radius: 9999px;
background-color: rgb(255 255 255 / 0.7);
height: 1.25rem;
width: 1.25rem;
}
input[type='range']:focus::-webkit-slider-thumb {
border: 1px solid #6b6b6b;
outline: 3px solid #6b6b6b;
outline-offset: 0.125rem;
}
/* firefox */
input[type='range']::-moz-range-track {
background-color: rgb(0 0 0 / 0.25);
border-radius: 9999px;
height: 0.75rem;
}
input[type='range']::-moz-range-thumb {
border: none;
border-radius: 9999px;
margin-top: -0.25rem;
background-color: rgb(255 255 255 / 0.7);
height: 1.25rem;
width: 1.25rem;
}
input[type='range']:focus::-moz-range-thumb {
border: 1px solid #6b6b6b;
outline: 3px solid #6b6b6b;
outline-offset: 0.125rem;
}
</style>
+2 -1
View File
@@ -1,7 +1,7 @@
<template>
<div class="w-full">
<p class="px-1 text-sm font-semibold" :class="disabled ? 'text-gray-400' : ''">{{ label }}</p>
<ui-textarea-input ref="input" v-model="inputValue" :disabled="disabled" :rows="rows" class="w-full" />
<ui-textarea-input ref="input" v-model="inputValue" :disabled="disabled" :readonly="readonly" :rows="rows" class="w-full" />
</div>
</template>
@@ -11,6 +11,7 @@ export default {
value: [String, Number],
label: String,
disabled: Boolean,
readonly: Boolean,
rows: {
type: Number,
default: 2
+85
View File
@@ -0,0 +1,85 @@
<template>
<div class="inline-flex toggle-btn-wrapper shadow-md">
<button v-for="item in items" :key="item.value" type="button" class="toggle-btn outline-none relative border border-gray-600 px-4 py-1" :class="{ selected: item.value === value }" @click.stop="clickBtn(item.value)">
{{ item.text }}
</button>
</div>
</template>
<script>
export default {
props: {
value: String,
/**
* [{ "text", "", "value": "" }]
*/
items: {
type: Array,
default: Object
}
},
data() {
return {}
},
computed: {},
methods: {
clickBtn(value) {
this.$emit('input', value)
}
},
mounted() {}
}
</script>
<style scoped>
.toggle-btn-wrapper .toggle-btn:first-child {
border-top-left-radius: 0.375rem /* 6px */;
border-bottom-left-radius: 0.375rem /* 6px */;
}
.toggle-btn-wrapper .toggle-btn:last-child {
border-top-right-radius: 0.375rem /* 6px */;
border-bottom-right-radius: 0.375rem /* 6px */;
}
.toggle-btn-wrapper .toggle-btn:first-child::before {
border-top-left-radius: 0.375rem /* 6px */;
border-bottom-left-radius: 0.375rem /* 6px */;
}
.toggle-btn-wrapper .toggle-btn:last-child::before {
border-top-right-radius: 0.375rem /* 6px */;
border-bottom-right-radius: 0.375rem /* 6px */;
}
.toggle-btn-wrapper .toggle-btn:not(:first-child) {
margin-left: -1px;
}
.toggle-btn::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0);
transition: all 0.1s ease-in-out;
}
.toggle-btn:hover:not(:disabled)::before {
background-color: rgba(255, 255, 255, 0.1);
}
.toggle-btn:hover:not(:disabled) {
color: white;
}
.toggle-btn {
color: rgba(255, 255, 255, 0.75);
}
.toggle-btn.selected {
color: white;
}
.toggle-btn.selected::before {
background-color: rgba(255, 255, 255, 0.1);
}
button.toggle-btn:disabled::before {
background-color: rgba(0, 0, 0, 0.2);
}
</style>
@@ -12,8 +12,8 @@
<div class="flex flex-wrap mt-2 -mx-1">
<div class="w-full md:w-3/4 px-1">
<!-- Authors filter only contains authors in this library, use query input to query all authors -->
<ui-multi-select-query-input ref="authorsSelect" v-model="details.authors" :label="$strings.LabelAuthors" endpoint="authors/search" />
<!-- Authors filter only contains authors in this library, uses filter data -->
<ui-multi-select-query-input ref="authorsSelect" v-model="details.authors" :label="$strings.LabelAuthors" filter-key="authors" />
</div>
<div class="flex-grow px-1 mt-2 md:mt-0">
<ui-text-input-with-label ref="publishYearInput" v-model="details.publishedYear" type="number" :label="$strings.LabelPublishYear" />
+15 -4
View File
@@ -231,8 +231,12 @@ export default {
scanComplete(data) {
console.log('Scan complete received', data)
var message = `${data.type === 'match' ? 'Match' : 'Scan'} "${data.name}" complete!`
if (data.results) {
let message = `${data.type === 'match' ? 'Match' : 'Scan'} "${data.name}" complete!`
let toastType = 'success'
if (data.error) {
message = `${data.type === 'match' ? 'Match' : 'Scan'} "${data.name}" finished with error:\n${data.error}`
toastType = 'error'
} else if (data.results) {
var scanResultMsgs = []
var results = data.results
if (results.added) scanResultMsgs.push(`${results.added} added`)
@@ -247,9 +251,9 @@ export default {
var existingScan = this.$store.getters['scanners/getLibraryScan'](data.id)
if (existingScan && !isNaN(existingScan.toastId)) {
this.$toast.update(existingScan.toastId, { content: message, options: { timeout: 5000, type: 'success', closeButton: false, onClose: () => null } }, true)
this.$toast.update(existingScan.toastId, { content: message, options: { timeout: 5000, type: toastType, closeButton: false, onClose: () => null } }, true)
} else {
this.$toast.success(message, { timeout: 5000 })
this.$toast[toastType](message, { timeout: 5000 })
}
this.$store.commit('scanners/remove', data)
@@ -343,6 +347,10 @@ export default {
}
this.$store.commit('libraries/removeCollection', collection)
},
seriesRemoved({ id, libraryId }) {
if (this.currentLibraryId !== libraryId) return
this.$store.commit('libraries/removeSeriesFromFilterData', id)
},
playlistAdded(playlist) {
if (playlist.userId !== this.user.id || this.currentLibraryId !== playlist.libraryId) return
this.$store.commit('libraries/addUpdateUserPlaylist', playlist)
@@ -442,6 +450,9 @@ export default {
this.socket.on('collection_updated', this.collectionUpdated)
this.socket.on('collection_removed', this.collectionRemoved)
// Series Listeners
this.socket.on('series_removed', this.seriesRemoved)
// User Playlist Listeners
this.socket.on('playlist_added', this.playlistAdded)
this.socket.on('playlist_updated', this.playlistUpdated)
+2 -2
View File
@@ -71,8 +71,8 @@ module.exports = {
],
proxy: {
'/s/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' : '/' },
'/api/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' : '/' }
'/api/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' : '/' },
'/dev/': { target: 'http://localhost:3333', pathRewrite: { '^/dev/': '' } }
},
io: {
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "audiobookshelf-client",
"version": "2.2.23",
"version": "2.4.4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "audiobookshelf-client",
"version": "2.2.23",
"version": "2.4.4",
"license": "ISC",
"dependencies": {
"@nuxtjs/axios": "^5.13.6",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "audiobookshelf-client",
"version": "2.2.23",
"version": "2.4.4",
"description": "Self-hosted audiobook and podcast client",
"main": "index.js",
"scripts": {
+3 -3
View File
@@ -112,17 +112,17 @@
<div class="flex text-xs uppercase text-gray-300 font-semibold mb-2">
<div class="flex-grow">{{ $strings.LabelFilename }}</div>
<div class="w-20">{{ $strings.LabelDuration }}</div>
<div class="w-20 text-center">{{ $strings.HeaderChapters }}</div>
<div class="w-20 hidden md:block text-center">{{ $strings.HeaderChapters }}</div>
</div>
<template v-for="track in audioTracks">
<div :key="track.ino" class="flex items-center py-2" :class="currentTrackIndex === track.index && isPlayingChapter ? 'bg-success bg-opacity-10' : ''">
<div class="flex-grow">
<div class="flex-grow max-w-[calc(100%-80px)] pr-2">
<p class="text-xs truncate max-w-sm">{{ track.metadata.filename }}</p>
</div>
<div class="w-20" style="min-width: 80px">
<p class="text-xs font-mono text-gray-200">{{ $secondsToTimestamp(Math.round(track.duration), false, true) }}</p>
</div>
<div class="w-20 flex justify-center" style="min-width: 80px">
<div class="w-20 hidden md:flex justify-center" style="min-width: 80px">
<span v-if="(track.chapters || []).length" class="material-icons text-success text-sm">check</span>
</div>
</div>
+2 -2
View File
@@ -94,7 +94,7 @@
<transition name="slide">
<div v-if="showEncodeOptions" class="mb-4 pb-4 border-b border-white/10">
<div class="flex flex-wrap -mx-2">
<ui-text-input-with-label ref="bitrateInput" v-model="encodingOptions.bitrate" :disabled="processing || isTaskFinished" :label="'Audio Bitrate (e.g. 64k)'" class="m-2 max-w-40" />
<ui-text-input-with-label ref="bitrateInput" v-model="encodingOptions.bitrate" :disabled="processing || isTaskFinished" :label="'Audio Bitrate (e.g. 128k)'" class="m-2 max-w-40" />
<ui-text-input-with-label ref="channelsInput" v-model="encodingOptions.channels" :disabled="processing || isTaskFinished" :label="'Audio Channels (1 or 2)'" class="m-2 max-w-40" />
<ui-text-input-with-label ref="codecInput" v-model="encodingOptions.codec" :disabled="processing || isTaskFinished" :label="'Audio Codec'" class="m-2 max-w-40" />
</div>
@@ -214,7 +214,7 @@ export default {
showEncodeOptions: false,
shouldBackupAudioFiles: true,
encodingOptions: {
bitrate: '64k',
bitrate: '128k',
channels: '2',
codec: 'aac'
}
+2 -2
View File
@@ -26,8 +26,8 @@
</div>
<div v-if="!isPodcastLibrary" class="flex items-center px-4 w-1/2">
<ui-checkbox v-model="selectedBatchUsage.authors" />
<!-- Authors filter only contains authors in this library, use query input to query all authors -->
<ui-multi-select-query-input ref="authorsSelect" v-model="batchDetails.authors" :disabled="!selectedBatchUsage.authors" :label="$strings.LabelAuthors" endpoint="authors/search" class="mb-4 ml-4" />
<!-- Authors filter only contains authors in this library, uses filter data -->
<ui-multi-select-query-input ref="authorsSelect" v-model="batchDetails.authors" :disabled="!selectedBatchUsage.authors" :label="$strings.LabelAuthors" filter-key="authors" class="mb-4 ml-4" />
</div>
<div v-if="!isPodcastLibrary && !isMapAppend" class="flex items-center px-4 w-1/2">
<ui-checkbox v-model="selectedBatchUsage.publishedYear" />
+1
View File
@@ -55,6 +55,7 @@ export default {
else if (pageName === 'library-stats') return this.$strings.HeaderLibraryStats
else if (pageName === 'users') return this.$strings.HeaderUsers
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
}
return this.$strings.HeaderSettings
+33 -14
View File
@@ -1,6 +1,12 @@
<template>
<div>
<app-settings-content :header-text="$strings.HeaderBackups" :description="$strings.MessageBackupsDescription">
<div v-if="backupLocation" class="flex items-center mb-4">
<span class="material-icons-outlined text-2xl text-black-50 mr-2">folder</span>
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelBackupLocation }}:</span>
<div class="text-gray-100 pl-4">{{ backupLocation }}</div>
</div>
<div class="flex items-center py-2">
<ui-toggle-switch v-model="enableBackups" small :disabled="updatingServerSettings" @input="updateBackupsSettings" />
<ui-tooltip :text="$strings.LabelBackupsEnableAutomaticBackupsHelp">
@@ -11,14 +17,18 @@
<div v-if="enableBackups" class="mb-6">
<div class="flex items-center pl-6 mb-2">
<span class="material-icons-outlined text-2xl text-black-50 mr-2">schedule</span>
<div class="w-48"><span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.HeaderSchedule }}:</span></div>
<div class="w-40">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.HeaderSchedule }}:</span>
</div>
<div class="text-gray-100">{{ scheduleDescription }}</div>
<span class="material-icons text-lg text-black-50 hover:text-yellow-500 cursor-pointer ml-2" @click="showCronBuilder = !showCronBuilder">edit</span>
</div>
<div v-if="nextBackupDate" class="flex items-center pl-6 py-0.5 px-2">
<span class="material-icons-outlined text-2xl text-black-50 mr-2">event</span>
<div class="w-48"><span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelNextBackupDate }}:</span></div>
<div class="w-40">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelNextBackupDate }}:</span>
</div>
<div class="text-gray-100">{{ nextBackupDate }}</div>
</div>
</div>
@@ -39,7 +49,7 @@
</ui-tooltip>
</div>
<tables-backups-table />
<tables-backups-table @loaded="backupsLoaded" />
<modals-backup-schedule-modal v-model="showCronBuilder" :cron-expression.sync="cronExpression" />
</app-settings-content>
@@ -48,6 +58,11 @@
<script>
export default {
asyncData({ store, redirect }) {
if (!store.getters['user/getIsAdminOrUp']) {
redirect('/')
}
},
data() {
return {
updatingServerSettings: false,
@@ -56,7 +71,8 @@ export default {
maxBackupSize: 1,
cronExpression: '',
newServerSettings: {},
showCronBuilder: false
showCronBuilder: false,
backupLocation: ''
}
},
watch: {
@@ -89,6 +105,9 @@ export default {
}
},
methods: {
backupsLoaded(backupLocation) {
this.backupLocation = backupLocation
},
updateBackupsSettings() {
if (isNaN(this.maxBackupSize) || this.maxBackupSize <= 0) {
this.$toast.error('Invalid maximum backup size')
@@ -98,7 +117,7 @@ export default {
this.$toast.error('Invalid number of backups to keep')
return
}
var updatePayload = {
const updatePayload = {
backupSchedule: this.enableBackups ? this.cronExpression : false,
backupsToKeep: Number(this.backupsToKeep),
maxBackupSize: Number(this.maxBackupSize)
@@ -108,15 +127,15 @@ export default {
updateServerSettings(payload) {
this.updatingServerSettings = true
this.$store
.dispatch('updateServerSettings', payload)
.then((success) => {
console.log('Updated Server Settings', success)
this.updatingServerSettings = false
})
.catch((error) => {
console.error('Failed to update server settings', error)
this.updatingServerSettings = false
})
.dispatch('updateServerSettings', payload)
.then((success) => {
console.log('Updated Server Settings', success)
this.updatingServerSettings = false
})
.catch((error) => {
console.error('Failed to update server settings', error)
this.updatingServerSettings = false
})
},
initServerSettings() {
this.newServerSettings = this.serverSettings ? { ...this.serverSettings } : {}
+19 -3
View File
@@ -34,10 +34,14 @@
<div class="w-full md:w-1/2 px-1">
<ui-text-input-with-label ref="fromInput" v-model="newSettings.fromAddress" :disabled="savingSettings" :label="$strings.LabelEmailSettingsFromAddress" />
</div>
<div class="w-full md:w-1/2 px-1">
<ui-text-input-with-label ref="testInput" v-model="newSettings.testAddress" :disabled="savingSettings" :label="$strings.LabelEmailSettingsTestAddress" />
</div>
</div>
<div class="flex items-center justify-between pt-4">
<ui-btn :loading="sendingTest" :disabled="savingSettings || !newSettings.host" type="button" @click="sendTestClick">{{ $strings.ButtonTest }}</ui-btn>
<ui-btn v-if="hasUpdates" :disabled="savingSettings" type="button" @click="resetChanges">{{ $strings.ButtonReset }}</ui-btn>
<ui-btn v-else :loading="sendingTest" :disabled="savingSettings || !newSettings.host" type="button" @click="sendTestClick">{{ $strings.ButtonTest }}</ui-btn>
<ui-btn :loading="savingSettings" :disabled="!hasUpdates" type="submit">{{ $strings.ButtonSave }}</ui-btn>
</div>
</form>
@@ -47,7 +51,7 @@
</div>
</app-settings-content>
<app-settings-content :header-text="$strings.HeaderEReaderDevices" showAddButton :description="''" @clicked="addNewDeviceClick">
<app-settings-content :header-text="$strings.HeaderEreaderDevices" showAddButton :description="''" @clicked="addNewDeviceClick">
<table v-if="existingEReaderDevices.length" class="tracksTable my-4">
<tr>
<th class="text-left">{{ $strings.LabelName }}</th>
@@ -80,6 +84,11 @@
<script>
export default {
asyncData({ store, redirect }) {
if (!store.getters['user/getIsAdminOrUp']) {
redirect('/')
}
},
data() {
return {
loading: false,
@@ -93,6 +102,7 @@ export default {
secure: true,
user: null,
pass: null,
testAddress: null,
fromAddress: null
},
newEReaderDevice: {
@@ -117,6 +127,11 @@ export default {
}
},
methods: {
resetChanges() {
this.newSettings = {
...this.settings
}
},
editDeviceClick(device) {
this.selectedEReaderDevice = device
this.showEReaderDeviceModal = true
@@ -139,7 +154,7 @@ export default {
}
this.deletingDeviceName = device.name
this.$axios
.$patch(`/emails/ereader-devices`, payload)
.$post(`/api/emails/ereader-devices`, payload)
.then((data) => {
this.ereaderDevicesUpdated(data.ereaderDevices)
this.$toast.success('Device deleted')
@@ -196,6 +211,7 @@ export default {
secure: this.newSettings.secure,
user: this.newSettings.user,
pass: this.newSettings.pass,
testAddress: this.newSettings.testAddress,
fromAddress: this.newSettings.fromAddress
}
this.savingSettings = true
+46 -28
View File
@@ -36,7 +36,10 @@
</ui-tooltip>
</div>
<div v-if="newServerSettings.sortingIgnorePrefix" class="w-72 ml-14 mb-2">
<ui-multi-select v-model="newServerSettings.sortingPrefixes" small :items="newServerSettings.sortingPrefixes" :label="$strings.LabelPrefixesToIgnore" @input="updateSortingPrefixes" :disabled="updatingServerSettings" />
<ui-multi-select v-model="newServerSettings.sortingPrefixes" small :items="newServerSettings.sortingPrefixes" :label="$strings.LabelPrefixesToIgnore" @input="sortingPrefixesUpdated" :disabled="savingPrefixes" />
<div class="flex justify-end py-1">
<ui-btn v-if="hasPrefixesChanged" color="success" :loading="savingPrefixes" small @click="updateSortingPrefixes">Save</ui-btn>
</div>
</div>
<div class="flex items-center py-2 mb-2">
@@ -157,10 +160,10 @@
</div>
<div class="flex items-center py-2">
<ui-toggle-switch labeledBy="settings-disable-watcher" v-model="newServerSettings.scannerDisableWatcher" :disabled="updatingServerSettings" @input="(val) => updateSettingsKey('scannerDisableWatcher', val)" />
<ui-tooltip :text="$strings.LabelSettingsDisableWatcherHelp">
<ui-toggle-switch labeledBy="settings-disable-watcher" v-model="scannerEnableWatcher" :disabled="updatingServerSettings" @input="(val) => updateSettingsKey('scannerDisableWatcher', !val)" />
<ui-tooltip :text="$strings.LabelSettingsEnableWatcherHelp">
<p class="pl-4">
<span id="settings-disable-watcher">{{ $strings.LabelSettingsDisableWatcher }}</span>
<span id="settings-disable-watcher">{{ $strings.LabelSettingsEnableWatcher }}</span>
<span class="material-icons icon-text">info_outlined</span>
</p>
</ui-tooltip>
@@ -192,7 +195,6 @@
<div class="flex-grow" />
<ui-btn color="bg" small :padding-x="4" class="mr-2 text-xs md:text-sm" :loading="isPurgingCache" @click.stop="purgeCache">{{ $strings.ButtonPurgeAllCache }}</ui-btn>
<ui-btn color="bg" small :padding-x="4" class="mr-2 text-xs md:text-sm" :loading="isPurgingCache" @click.stop="purgeItemsCache">{{ $strings.ButtonPurgeItemsCache }}</ui-btn>
<ui-btn color="bg" small :padding-x="4" class="mr-2 text-xs md:text-sm" :loading="isResettingLibraryItems" @click="resetLibraryItems">{{ $strings.ButtonRemoveAllLibraryItems }}</ui-btn>
</div>
<div class="flex items-center py-4">
@@ -249,15 +251,23 @@
<script>
export default {
asyncData({ store, redirect }) {
if (!store.getters['user/getIsAdminOrUp']) {
redirect('/')
}
},
data() {
return {
isResettingLibraryItems: false,
updatingServerSettings: false,
homepageUseBookshelfView: false,
useBookshelfView: false,
scannerEnableWatcher: false,
isPurgingCache: false,
hasPrefixesChanged: false,
newServerSettings: {},
showConfirmPurgeCache: false,
savingPrefixes: false,
metadataFileFormats: [
{
text: '.json',
@@ -300,15 +310,36 @@ export default {
}
},
methods: {
updateSortingPrefixes(val) {
if (!val || !val.length) {
sortingPrefixesUpdated(val) {
const prefixes = [...new Set(val?.map((prefix) => prefix.trim().toLowerCase()) || [])]
this.newServerSettings.sortingPrefixes = prefixes
const serverPrefixes = this.serverSettings.sortingPrefixes || []
this.hasPrefixesChanged = prefixes.some((p) => !serverPrefixes.includes(p)) || serverPrefixes.some((p) => !prefixes.includes(p))
},
updateSortingPrefixes() {
const prefixes = [...new Set(this.newServerSettings.sortingPrefixes.map((prefix) => prefix.trim().toLowerCase()) || [])]
if (!prefixes.length) {
this.$toast.error('Must have at least 1 prefix')
return
}
var prefixes = val.map((prefix) => prefix.trim().toLowerCase())
this.updateServerSettings({
sortingPrefixes: prefixes
})
this.savingPrefixes = true
this.$axios
.$patch(`/api/sorting-prefixes`, { sortingPrefixes: prefixes })
.then((data) => {
this.$toast.success(`Sorting prefixes updated. ${data.rowsUpdated} rows`)
if (data.serverSettings) {
this.$store.commit('setServerSettings', data.serverSettings)
}
this.hasPrefixesChanged = false
})
.catch((error) => {
console.error('Failed to update prefixes', error)
this.$toast.error('Failed to update sorting prefixes')
})
.finally(() => {
this.savingPrefixes = false
})
},
updateScannerCoverProvider(val) {
this.updateServerSettings({
@@ -333,6 +364,9 @@ export default {
this.updateSettingsKey('metadataFileFormat', val)
},
updateSettingsKey(key, val) {
if (key === 'scannerDisableWatcher') {
this.newServerSettings.scannerDisableWatcher = val
}
this.updateServerSettings({
[key]: val
})
@@ -359,27 +393,11 @@ export default {
initServerSettings() {
this.newServerSettings = this.serverSettings ? { ...this.serverSettings } : {}
this.newServerSettings.sortingPrefixes = [...(this.newServerSettings.sortingPrefixes || [])]
this.scannerEnableWatcher = !this.newServerSettings.scannerDisableWatcher
this.homepageUseBookshelfView = this.newServerSettings.homeBookshelfView != this.$constants.BookshelfView.DETAIL
this.useBookshelfView = this.newServerSettings.bookshelfView != this.$constants.BookshelfView.DETAIL
},
resetLibraryItems() {
if (confirm(this.$strings.MessageRemoveAllItemsWarning)) {
this.isResettingLibraryItems = true
this.$axios
.$delete('/api/items/all')
.then(() => {
this.isResettingLibraryItems = false
this.$toast.success('Successfully reset items')
location.reload()
})
.catch((error) => {
console.error('failed to reset items', error)
this.isResettingLibraryItems = false
this.$toast.error('Failed to reset items - manually remove the /config/libraryItems folder')
})
}
},
purgeCache() {
this.showConfirmPurgeCache = true
},
@@ -38,6 +38,11 @@
<script>
export default {
asyncData({ store, redirect }) {
if (!store.getters['user/getIsAdminOrUp']) {
redirect('/')
}
},
data() {
return {
loading: false,
@@ -19,6 +19,11 @@
<script>
export default {
asyncData({ store, redirect }) {
if (!store.getters['user/getIsAdminOrUp']) {
redirect('/')
}
},
data() {
return {}
},
@@ -38,6 +38,11 @@
<script>
export default {
asyncData({ store, redirect }) {
if (!store.getters['user/getIsAdminOrUp']) {
redirect('/')
}
},
data() {
return {
loading: false,
+5
View File
@@ -9,6 +9,11 @@
<script>
export default {
asyncData({ store, redirect }) {
if (!store.getters['user/getIsAdminOrUp']) {
redirect('/')
}
},
data() {
return {
showLibraryModal: false,
+19 -8
View File
@@ -22,7 +22,7 @@
</div>
</template>
</div>
<div class="w-80 my-6 mx-auto">
<div v-if="isBookLibrary" class="w-80 my-6 mx-auto">
<h1 class="text-2xl mb-4">{{ $strings.HeaderStatsTop10Authors }}</h1>
<p v-if="!top10Authors.length">{{ $strings.MessageNoAuthors }}</p>
<template v-for="(author, index) in top10Authors">
@@ -87,6 +87,11 @@
<script>
export default {
asyncData({ redirect, store }) {
if (!store.getters['user/getIsAdminOrUp']) {
redirect('/')
return
}
if (!store.state.libraries.currentLibraryId) {
return redirect('/config')
}
@@ -109,43 +114,49 @@ export default {
return this.$store.state.user.user
},
totalItems() {
return this.libraryStats ? this.libraryStats.totalItems : 0
return this.libraryStats?.totalItems || 0
},
genresWithCount() {
return this.libraryStats ? this.libraryStats.genresWithCount : []
return this.libraryStats?.genresWithCount || []
},
top5Genres() {
return this.genresWithCount.slice(0, 5)
return this.genresWithCount?.slice(0, 5) || []
},
top10LongestItems() {
return this.libraryStats ? this.libraryStats.longestItems || [] : []
return this.libraryStats?.longestItems || []
},
longestItemDuration() {
if (!this.top10LongestItems.length) return 0
return this.top10LongestItems[0].duration
},
top10LargestItems() {
return this.libraryStats ? this.libraryStats.largestItems || [] : []
return this.libraryStats?.largestItems || []
},
largestItemSize() {
if (!this.top10LargestItems.length) return 0
return this.top10LargestItems[0].size
},
authorsWithCount() {
return this.libraryStats ? this.libraryStats.authorsWithCount : []
return this.libraryStats?.authorsWithCount || []
},
mostUsedAuthorCount() {
if (!this.authorsWithCount.length) return 0
return this.authorsWithCount[0].count
},
top10Authors() {
return this.authorsWithCount.slice(0, 10)
return this.authorsWithCount?.slice(0, 10) || []
},
currentLibraryId() {
return this.$store.state.libraries.currentLibraryId
},
currentLibraryName() {
return this.$store.getters['libraries/getCurrentLibraryName']
},
currentLibraryMediaType() {
return this.$store.getters['libraries/getCurrentLibraryMediaType']
},
isBookLibrary() {
return this.currentLibraryMediaType === 'book'
}
},
methods: {
+5
View File
@@ -28,6 +28,11 @@
<script>
export default {
asyncData({ store, redirect }) {
if (!store.getters['user/getIsAdminOrUp']) {
redirect('/')
}
},
data() {
return {
search: null,
+5
View File
@@ -46,6 +46,11 @@
<script>
export default {
asyncData({ store, redirect }) {
if (!store.getters['user/getIsAdminOrUp']) {
redirect('/')
}
},
data() {
return {
loading: false,
+176
View File
@@ -0,0 +1,176 @@
<template>
<div>
<app-settings-content :header-text="$strings.HeaderRSSFeeds">
<div v-if="feeds.length" class="block max-w-full">
<table class="rssFeedsTable text-xs">
<tr class="bg-primary bg-opacity-40 h-12">
<th class="w-16 min-w-16"></th>
<th class="w-48 max-w-64 min-w-24 text-left truncate">{{ $strings.LabelTitle }}</th>
<th class="w-48 min-w-24 text-left hidden xl:table-cell">{{ $strings.LabelSlug }}</th>
<th class="w-24 min-w-16 text-left hidden md:table-cell">{{ $strings.LabelType }}</th>
<th class="w-16 min-w-16 text-center">{{ $strings.HeaderEpisodes }}</th>
<th class="w-16 min-w-16 text-center hidden lg:table-cell">{{ $strings.LabelRSSFeedPreventIndexing }}</th>
<th class="w-48 min-w-24 flex-grow hidden md:table-cell">{{ $strings.LabelLastUpdate }}</th>
<th class="w-16 text-left"></th>
</tr>
<tr v-for="feed in feeds" :key="feed.id" class="cursor-pointer h-12" @click="showFeed(feed)">
<!-- -->
<td>
<img :src="coverUrl(feed)" class="h-full w-full" />
</td>
<!-- -->
<td class="w-48 max-w-64 min-w-24 text-left truncate">
<p class="truncate">{{ feed.meta.title }}</p>
</td>
<!-- -->
<td class="hidden xl:table-cell">
<p class="truncate">{{ feed.slug }}</p>
</td>
<!-- -->
<td class="hidden md:table-cell">
<p class="">{{ getEntityType(feed.entityType) }}</p>
</td>
<!-- -->
<td class="text-center">
<p class="">{{ feed.episodes.length }}</p>
</td>
<!-- -->
<td class="text-center leading-none hidden lg:table-cell">
<p v-if="feed.meta.preventIndexing" class="">
<span class="material-icons text-2xl">check</span>
</p>
</td>
<!-- -->
<td class="text-center hidden md:table-cell">
<ui-tooltip v-if="feed.updatedAt" direction="top" :text="$formatDatetime(feed.updatedAt, dateFormat, timeFormat)">
<p class="text-gray-200">{{ $dateDistanceFromNow(feed.updatedAt) }}</p>
</ui-tooltip>
</td>
<!-- -->
<td class="text-center">
<ui-icon-btn icon="delete" class="mx-0.5" :size="7" bg-color="error" outlined @click.stop="deleteFeedClick(feed)" />
</td>
</tr>
</table>
</div>
</app-settings-content>
<modals-rssfeed-view-feed-modal v-model="showFeedModal" :feed="selectedFeed" />
</div>
</template>
<script>
export default {
data() {
return {
showFeedModal: false,
selectedFeed: null,
feeds: []
}
},
computed: {
dateFormat() {
return this.$store.state.serverSettings.dateFormat
},
timeFormat() {
return this.$store.state.serverSettings.timeFormat
}
},
methods: {
showFeed(feed) {
this.selectedFeed = feed
this.showFeedModal = true
},
deleteFeedClick(feed) {
const payload = {
message: this.$strings.MessageConfirmCloseFeed,
callback: (confirmed) => {
if (confirmed) {
this.deleteFeed(feed)
}
},
type: 'yesNo'
}
this.$store.commit('globals/setConfirmPrompt', payload)
},
deleteFeed(feed) {
this.processing = true
this.$axios
.$post(`/api/feeds/${feed.id}/close`)
.then(() => {
this.$toast.success(this.$strings.ToastRSSFeedCloseSuccess)
this.show = false
this.loadFeeds()
})
.catch((error) => {
console.error('Failed to close RSS feed', error)
this.$toast.error(this.$strings.ToastRSSFeedCloseFailed)
})
.finally(() => {
this.processing = false
})
},
getEntityType(entityType) {
if (entityType === 'libraryItem') return this.$strings.LabelItem
else if (entityType === 'series') return this.$strings.LabelSeries
else if (entityType === 'collection') return this.$strings.LabelCollection
return this.$strings.LabelUnknown
},
coverUrl(feed) {
if (!feed.coverPath) return `${this.$config.routerBasePath}/Logo.png`
return `${feed.feedUrl}/cover`
},
async loadFeeds() {
const data = await this.$axios.$get(`/api/feeds`).catch((err) => {
console.error('Failed to load RSS feeds', err)
return null
})
if (!data) {
this.$toast.error('Failed to load RSS feeds')
return
}
this.feeds = data.feeds
},
init() {
this.loadFeeds()
}
},
mounted() {
this.init()
}
}
</script>
<style scoped>
.rssFeedsTable {
border-collapse: collapse;
width: 100%;
max-width: 100%;
border: 1px solid #474747;
}
.rssFeedsTable tr:first-child {
background-color: #272727;
}
.rssFeedsTable tr:not(:first-child) {
background-color: #373838;
}
.rssFeedsTable tr:not(:first-child):nth-child(odd) {
background-color: #2f2f2f;
}
.rssFeedsTable tr:hover:not(:first-child) {
background-color: #474747;
}
.rssFeedsTable td {
padding: 4px 8px;
}
.rssFeedsTable th {
padding: 4px 8px;
font-size: 0.75rem;
}
</style>
+13 -7
View File
@@ -53,8 +53,10 @@
</div>
<p v-else class="text-white text-opacity-50">{{ $strings.MessageNoListeningSessions }}</p>
<div class="w-full my-8 h-px bg-white/10" />
<!-- open listening sessions table -->
<p v-if="openListeningSessions.length" class="text-lg mb-4 mt-8">Open Listening Sessions</p>
<p v-if="openListeningSessions.length" class="text-lg my-4">Open Listening Sessions</p>
<div v-if="openListeningSessions.length" class="block max-w-full">
<table class="userSessionsTable">
<tr class="bg-primary bg-opacity-40">
@@ -73,8 +75,7 @@
<p class="text-xs text-gray-400 truncate">{{ session.displayAuthor }}</p>
</td>
<td class="hidden md:table-cell">
<p v-if="filteredUserUsername" class="text-xs">{{ filteredUserUsername }}</p>
<p v-else class="text-xs">{{ session.user ? session.user.username : 'N/A' }}</p>
<p class="text-xs">{{ session.user ? session.user.username : 'N/A' }}</p>
</td>
<td class="hidden md:table-cell">
<p class="text-xs">{{ getPlayMethodName(session.playMethod) }}</p>
@@ -104,7 +105,12 @@
<script>
export default {
async asyncData({ params, redirect, app }) {
async asyncData({ store, redirect, app }) {
if (!store.getters['user/getIsAdminOrUp']) {
redirect('/')
return
}
const users = await app.$axios
.$get('/api/users')
.then((res) => {
@@ -148,8 +154,8 @@ export default {
},
filteredUserUsername() {
if (!this.userFilter) return null
var user = this.users.find((u) => u.id === this.userFilter)
return user ? user.username : null
const user = this.users.find((u) => u.id === this.userFilter)
return user?.username || null
},
dateFormat() {
return this.$store.state.serverSettings.dateFormat
@@ -268,7 +274,7 @@ export default {
return 'Unknown'
},
async loadSessions(page) {
var userFilterQuery = this.selectedUser ? `&user=${this.selectedUser}` : ''
const userFilterQuery = this.selectedUser ? `&user=${this.selectedUser}` : ''
const data = await this.$axios.$get(`/api/sessions?page=${page}&itemsPerPage=${this.itemsPerPage}${userFilterQuery}`).catch((err) => {
console.error('Failed to load listening sessions', err)
return null
+4 -2
View File
@@ -41,7 +41,7 @@
<div class="flex mb-4 items-center">
<h1 class="text-2xl">{{ $strings.HeaderStatsRecentSessions }}</h1>
<div class="flex-grow" />
<ui-btn :to="`/config/users/${user.id}/sessions`" class="text-xs" :padding-x="1.5" :padding-y="1">{{ $strings.ButtonViewAll }}</ui-btn>
<ui-btn v-if="isAdminOrUp" :to="`/config/users/${user.id}/sessions`" class="text-xs" :padding-x="1.5" :padding-y="1">{{ $strings.ButtonViewAll }}</ui-btn>
</div>
<p v-if="!mostRecentListeningSessions.length">{{ $strings.MessageNoListeningSessions }}</p>
<template v-for="(item, index) in mostRecentListeningSessions">
@@ -82,6 +82,9 @@ export default {
}
},
computed: {
isAdminOrUp() {
return this.$store.getters['user/getIsAdminOrUp']
},
user() {
return this.$store.state.user.user
},
@@ -116,7 +119,6 @@ export default {
console.error('Failed to load listening sesions', err)
return []
})
console.log('Loaded user listening data', this.listeningStats)
}
},
mounted() {
+7 -43
View File
@@ -47,13 +47,7 @@
<div class="py-2">
<h1 class="text-lg mb-2 text-white text-opacity-90 px-2 sm:px-0">{{ $strings.HeaderSavedMediaProgress }}</h1>
<div v-if="mediaProgressWithoutMedia.length" class="flex items-center py-2 mb-2">
<p class="text-error">User has media progress for {{ mediaProgressWithoutMedia.length }} items that no longer exist.</p>
<div class="flex-grow" />
<ui-btn small :loading="purgingMediaProgress" @click.stop="purgeMediaProgress">{{ $strings.ButtonPurgeMediaProgress }}</ui-btn>
</div>
<table v-if="mediaProgressWithMedia.length" class="userAudiobooksTable">
<table v-if="mediaProgress.length" class="userAudiobooksTable">
<tr class="bg-primary bg-opacity-40">
<th class="w-16 text-left">{{ $strings.LabelItem }}</th>
<th class="text-left"></th>
@@ -61,19 +55,14 @@
<th class="w-40 hidden sm:table-cell">{{ $strings.LabelStartedAt }}</th>
<th class="w-40 hidden sm:table-cell">{{ $strings.LabelLastUpdate }}</th>
</tr>
<tr v-for="item in mediaProgressWithMedia" :key="item.id" :class="!item.isFinished ? '' : 'isFinished'">
<tr v-for="item in mediaProgress" :key="item.id" :class="!item.isFinished ? '' : 'isFinished'">
<td>
<covers-book-cover :width="50" :library-item="item" :book-cover-aspect-ratio="bookCoverAspectRatio" />
<covers-preview-cover v-if="item.coverPath" :width="50" :src="$store.getters['globals/getLibraryItemCoverSrcById'](item.libraryItemId, item.mediaUpdatedAt)" :book-cover-aspect-ratio="bookCoverAspectRatio" :show-resolution="false" />
<div v-else class="bg-primary flex items-center justify-center text-center text-xs text-gray-400 p-1" :style="{ width: '50px', height: 50 * bookCoverAspectRatio + 'px' }">No Cover</div>
</td>
<td>
<template v-if="item.media && item.media.metadata && item.episode">
<p>{{ item.episode.title || 'Unknown' }}</p>
<p class="text-white text-opacity-50 text-sm font-sans">{{ item.media.metadata.title }}</p>
</template>
<template v-else-if="item.media && item.media.metadata">
<p>{{ item.media.metadata.title || 'Unknown' }}</p>
<p v-if="item.media.metadata.authorName" class="text-white text-opacity-50 text-sm font-sans">by {{ item.media.metadata.authorName }}</p>
</template>
<p>{{ item.displayTitle || 'Unknown' }}</p>
<p v-if="item.displaySubtitle" class="text-white text-opacity-50 text-sm font-sans">{{ item.displaySubtitle }}</p>
</td>
<td class="text-center">
<p class="text-sm">{{ Math.floor(item.progress * 100) }}%</p>
@@ -111,8 +100,7 @@ export default {
data() {
return {
listeningSessions: {},
listeningStats: {},
purgingMediaProgress: false
listeningStats: {}
}
},
computed: {
@@ -131,12 +119,6 @@ export default {
mediaProgress() {
return this.user.mediaProgress.sort((a, b) => b.lastUpdate - a.lastUpdate)
},
mediaProgressWithMedia() {
return this.mediaProgress.filter((mp) => mp.media)
},
mediaProgressWithoutMedia() {
return this.mediaProgress.filter((mp) => !mp.media)
},
totalListeningTime() {
return this.listeningStats.totalTime || 0
},
@@ -176,24 +158,6 @@ export default {
return []
})
console.log('Loaded user listening data', this.listeningSessions, this.listeningStats)
},
purgeMediaProgress() {
this.purgingMediaProgress = true
this.$axios
.$post(`/api/users/${this.user.id}/purge-media-progress`)
.then((updatedUser) => {
console.log('Updated user', updatedUser)
this.$toast.success('Media progress purged')
this.user = updatedUser
})
.catch((error) => {
console.error('Failed to purge media progress', error)
this.$toast.error('Failed to purge media progress')
})
.finally(() => {
this.purgingMediaProgress = false
})
}
},
mounted() {
+5
View File
@@ -9,6 +9,11 @@
<script>
export default {
asyncData({ store, redirect }) {
if (!store.getters['user/getIsAdminOrUp']) {
redirect('/')
}
},
data() {
return {
selectedAccount: null,
+3 -2
View File
@@ -160,7 +160,7 @@ export default {
}
// Include episode downloads for podcasts
var item = await app.$axios.$get(`/api/items/${params.id}?expanded=1&include=authors,downloads,rssfeed`).catch((error) => {
var item = await app.$axios.$get(`/api/items/${params.id}?expanded=1&include=downloads,rssfeed`).catch((error) => {
console.error('Failed', error)
return false
})
@@ -533,7 +533,6 @@ export default {
.$patch(`/api/me/progress/${this.libraryItemId}`, updatePayload)
.then(() => {
this.isProcessingReadUpdate = false
this.$toast.success(updatePayload.isFinished ? this.$strings.ToastItemMarkedAsFinishedSuccess : this.$strings.ToastItemMarkedAsNotFinishedSuccess)
})
.catch((error) => {
console.error('Failed', error)
@@ -762,6 +761,7 @@ export default {
if (this.libraryId) {
this.$store.commit('libraries/setCurrentLibrary', this.libraryId)
}
this.$eventBus.$on(`${this.libraryItem.id}_updated`, this.libraryItemUpdated)
this.$root.socket.on('item_updated', this.libraryItemUpdated)
this.$root.socket.on('rss_feed_open', this.rssFeedOpen)
this.$root.socket.on('rss_feed_closed', this.rssFeedClosed)
@@ -770,6 +770,7 @@ export default {
this.$root.socket.on('episode_download_finished', this.episodeDownloadFinished)
},
beforeDestroy() {
this.$eventBus.$off(`${this.libraryItem.id}_updated`, this.libraryItemUpdated)
this.$root.socket.off('item_updated', this.libraryItemUpdated)
this.$root.socket.off('rss_feed_open', this.rssFeedOpen)
this.$root.socket.off('rss_feed_closed', this.rssFeedClosed)
@@ -22,7 +22,7 @@
<div class="flex items-center">
<a :href="podcast.pageUrl" class="text-base md:text-lg text-gray-200 hover:underline" target="_blank" @click.stop>{{ podcast.title }}</a>
<widgets-explicit-indicator :explicit="podcast.explicit" />
<widgets-already-in-library-indicator :already-in-library="podcast.alreadyInLibrary"/>
<widgets-already-in-library-indicator :already-in-library="podcast.alreadyInLibrary" />
</div>
<p class="text-sm md:text-base text-gray-300 whitespace-nowrap truncate">by {{ podcast.artistName }}</p>
<p class="text-xs text-gray-400 leading-5">{{ podcast.genres.join(', ') }}</p>
@@ -146,11 +146,15 @@ export default {
async submitSearch(term) {
this.processing = true
this.termSearched = ''
var results = await this.$axios.$get(`/api/search/podcast?term=${encodeURIComponent(term)}`).catch((error) => {
let results = await this.$axios.$get(`/api/search/podcast?term=${encodeURIComponent(term)}`).catch((error) => {
console.error('Search request failed', error)
return []
})
console.log('Got results', results)
// Filter out podcasts without an RSS feed
results = results.filter((r) => r.feedUrl)
for (let result of results) {
let podcast = this.existentPodcasts.find((p) => p.itunesId === result.id || p.title === result.title.toLowerCase())
if (podcast) {
@@ -164,7 +168,7 @@ export default {
},
async selectPodcast(podcast) {
console.log('Selected podcast', podcast)
if(podcast.existentId){
if (podcast.existentId) {
this.$router.push(`/item/${podcast.existentId}`)
return
}
@@ -173,7 +177,7 @@ export default {
return
}
this.processing = true
var payload = await this.$axios.$post(`/api/podcasts/feed`, {rssFeed: podcast.feedUrl}).catch((error) => {
const payload = await this.$axios.$post(`/api/podcasts/feed`, { rssFeed: podcast.feedUrl }).catch((error) => {
console.error('Failed to get feed', error)
this.$toast.error('Failed to get podcast feed')
return null
+1 -1
View File
@@ -19,7 +19,7 @@ export default {
return redirect(`/library/${libraryId}`)
}
const series = await app.$axios.$get(`/api/series/${params.id}?include=progress,rssfeed`).catch((error) => {
const series = await app.$axios.$get(`/api/libraries/${library.id}/series/${params.id}?include=progress,rssfeed`).catch((error) => {
console.error('Failed', error)
return false
})
+14 -6
View File
@@ -74,9 +74,17 @@ export default {
} else {
this.$router.replace('/oops?message=No libraries available')
}
} else if (this.$route.query.redirect) {
this.$router.replace(this.$route.query.redirect)
} else {
if (this.$route.query.redirect) {
const isAdminUser = this.$store.getters['user/getIsAdminOrUp']
const redirect = this.$route.query.redirect
// If not admin user then do not redirect to config pages other than your stats
if (isAdminUser || !redirect.startsWith('/config/') || redirect === '/config/stats') {
this.$router.replace(redirect)
return
}
}
this.$router.replace(`/library/${this.$store.state.libraries.currentLibraryId}`)
}
}
@@ -144,17 +152,17 @@ export default {
this.error = null
this.processing = true
var payload = {
const payload = {
username: this.username,
password: this.password || ''
}
var authRes = await this.$axios.$post('/login', payload).catch((error) => {
const authRes = await this.$axios.$post('/login', payload).catch((error) => {
console.error('Failed', error.response)
if (error.response) this.error = error.response.data
else this.error = 'Unknown Error'
return false
})
if (authRes && authRes.error) {
if (authRes?.error) {
this.error = authRes.error
} else if (authRes) {
this.setUser(authRes)
@@ -162,7 +170,7 @@ export default {
this.processing = false
},
checkAuth() {
var token = localStorage.getItem('token')
const token = localStorage.getItem('token')
if (!token) return false
this.processing = true
+10 -4
View File
@@ -191,6 +191,7 @@ export default class PlayerHandler {
const payload = {
deviceInfo: {
clientName: 'Abs Web',
deviceId: this.getDeviceId()
},
supportedMimeTypes: this.player.playableMimeTypes,
@@ -281,6 +282,10 @@ export default class PlayerHandler {
}
}
/**
* First sync happens after 20 seconds
* subsequent syncs happen every 10 seconds
*/
startPlayInterval() {
clearInterval(this.playInterval)
let lastTick = Date.now()
@@ -293,7 +298,7 @@ export default class PlayerHandler {
const exactTimeElapsed = ((Date.now() - lastTick) / 1000)
lastTick = Date.now()
this.listeningTimeSinceSync += exactTimeElapsed
const TimeToWaitBeforeSync = this.lastSyncTime > 0 ? 5 : 20
const TimeToWaitBeforeSync = this.lastSyncTime > 0 ? 10 : 20
if (this.listeningTimeSinceSync >= TimeToWaitBeforeSync) {
this.sendProgressSync(currentTime)
}
@@ -315,7 +320,7 @@ export default class PlayerHandler {
}
this.listeningTimeSinceSync = 0
this.lastSyncTime = 0
return this.ctx.$axios.$post(`/api/session/${this.currentSessionId}/close`, syncData, { timeout: 1000 }).catch((error) => {
return this.ctx.$axios.$post(`/api/session/${this.currentSessionId}/close`, syncData, { timeout: 6000 }).catch((error) => {
console.error('Failed to close session', error)
})
}
@@ -335,12 +340,13 @@ export default class PlayerHandler {
}
this.listeningTimeSinceSync = 0
this.ctx.$axios.$post(`/api/session/${this.currentSessionId}/sync`, syncData, { timeout: 3000 }).then(() => {
this.ctx.$axios.$post(`/api/session/${this.currentSessionId}/sync`, syncData, { timeout: 9000 }).then(() => {
this.failedProgressSyncs = 0
}).catch((error) => {
console.error('Failed to update session progress', error)
// After 4 failed sync attempts show an alert toast
this.failedProgressSyncs++
if (this.failedProgressSyncs >= 2) {
if (this.failedProgressSyncs >= 4) {
this.ctx.showFailedProgressSyncs()
this.failedProgressSyncs = 0
}
+5
View File
@@ -11,6 +11,11 @@ export default function ({ $axios, store, $config }) {
if (bearerToken) {
config.headers.common['Authorization'] = `Bearer ${bearerToken}`
}
if (process.env.NODE_ENV === 'development') {
config.url = `/dev${config.url}`
console.log('Making request to ' + config.url)
}
})
$axios.onError(error => {
+3 -1
View File
@@ -11,7 +11,9 @@ const languageCodeMap = {
'fr': { label: 'Français', dateFnsLocale: 'fr' },
'hr': { label: 'Hrvatski', dateFnsLocale: 'hr' },
'it': { label: 'Italiano', dateFnsLocale: 'it' },
'lt': { label: 'Lietuvių', dateFnsLocale: 'lt' },
'nl': { label: 'Nederlands', dateFnsLocale: 'nl' },
'no': { label: 'Norsk', dateFnsLocale: 'no' },
'pl': { label: 'Polski', dateFnsLocale: 'pl' },
'ru': { label: 'Русский', dateFnsLocale: 'ru' },
'zh-cn': { label: '简体中文 (Simplified Chinese)', dateFnsLocale: 'zhCN' },
@@ -34,7 +36,7 @@ Vue.prototype.$strings = { ...enUsStrings }
Vue.prototype.$getString = (key, subs) => {
if (!Vue.prototype.$strings[key]) return ''
if (subs && Array.isArray(subs) && subs.length) {
if (subs?.length && Array.isArray(subs)) {
return supplant(Vue.prototype.$strings[key], subs)
}
return Vue.prototype.$strings[key]
+11 -8
View File
@@ -24,20 +24,20 @@ Vue.prototype.$formatJsDate = (jsdate, fnsFormat = 'MM/dd/yyyy HH:mm') => {
return format(jsdate, fnsFormat)
}
Vue.prototype.$formatTime = (unixms, fnsFormat = 'HH:mm') => {
if (!unixms) return ''
return format(unixms, fnsFormat)
if (!unixms) return ''
return format(unixms, fnsFormat)
}
Vue.prototype.$formatJsTime = (jsdate, fnsFormat = 'HH:mm') => {
if (!jsdate || !isDate(jsdate)) return ''
return format(jsdate, fnsFormat)
if (!jsdate || !isDate(jsdate)) return ''
return format(jsdate, fnsFormat)
}
Vue.prototype.$formatDatetime = (unixms, fnsDateFormart = 'MM/dd/yyyy', fnsTimeFormat = 'HH:mm') => {
if (!unixms) return ''
return format(unixms, `${fnsDateFormart} ${fnsTimeFormat}`)
if (!unixms) return ''
return format(unixms, `${fnsDateFormart} ${fnsTimeFormat}`)
}
Vue.prototype.$formatJsDatetime = (jsdate, fnsDateFormart = 'MM/dd/yyyy', fnsTimeFormat = 'HH:mm') => {
if (!jsdate || !isDate(jsdate)) return ''
return format(jsdate, `${fnsDateFormart} ${fnsTimeFormat}`)
if (!jsdate || !isDate(jsdate)) return ''
return format(jsdate, `${fnsDateFormart} ${fnsTimeFormat}`)
}
Vue.prototype.$addDaysToToday = (daysToAdd) => {
var date = addDays(new Date(), daysToAdd)
@@ -132,8 +132,10 @@ Vue.prototype.$copyToClipboard = (str, ctx) => {
if (navigator.clipboard) {
navigator.clipboard.writeText(str).then(() => {
if (ctx) ctx.$toast.success('Copied to clipboard')
resolve(true)
}, (err) => {
console.error('Clipboard copy failed', str, err)
resolve(false)
})
} else {
const el = document.createElement('textarea')
@@ -147,6 +149,7 @@ Vue.prototype.$copyToClipboard = (str, ctx) => {
document.body.removeChild(el)
if (ctx) ctx.$toast.success('Copied to clipboard')
resolve(true)
}
})
}
+7 -7
View File
@@ -83,8 +83,8 @@ export const getters = {
getLibraryItemCoverSrc: (state, getters, rootState, rootGetters) => (libraryItem, placeholder = null) => {
if (!placeholder) placeholder = `${rootState.routerBasePath}/book_placeholder.jpg`
if (!libraryItem) return placeholder
var media = libraryItem.media
if (!media || !media.coverPath || media.coverPath === placeholder) return placeholder
const media = libraryItem.media
if (!media?.coverPath || media.coverPath === placeholder) return placeholder
// Absolute URL covers (should no longer be used)
if (media.coverPath.startsWith('http:') || media.coverPath.startsWith('https:')) return media.coverPath
@@ -99,14 +99,14 @@ export const getters = {
return `${rootState.routerBasePath}/api/items/${libraryItemId}/cover?token=${userToken}&ts=${lastUpdate}`
},
getLibraryItemCoverSrcById: (state, getters, rootState, rootGetters) => (libraryItemId, placeholder = null, raw = false) => {
if (!placeholder) placeholder = `${rootState.routerBasePath}/book_placeholder.jpg`
getLibraryItemCoverSrcById: (state, getters, rootState, rootGetters) => (libraryItemId, timestamp = null, raw = false) => {
const placeholder = `${rootState.routerBasePath}/book_placeholder.jpg`
if (!libraryItemId) return placeholder
var userToken = rootGetters['user/getToken']
const userToken = rootGetters['user/getToken']
if (process.env.NODE_ENV !== 'production') { // Testing
return `http://localhost:3333${rootState.routerBasePath}/api/items/${libraryItemId}/cover?token=${userToken}${raw ? '&raw=1' : ''}`
return `http://localhost:3333${rootState.routerBasePath}/api/items/${libraryItemId}/cover?token=${userToken}${raw ? '&raw=1' : ''}${timestamp ? `&ts=${timestamp}` : ''}`
}
return `${rootState.routerBasePath}/api/items/${libraryItemId}/cover?token=${userToken}${raw ? '&raw=1' : ''}`
return `${rootState.routerBasePath}/api/items/${libraryItemId}/cover?token=${userToken}${raw ? '&raw=1' : ''}${timestamp ? `&ts=${timestamp}` : ''}`
},
getIsBatchSelectingMediaItems: (state) => {
return state.selectedMediaItems.length
+25 -15
View File
@@ -234,25 +234,31 @@ export const mutations = {
setNumUserPlaylists(state, numUserPlaylists) {
state.numUserPlaylists = numUserPlaylists
},
removeSeriesFromFilterData(state, seriesId) {
if (!seriesId || !state.filterData) return
state.filterData.series = state.filterData.series.filter(se => se.id !== seriesId)
},
updateFilterDataWithItem(state, libraryItem) {
if (!libraryItem || !state.filterData) return
if (state.currentLibraryId !== libraryItem.libraryId) return
/*
var data = {
structure of filterData:
{
authors: [],
genres: [],
tags: [],
series: [],
narrators: [],
languages: []
languages: [],
publishers: []
}
*/
var mediaMetadata = libraryItem.media.metadata
const mediaMetadata = libraryItem.media.metadata
// Add/update book authors
if (mediaMetadata.authors && mediaMetadata.authors.length) {
if (mediaMetadata.authors?.length) {
mediaMetadata.authors.forEach((author) => {
var indexOf = state.filterData.authors.findIndex(au => au.id === author.id)
const indexOf = state.filterData.authors.findIndex(au => au.id === author.id)
if (indexOf >= 0) {
state.filterData.authors.splice(indexOf, 1, author)
} else {
@@ -263,9 +269,9 @@ export const mutations = {
}
// Add/update series
if (mediaMetadata.series && mediaMetadata.series.length) {
if (mediaMetadata.series?.length) {
mediaMetadata.series.forEach((series) => {
var indexOf = state.filterData.series.findIndex(se => se.id === series.id)
const indexOf = state.filterData.series.findIndex(se => se.id === series.id)
if (indexOf >= 0) {
state.filterData.series.splice(indexOf, 1, { id: series.id, name: series.name })
} else {
@@ -276,7 +282,7 @@ export const mutations = {
}
// Add genres
if (mediaMetadata.genres && mediaMetadata.genres.length) {
if (mediaMetadata.genres?.length) {
mediaMetadata.genres.forEach((genre) => {
if (!state.filterData.genres.includes(genre)) {
state.filterData.genres.push(genre)
@@ -286,7 +292,7 @@ export const mutations = {
}
// Add tags
if (libraryItem.media.tags && libraryItem.media.tags.length) {
if (libraryItem.media.tags?.length) {
libraryItem.media.tags.forEach((tag) => {
if (!state.filterData.tags.includes(tag)) {
state.filterData.tags.push(tag)
@@ -296,7 +302,7 @@ export const mutations = {
}
// Add narrators
if (mediaMetadata.narrators && mediaMetadata.narrators.length) {
if (mediaMetadata.narrators?.length) {
mediaMetadata.narrators.forEach((narrator) => {
if (!state.filterData.narrators.includes(narrator)) {
state.filterData.narrators.push(narrator)
@@ -305,12 +311,16 @@ export const mutations = {
})
}
// Add publishers
if (mediaMetadata.publisher && !state.filterData.publishers.includes(mediaMetadata.publisher)) {
state.filterData.publishers.push(mediaMetadata.publisher)
state.filterData.publishers.sort((a, b) => a.localeCompare(b))
}
// Add language
if (mediaMetadata.language) {
if (!state.filterData.languages.includes(mediaMetadata.language)) {
state.filterData.languages.push(mediaMetadata.language)
state.filterData.languages.sort((a, b) => a.localeCompare(b))
}
if (mediaMetadata.language && !state.filterData.languages.includes(mediaMetadata.language)) {
state.filterData.languages.push(mediaMetadata.language)
state.filterData.languages.sort((a, b) => a.localeCompare(b))
}
},
setCollections(state, collections) {
+7 -7
View File
@@ -33,22 +33,22 @@ export const getters = {
return state.user.bookmarks.filter(bm => bm.libraryItemId === libraryItemId)
},
getUserSetting: (state) => (key) => {
return state.settings ? state.settings[key] : null
return state.settings?.[key] || null
},
getUserCanUpdate: (state) => {
return state.user && state.user.permissions ? !!state.user.permissions.update : false
return !!state.user?.permissions?.update
},
getUserCanDelete: (state) => {
return state.user && state.user.permissions ? !!state.user.permissions.delete : false
return !!state.user?.permissions?.delete
},
getUserCanDownload: (state) => {
return state.user && state.user.permissions ? !!state.user.permissions.download : false
return !!state.user?.permissions?.download
},
getUserCanUpload: (state) => {
return state.user && state.user.permissions ? !!state.user.permissions.upload : false
return !!state.user?.permissions?.upload
},
getUserCanAccessAllLibraries: (state) => {
return state.user && state.user.permissions ? !!state.user.permissions.accessAllLibraries : false
return !!state.user?.permissions?.accessAllLibraries
},
getLibrariesAccessible: (state, getters) => {
if (!state.user) return []
@@ -80,7 +80,7 @@ export const actions = {
if (state.settings.orderBy == 'media.metadata.publishedYear') {
settingsUpdate.orderBy = 'media.metadata.title'
}
const invalidFilters = ['series', 'authors', 'narrators', 'languages', 'progress', 'issues', 'ebooks', 'abridged']
const invalidFilters = ['series', 'authors', 'narrators', 'publishers', 'languages', 'progress', 'issues', 'ebooks', 'abridged']
const filterByFirstPart = (state.settings.filterBy || '').split('.').shift()
if (invalidFilters.includes(filterByFirstPart)) {
settingsUpdate.filterBy = 'all'
+65 -34
View File
@@ -3,7 +3,7 @@
"ButtonAddChapters": "Kapitel hinzufügen",
"ButtonAddPodcasts": "Podcasts hinzufügen",
"ButtonAddYourFirstLibrary": "Erstelle deine erste Bibliothek",
"ButtonApply": "Anwenden",
"ButtonApply": "Übernehmen",
"ButtonApplyChapters": "Kapitel anwenden",
"ButtonAuthors": "Autoren",
"ButtonBrowseForFolder": "Ordnersuche",
@@ -37,7 +37,7 @@
"ButtonMapChapterTitles": "Kapitelüberschriften zuordnen",
"ButtonMatchAllAuthors": "Online Metadaten-Abgleich (alle Autoren)",
"ButtonMatchBooks": "Online Metadaten-Abgleich (alle Medien)",
"ButtonNevermind": "Vergiss es",
"ButtonNevermind": "Abbrechen",
"ButtonOk": "Ok",
"ButtonOpenFeed": "Feed öffnen",
"ButtonOpenManager": "Manager öffnen",
@@ -98,11 +98,12 @@
"HeaderCurrentDownloads": "Aktuelle Downloads",
"HeaderDetails": "Details",
"HeaderDownloadQueue": "Download Warteschlange",
"HeaderEbookFiles": "Ebook Files",
"HeaderEbookFiles": "E-Book Dateien",
"HeaderEmail": "Email",
"HeaderEmailSettings": "Email Settings",
"HeaderEmailSettings": "Email Einstellungen",
"HeaderEpisodes": "Episoden",
"HeaderEReaderDevices": "E-Reader Devices",
"HeaderEreaderDevices": "Ereader Geräte",
"HeaderEreaderSettings": "Ereader Einstellungen",
"HeaderFiles": "Dateien",
"HeaderFindChapters": "Kapitel suchen",
"HeaderIgnoredFiles": "Ignorierte Dateien",
@@ -137,6 +138,7 @@
"HeaderRemoveEpisodes": "Lösche {0} Episoden",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "RSS-Feed ist geöffnet",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderSavedMediaProgress": "Gespeicherte Hörfortschritte",
"HeaderSchedule": "Zeitplan",
"HeaderScheduleLibraryScans": "Automatische Bibliotheksscans",
@@ -154,6 +156,7 @@
"HeaderStatsRecentSessions": "Neueste Ereignisse",
"HeaderStatsTop10Authors": "Top 10 Autoren",
"HeaderStatsTop5Genres": "Top 5 Kategorien",
"HeaderTableOfContents": "Inhaltsverzeichnis",
"HeaderTools": "Werkzeuge",
"HeaderUpdateAccount": "Konto aktualisieren",
"HeaderUpdateAuthor": "Autor aktualisieren",
@@ -183,6 +186,7 @@
"LabelAuthors": "Autoren",
"LabelAutoDownloadEpisodes": "Episoden automatisch herunterladen",
"LabelBackToUser": "Zurück zum Benutzer",
"LabelBackupLocation": "Backup-Ort",
"LabelBackupsEnableAutomaticBackups": "Automatische Sicherung aktivieren",
"LabelBackupsEnableAutomaticBackupsHelp": "Backups werden in /metadata/backups gespeichert",
"LabelBackupsMaxBackupSize": "Maximale Sicherungsgröße (in GB)",
@@ -193,17 +197,18 @@
"LabelBooks": "Bücher",
"LabelChangePassword": "Passwort ändern",
"LabelChannels": "Kanäle",
"LabelChapters": "Chapters",
"LabelChapters": "Kapitel",
"LabelChaptersFound": "gefundene Kapitel",
"LabelChapterTitle": "Kapitelüberschrift",
"LabelClosePlayer": "Player schließen",
"LabelCodec": "Codec",
"LabelCollapseSeries": "Serien zusammenfassen",
"LabelCollection": "Sammlung",
"LabelCollections": "Sammlungen",
"LabelComplete": "Vollständig",
"LabelConfirmPassword": "Passwort bestätigen",
"LabelContinueListening": "Weiterhören",
"LabelContinueReading": "Continue Reading",
"LabelContinueReading": "Lesen fortsetzen",
"LabelContinueSeries": "Serien fortsetzen",
"LabelCover": "Titelbild",
"LabelCoverImageURL": "URL des Titelbildes",
@@ -220,16 +225,19 @@
"LabelDirectory": "Verzeichnis",
"LabelDiscFromFilename": "CD aus dem Dateinamen",
"LabelDiscFromMetadata": "CD aus den Metadaten",
"LabelDiscover": "Entdecken",
"LabelDownload": "Herunterladen",
"LabelDownloadNEpisodes": "Download {0} episodes",
"LabelDuration": "Laufzeit",
"LabelDurationFound": "Gefundene Laufzeit:",
"LabelEbook": "Ebook",
"LabelEbooks": "Ebooks",
"LabelEbook": "E-Book",
"LabelEbooks": "E-Books",
"LabelEdit": "Bearbeiten",
"LabelEmail": "Email",
"LabelEmailSettingsFromAddress": "From Address",
"LabelEmailSettingsSecure": "Secure",
"LabelEmailSettingsSecureHelp": "If true the connection will use TLS when connecting to server. If false then TLS is used if server supports the STARTTLS extension. In most cases set this value to true if you are connecting to port 465. For port 587 or 25 keep it false. (from nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsFromAddress": "Von Address",
"LabelEmailSettingsSecure": "Sicherheit",
"LabelEmailSettingsSecureHelp": "Wenn \"true\", verwendet die Verbindung TLS, wenn sie eine Verbindung zum Server herstellt. Bei \"false\" wird TLS verwendet, wenn der Server die STARTTLS-Erweiterung unterstützt. In den meisten Fällen setzen Sie diesen Wert auf \"true\", wenn Sie eine Verbindung zu Port 465 herstellen. Für Port 587 oder 25 behalten Sie den Wert \"false\" bei. (von nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Test Addresse",
"LabelEmbeddedCover": "Eingebettetes Cover",
"LabelEnable": "Aktivieren",
"LabelEnd": "Ende",
@@ -240,7 +248,7 @@
"LabelExplicit": "Explizit (Altersbeschränkung)",
"LabelFeedURL": "Feed URL",
"LabelFile": "Datei",
"LabelFileBirthtime": "Datei Geburtsdatum",
"LabelFileBirthtime": "Datei erstellt",
"LabelFileModified": "Datei geändert",
"LabelFilename": "Dateiname",
"LabelFilterByUser": "Nach Benutzern filtern",
@@ -248,12 +256,13 @@
"LabelFinished": "beendet",
"LabelFolder": "Ordner",
"LabelFolders": "Verzeichnisse",
"LabelFontScale": "Schriftgröße",
"LabelFormat": "Format",
"LabelGenre": "Kategorie",
"LabelGenres": "Kategorien",
"LabelHardDeleteFile": "Datei dauerhaft löschen",
"LabelHasEbook": "Has ebook",
"LabelHasSupplementaryEbook": "Has supplementary ebook",
"LabelHasEbook": "mit E-Book",
"LabelHasSupplementaryEbook": "mit zusätlichem E-Book",
"LabelHost": "Host",
"LabelHour": "Stunde",
"LabelIcon": "Symbol",
@@ -270,7 +279,7 @@
"LabelIntervalEveryDay": "Jeden Tag",
"LabelIntervalEveryHour": "Jede Stunde",
"LabelInvalidParts": "Ungültige Teile",
"LabelInvert": "Invert",
"LabelInvert": "Umkehren",
"LabelItem": "Medium",
"LabelLanguage": "Sprache",
"LabelLanguageDefaultServer": "Standard-Server-Sprache",
@@ -279,12 +288,16 @@
"LabelLastSeen": "Zuletzt angesehen",
"LabelLastTime": "Letztes Mal",
"LabelLastUpdate": "Letzte Aktualisierung",
"LabelLayout": "Layout",
"LabelLayoutSinglePage": "Eine Seite",
"LabelLayoutSplitPage": "Geteilte Seite",
"LabelLess": "Weniger",
"LabelLibrariesAccessibleToUser": "Für Benutzer zugängliche Bibliotheken",
"LabelLibrary": "Bibliothek",
"LabelLibraryItem": "Bibliothekseintrag",
"LabelLibraryName": "Bibliotheksname",
"LabelLimit": "Begrenzung",
"LabelLineSpacing": "Zeilenabstand",
"LabelListenAgain": "Erneut anhören",
"LabelLogLevelDebug": "Fehlersuche",
"LabelLogLevelInfo": "Informationen",
@@ -299,7 +312,7 @@
"LabelMissing": "Fehlend",
"LabelMissingParts": "Fehlende Teile",
"LabelMore": "Mehr",
"LabelMoreInfo": "More Info",
"LabelMoreInfo": "Mehr Info",
"LabelName": "Name",
"LabelNarrator": "Erzähler",
"LabelNarrators": "Erzähler",
@@ -309,6 +322,7 @@
"LabelNewPassword": "Neues Passwort",
"LabelNextBackupDate": "Nächstes Sicherungsdatum",
"LabelNextScheduledRun": "Nächster planmäßiger Durchlauf",
"LabelNoEpisodesSelected": "Keine Episoden ausgewählt",
"LabelNotes": "Hinweise",
"LabelNotFinished": "nicht beendet",
"LabelNotificationAppriseURL": "Apprise URL(s)",
@@ -343,15 +357,15 @@
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Zu ignorierende(s) Vorwort(e) (Groß- und Kleinschreibung wird nicht berücksichtigt)",
"LabelPreventIndexing": "Verhindere, dass dein Feed von iTunes- und Google-Podcast-Verzeichnissen indiziert wird",
"LabelPrimaryEbook": "Primary ebook",
"LabelPrimaryEbook": "Haupt-E-Book",
"LabelProgress": "Fortschritt",
"LabelProvider": "Anbieter",
"LabelPubDate": "Veröffentlichungsdatum",
"LabelPublisher": "Herausgeber",
"LabelPublishYear": "Jahr",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRead": "Lesen",
"LabelReadAgain": "Nocheinmal Lesen",
"LabelReadEbookWithoutProgress": "E-Book lesen und Fortschritt verwerfen",
"LabelRecentlyAdded": "Kürzlich hinzugefügt",
"LabelRecentSeries": "Aktuelle Serien",
"LabelRecommended": "Empfohlen",
@@ -368,25 +382,32 @@
"LabelSearchTitle": "Titel",
"LabelSearchTitleOrASIN": "Titel oder ASIN",
"LabelSeason": "Staffel",
"LabelSendEbookToDevice": "Send Ebook to...",
"LabelSelectAllEpisodes": "Alle Episoden auswählen",
"LabelSelectEpisodesShowing": "{0} ausgewählte Episoden werden angezeigt",
"LabelSendEbookToDevice": "E-Book senden an...",
"LabelSequence": "Reihenfolge",
"LabelSeries": "Serien",
"LabelSeriesName": "Serienname",
"LabelSeriesProgress": "Serienfortschritt",
"LabelSetEbookAsPrimary": "Set as primary",
"LabelSetEbookAsSupplementary": "Set as supplementary",
"LabelSettingsAudiobooksOnly": "Audiobooks only",
"LabelSettingsAudiobooksOnlyHelp": "Enabling this setting will ignore ebook files unless they are inside an audiobook folder in which case they will be set as supplementary ebooks",
"LabelSetEbookAsPrimary": "Setzen als Hauptbuch",
"LabelSetEbookAsSupplementary": "Setzen als Ergänzung",
"LabelSettingsAudiobooksOnly": "nur Hörbücher",
"LabelSettingsAudiobooksOnlyHelp": "Wenn Sie diese Einstellung aktivieren, werden E-Book-Dateien ignoriert, es sei denn, sie befinden sich in einem Hörbuchordner. In diesem Fall werden sie als zusätzliche E-Books festgelegt",
"LabelSettingsBookshelfViewHelp": "Skeumorphes Design mit Holzeinlegeböden",
"LabelSettingsChromecastSupport": "Chromecastunterstützung",
"LabelSettingsDateFormat": "Datumsformat",
"LabelSettingsDisableWatcher": "Überwachung deaktivieren",
"LabelSettingsDisableWatcherForLibrary": "Ordnerüberwachung für die Bibliothek deaktivieren",
"LabelSettingsDisableWatcherHelp": "Deaktiviert das automatische Hinzufügen/Aktualisieren von Elementen, wenn Dateiänderungen erkannt werden. *Erfordert einen Server-Neustart",
"LabelSettingsEnableWatcher": "Überwachung aktivieren",
"LabelSettingsEnableWatcherForLibrary": "Ordnerüberwachung für die Bibliothek aktivieren",
"LabelSettingsEnableWatcherHelp": "Aktiviert das automatische Hinzufügen/Aktualisieren von Elementen, wenn Dateiänderungen erkannt werden. *Erfordert einen Server-Neustart",
"LabelSettingsExperimentalFeatures": "Experimentelle Funktionen",
"LabelSettingsExperimentalFeaturesHelp": "Funktionen welche sich in der Entwicklung befinden, benötigen Ihr Feedback und Ihre Hilfe beim Testen. Klicken Sie hier, um die Github-Diskussion zu öffnen.",
"LabelSettingsFindCovers": "Suche Titelbilder",
"LabelSettingsFindCoversHelp": "Wenn Ihr Medium kein eingebettetes Titelbild oder kein Titelbild im Ordner hat, versucht der Scanner, ein Titelbild online zu finden.<br>Hinweis: Dies verlängert die Scandauer",
"LabelSettingsHideSingleBookSeries": "Ausblenden einzelzne Bücher",
"LabelSettingsHideSingleBookSeriesHelp": "Serien, die ein einzelnes Buch enthalten, werden in den Regalen der Serienseite und der Startseite ausgeblendet.",
"LabelSettingsHomePageBookshelfView": "Startseite verwendet die Bücherregalansicht",
"LabelSettingsLibraryBookshelfView": "Bibliothek verwendet die Bücherregalansicht",
"LabelSettingsOverdriveMediaMarkers": "Verwende Overdrive Media Marker für Kapitel",
@@ -413,6 +434,7 @@
"LabelShowAll": "Alles anzeigen",
"LabelSize": "Größe",
"LabelSleepTimer": "Einschlaf-Timer",
"LabelSlug": "URL Teil",
"LabelStart": "Start",
"LabelStarted": "Gestartet",
"LabelStartedAt": "Gestartet am",
@@ -439,6 +461,9 @@
"LabelTagsAccessibleToUser": "Für Benutzer zugängliche Schlagwörter",
"LabelTagsNotAccessibleToUser": "Für Benutzer nicht zugängliche Schlagwörter",
"LabelTasks": "Laufende Aufgaben",
"LabelTheme": "Theme",
"LabelThemeDark": "Dark",
"LabelThemeLight": "Light",
"LabelTimeBase": "Basiszeit",
"LabelTimeListened": "Gehörte Zeit",
"LabelTimeListenedToday": "Heute gehörte Zeit",
@@ -457,6 +482,7 @@
"LabelTrackFromMetadata": "Titel aus Metadaten",
"LabelTracks": "Dateien",
"LabelTracksMultiTrack": "Mehrfachdatei",
"LabelTracksNone": "Keine Dateien",
"LabelTracksSingleTrack": "Einzeldatei",
"LabelType": "Typ",
"LabelUnabridged": "Ungekürzt",
@@ -477,7 +503,7 @@
"LabelViewBookmarks": "Lesezeichen anzeigen",
"LabelViewChapters": "Kapitel anzeigen",
"LabelViewQueue": "Spieler-Warteschlange anzeigen",
"LabelVolume": "Volume",
"LabelVolume": "Volumen",
"LabelWeekdaysToRun": "Wochentage für die Ausführung",
"LabelYourAudiobookDuration": "Laufzeit Ihres Mediums",
"LabelYourBookmarks": "Lesezeichen",
@@ -497,14 +523,18 @@
"MessageChapterErrorStartLtPrev": "Ungültige Kapitelstartzeit: Kapitelanfang < Kapitelanfang vorheriges Kapitel (Kapitelanfang liegt zeitlich vor dem Beginn des vorherigen Kapitels -> Lösung: Kapitelanfang >= Startzeit des vorherigen Kapitels)",
"MessageChapterStartIsAfter": "Ungültige Kapitelstartzeit: Kapitelanfang > Mediumende (Kapitelanfang liegt nach dem Ende des Mediums)",
"MessageCheckingCron": "Überprüfe Cron...",
"MessageConfirmCloseFeed": "Sind Sie sicher, dass Sie diesen Feed schließen wollen?",
"MessageConfirmDeleteBackup": "Sind Sie sicher, dass Sie die Sicherung für {0} löschen wollen?",
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
"MessageConfirmDeleteFile": "Es wird die Datei vom System löschen. Sind Sie sicher?",
"MessageConfirmDeleteLibrary": "Sind Sie sicher, dass Sie die Bibliothek \"{0}\" dauerhaft löschen wollen?",
"MessageConfirmDeleteSession": "Sind Sie sicher, dass Sie diese Sitzung löschen möchten?",
"MessageConfirmForceReScan": "Sind Sie sicher, dass Sie einen erneuten Scanvorgang erzwingen wollen?",
"MessageConfirmMarkAllEpisodesFinished": "Sind Sie sicher, dass Sie alle Episoden als abgeschlossen markieren möchten?",
"MessageConfirmMarkAllEpisodesNotFinished": "Sind Sie sicher, dass Sie alle Episoden als nicht abgeschlossen markieren möchten?",
"MessageConfirmMarkSeriesFinished": "Sind Sie sicher, dass Sie alle Medien dieser Reihe als abgeschlossen markieren wollen?",
"MessageConfirmMarkSeriesNotFinished": "Sind Sie sicher, dass Sie alle Medien dieser Reihe als nicht abgeschlossen markieren wollen?",
"MessageConfirmRemoveAllChapters": "Sind Sie sicher, dass Sie alle Kapitel entfernen möchten?",
"MessageConfirmRemoveAuthor": "Sind Sie sicher, dass Sie den Autor \"{0}\" enfernen möchten?",
"MessageConfirmRemoveCollection": "Sind Sie sicher, dass Sie die Sammlung \"{0}\" löschen wollen?",
"MessageConfirmRemoveEpisode": "Sind Sie sicher, dass Sie die Episode \"{0}\" löschen möchten?",
"MessageConfirmRemoveEpisodes": "Sind Sie sicher, dass Sie {0} Episoden löschen wollen?",
@@ -516,7 +546,7 @@
"MessageConfirmRenameTag": "Sind Sie sicher, dass Sie den Tag \"{0}\" in \"{1}\" für alle Hörbücher/Podcasts umbenennen wollen?",
"MessageConfirmRenameTagMergeNote": "Hinweis: Tag existiert bereits -> Tags werden zusammengelegt.",
"MessageConfirmRenameTagWarning": "Warnung! Ein ähnlicher Tag mit einem anderen Wortlaut existiert bereits: \"{0}\".",
"MessageConfirmSendEbookToDevice": "Are you sure you want to send {0} ebook \"{1}\" to device \"{2}\"?",
"MessageConfirmSendEbookToDevice": "Sind Sie sicher, dass sie {0} ebook \"{1}\" auf das Gerät \"{2}\" senden wollen?",
"MessageDownloadingEpisode": "Episode herunterladen",
"MessageDragFilesIntoTrackOrder": "Verschieben Sie die Dateien in die richtige Reihenfolge",
"MessageEmbedFinished": "Einbettung abgeschlossen!",
@@ -535,9 +565,11 @@
"MessageM4BFailed": "M4B fehlgeschlagen!",
"MessageM4BFinished": "M4B beendet!",
"MessageMapChapterTitles": "Zuordnen von Kapiteltiteln zu Ihren vorhandenen Medienkapiteln ohne Anpassung der Zeitangaben",
"MessageMarkAllEpisodesFinished": "Alle Episoden als beendet markieren",
"MessageMarkAllEpisodesNotFinished": "Alle Episoden als ungehört markieren",
"MessageMarkAsFinished": "Als beendet markieren",
"MessageMarkAsNotFinished": "Als nicht abgeschlossen markieren",
"MessageMatchBooksDescription": "versucht, Bücher in der Bibliothek mit einem Buch des ausgewählten Suchanbieters abzugleichen und leere Details und das Titelbild auszufüllen. Details werden nicht überschrieben.",
"MessageMatchBooksDescription": "Es wird versucht die Bücher in der Bibliothek mit einem Buch des ausgewählten Suchanbieters abzugleichen um leere Details und das Titelbild auszufüllen. Vorhandene Details werden nicht überschrieben.",
"MessageNoAudioTracks": "Keine Audiodateien",
"MessageNoAuthors": "Keine Autoren",
"MessageNoBackups": "Keine Sicherungen",
@@ -573,9 +605,8 @@
"MessagePauseChapter": "Kapitelwiedergabe pausieren",
"MessagePlayChapter": "Kapitelanfang anhören",
"MessagePlaylistCreateFromCollection": "Erstelle eine Wiedergabeliste aus der Sammlung",
"MessagePodcastHasNoRSSFeedForMatching": "Podcast hat keine RSS-Feed-Url welche für den Online-Abgleich verwendet werden kann",
"MessagePodcastHasNoRSSFeedForMatching": "Der Podcast hat keine RSS-Feed-Url welche für den Online-Abgleich verwendet werden kann",
"MessageQuickMatchDescription": "Füllt leere Details und Titelbilder mit dem ersten Treffer aus '{0}'. Überschreibt keine Details, es sei denn, die Server-Einstellung \"Passende Metadaten bevorzugen\" ist aktiviert.",
"MessageRemoveAllItemsWarning": "WARNUNG! Bei dieser Aktion werden alle Bibliotheksobjekte aus der Datenbank entfernt, einschließlich aller Aktualisierungen oder Online-Abgleichs, die Sie vorgenommen haben. Ihre eigentlichen Dateien bleiben davon unberührt. Sind Sie sicher?",
"MessageRemoveChapter": "Kapitel löschen",
"MessageRemoveEpisodes": "Entferne {0} Episode(n)",
"MessageRemoveFromPlayerQueue": "Aus der Abspielwarteliste löschen",
@@ -671,8 +702,8 @@
"ToastRemoveItemFromCollectionSuccess": "Medium aus der Sammlung gelöscht",
"ToastRSSFeedCloseFailed": "RSS-Feed konnte nicht geschlossen werden",
"ToastRSSFeedCloseSuccess": "RSS-Feed geschlossen",
"ToastSendEbookToDeviceFailed": "Failed to send ebook to device",
"ToastSendEbookToDeviceSuccess": "Ebook sent to device \"{0}\"",
"ToastSendEbookToDeviceFailed": "E-Book konnte nicht auf Gerät übertragen werden",
"ToastSendEbookToDeviceSuccess": "E-Book an Gerät senden \"{0}\"",
"ToastSeriesUpdateFailed": "Aktualisierung der Serien fehlgeschlagen",
"ToastSeriesUpdateSuccess": "Serien aktualisiert",
"ToastSessionDeleteFailed": "Sitzung konnte nicht gelöscht werden",
+33 -2
View File
@@ -102,7 +102,8 @@
"HeaderEmail": "Email",
"HeaderEmailSettings": "Email Settings",
"HeaderEpisodes": "Episodes",
"HeaderEReaderDevices": "E-Reader Devices",
"HeaderEreaderDevices": "Ereader Devices",
"HeaderEreaderSettings": "Ereader Settings",
"HeaderFiles": "Files",
"HeaderFindChapters": "Find Chapters",
"HeaderIgnoredFiles": "Ignored Files",
@@ -137,6 +138,7 @@
"HeaderRemoveEpisodes": "Remove {0} Episodes",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "RSS Feed is Open",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderSavedMediaProgress": "Saved Media Progress",
"HeaderSchedule": "Schedule",
"HeaderScheduleLibraryScans": "Schedule Automatic Library Scans",
@@ -154,6 +156,7 @@
"HeaderStatsRecentSessions": "Recent Sessions",
"HeaderStatsTop10Authors": "Top 10 Authors",
"HeaderStatsTop5Genres": "Top 5 Genres",
"HeaderTableOfContents": "Table of Contents",
"HeaderTools": "Tools",
"HeaderUpdateAccount": "Update Account",
"HeaderUpdateAuthor": "Update Author",
@@ -183,6 +186,7 @@
"LabelAuthors": "Authors",
"LabelAutoDownloadEpisodes": "Auto Download Episodes",
"LabelBackToUser": "Back to User",
"LabelBackupLocation": "Backup Location",
"LabelBackupsEnableAutomaticBackups": "Enable automatic backups",
"LabelBackupsEnableAutomaticBackupsHelp": "Backups saved in /metadata/backups",
"LabelBackupsMaxBackupSize": "Maximum backup size (in GB)",
@@ -199,6 +203,7 @@
"LabelClosePlayer": "Close player",
"LabelCodec": "Codec",
"LabelCollapseSeries": "Collapse Series",
"LabelCollection": "Collection",
"LabelCollections": "Collections",
"LabelComplete": "Complete",
"LabelConfirmPassword": "Confirm Password",
@@ -220,7 +225,9 @@
"LabelDirectory": "Directory",
"LabelDiscFromFilename": "Disc from Filename",
"LabelDiscFromMetadata": "Disc from Metadata",
"LabelDiscover": "Discover",
"LabelDownload": "Download",
"LabelDownloadNEpisodes": "Download {0} episodes",
"LabelDuration": "Duration",
"LabelDurationFound": "Duration found:",
"LabelEbook": "Ebook",
@@ -230,6 +237,7 @@
"LabelEmailSettingsFromAddress": "From Address",
"LabelEmailSettingsSecure": "Secure",
"LabelEmailSettingsSecureHelp": "If true the connection will use TLS when connecting to server. If false then TLS is used if server supports the STARTTLS extension. In most cases set this value to true if you are connecting to port 465. For port 587 or 25 keep it false. (from nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Test Address",
"LabelEmbeddedCover": "Embedded Cover",
"LabelEnable": "Enable",
"LabelEnd": "End",
@@ -248,6 +256,7 @@
"LabelFinished": "Finished",
"LabelFolder": "Folder",
"LabelFolders": "Folders",
"LabelFontScale": "Font scale",
"LabelFormat": "Format",
"LabelGenre": "Genre",
"LabelGenres": "Genres",
@@ -279,12 +288,16 @@
"LabelLastSeen": "Last Seen",
"LabelLastTime": "Last Time",
"LabelLastUpdate": "Last Update",
"LabelLayout": "Layout",
"LabelLayoutSinglePage": "Single page",
"LabelLayoutSplitPage": "Split page",
"LabelLess": "Less",
"LabelLibrariesAccessibleToUser": "Libraries Accessible to User",
"LabelLibrary": "Library",
"LabelLibraryItem": "Library Item",
"LabelLibraryName": "Library Name",
"LabelLimit": "Limit",
"LabelLineSpacing": "Line spacing",
"LabelListenAgain": "Listen Again",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Info",
@@ -309,6 +322,7 @@
"LabelNewPassword": "New Password",
"LabelNextBackupDate": "Next backup date",
"LabelNextScheduledRun": "Next scheduled run",
"LabelNoEpisodesSelected": "No episodes selected",
"LabelNotes": "Notes",
"LabelNotFinished": "Not Finished",
"LabelNotificationAppriseURL": "Apprise URL(s)",
@@ -368,6 +382,8 @@
"LabelSearchTitle": "Search Title",
"LabelSearchTitleOrASIN": "Search Title or ASIN",
"LabelSeason": "Season",
"LabelSelectAllEpisodes": "Select all episodes",
"LabelSelectEpisodesShowing": "Select {0} episodes showing",
"LabelSendEbookToDevice": "Send Ebook to...",
"LabelSequence": "Sequence",
"LabelSeries": "Series",
@@ -383,10 +399,15 @@
"LabelSettingsDisableWatcher": "Disable Watcher",
"LabelSettingsDisableWatcherForLibrary": "Disable folder watcher for library",
"LabelSettingsDisableWatcherHelp": "Disables the automatic adding/updating of items when file changes are detected. *Requires server restart",
"LabelSettingsEnableWatcher": "Enable Watcher",
"LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
"LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
"LabelSettingsExperimentalFeatures": "Experimental features",
"LabelSettingsExperimentalFeaturesHelp": "Features in development that could use your feedback and help testing. Click to open github discussion.",
"LabelSettingsFindCovers": "Find covers",
"LabelSettingsFindCoversHelp": "If your audiobook does not have an embedded cover or a cover image inside the folder, the scanner will attempt to find a cover.<br>Note: This will extend scan time",
"LabelSettingsHideSingleBookSeries": "Hide single book series",
"LabelSettingsHideSingleBookSeriesHelp": "Series that have a single book will be hidden from the series page and home page shelves.",
"LabelSettingsHomePageBookshelfView": "Home page use bookshelf view",
"LabelSettingsLibraryBookshelfView": "Library use bookshelf view",
"LabelSettingsOverdriveMediaMarkers": "Use Overdrive Media Markers for chapters",
@@ -413,6 +434,7 @@
"LabelShowAll": "Show All",
"LabelSize": "Size",
"LabelSleepTimer": "Sleep timer",
"LabelSlug": "Slug",
"LabelStart": "Start",
"LabelStarted": "Started",
"LabelStartedAt": "Started At",
@@ -439,6 +461,9 @@
"LabelTagsAccessibleToUser": "Tags Accessible to User",
"LabelTagsNotAccessibleToUser": "Tags not Accessible to User",
"LabelTasks": "Tasks Running",
"LabelTheme": "Theme",
"LabelThemeDark": "Dark",
"LabelThemeLight": "Light",
"LabelTimeBase": "Time Base",
"LabelTimeListened": "Time Listened",
"LabelTimeListenedToday": "Time Listened Today",
@@ -457,6 +482,7 @@
"LabelTrackFromMetadata": "Track from Metadata",
"LabelTracks": "Tracks",
"LabelTracksMultiTrack": "Multi-track",
"LabelTracksNone": "No tracks",
"LabelTracksSingleTrack": "Single-track",
"LabelType": "Type",
"LabelUnabridged": "Unabridged",
@@ -497,14 +523,18 @@
"MessageChapterErrorStartLtPrev": "Invalid start time must be greater than or equal to previous chapter start time",
"MessageChapterStartIsAfter": "Chapter start is after the end of your audiobook",
"MessageCheckingCron": "Checking cron...",
"MessageConfirmCloseFeed": "Are you sure you want to close this feed?",
"MessageConfirmDeleteBackup": "Are you sure you want to delete backup for {0}?",
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
"MessageConfirmDeleteLibrary": "Are you sure you want to permanently delete library \"{0}\"?",
"MessageConfirmDeleteSession": "Are you sure you want to delete this session?",
"MessageConfirmForceReScan": "Are you sure you want to force re-scan?",
"MessageConfirmMarkAllEpisodesFinished": "Are you sure you want to mark all episodes as finished?",
"MessageConfirmMarkAllEpisodesNotFinished": "Are you sure you want to mark all episodes as not finished?",
"MessageConfirmMarkSeriesFinished": "Are you sure you want to mark all books in this series as finished?",
"MessageConfirmMarkSeriesNotFinished": "Are you sure you want to mark all books in this series as not finished?",
"MessageConfirmRemoveAllChapters": "Are you sure you want to remove all chapters?",
"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}\"?",
"MessageConfirmRemoveEpisodes": "Are you sure you want to remove {0} episodes?",
@@ -535,6 +565,8 @@
"MessageM4BFailed": "M4B Failed!",
"MessageM4BFinished": "M4B Finished!",
"MessageMapChapterTitles": "Map chapter titles to your existing audiobook chapters without adjusting timestamps",
"MessageMarkAllEpisodesFinished": "Mark all episodes finished",
"MessageMarkAllEpisodesNotFinished": "Mark all episodes not finished",
"MessageMarkAsFinished": "Mark as Finished",
"MessageMarkAsNotFinished": "Mark as Not Finished",
"MessageMatchBooksDescription": "will attempt to match books in the library with a book from the selected search provider and fill in empty details and cover art. Does not overwrite details.",
@@ -575,7 +607,6 @@
"MessagePlaylistCreateFromCollection": "Create playlist from collection",
"MessagePodcastHasNoRSSFeedForMatching": "Podcast has no RSS feed url to use for matching",
"MessageQuickMatchDescription": "Populate empty item details & cover with first match result from '{0}'. Does not overwrite details unless 'Prefer matched metadata' server setting is enabled.",
"MessageRemoveAllItemsWarning": "WARNING! This action will remove all library items from the database including any updates or matches you have made. This does not do anything to your actual files. Are you sure?",
"MessageRemoveChapter": "Remove chapter",
"MessageRemoveEpisodes": "Remove {0} episode(s)",
"MessageRemoveFromPlayerQueue": "Remove from player queue",
+33 -2
View File
@@ -102,7 +102,8 @@
"HeaderEmail": "Email",
"HeaderEmailSettings": "Email Settings",
"HeaderEpisodes": "Episodios",
"HeaderEReaderDevices": "E-Reader Devices",
"HeaderEreaderDevices": "Ereader Devices",
"HeaderEreaderSettings": "Ereader Settings",
"HeaderFiles": "Elemento",
"HeaderFindChapters": "Buscar Capitulo",
"HeaderIgnoredFiles": "Ignorar Elemento",
@@ -137,6 +138,7 @@
"HeaderRemoveEpisodes": "Remover {0} Episodios",
"HeaderRSSFeedGeneral": "Detalles RSS",
"HeaderRSSFeedIsOpen": "Fuente RSS esta abierta",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderSavedMediaProgress": "Guardar Progreso de multimedia",
"HeaderSchedule": "Horario",
"HeaderScheduleLibraryScans": "Programar Escaneo Automático de Biblioteca",
@@ -154,6 +156,7 @@
"HeaderStatsRecentSessions": "Sesiones Recientes",
"HeaderStatsTop10Authors": "Top 10 Autores",
"HeaderStatsTop5Genres": "Top 5 Géneros",
"HeaderTableOfContents": "Table of Contents",
"HeaderTools": "Herramientas",
"HeaderUpdateAccount": "Actualizar Cuenta",
"HeaderUpdateAuthor": "Actualizar Autor",
@@ -183,6 +186,7 @@
"LabelAuthors": "Autores",
"LabelAutoDownloadEpisodes": "Descargar Episodios Automáticamente",
"LabelBackToUser": "Regresar a Usuario",
"LabelBackupLocation": "Backup Location",
"LabelBackupsEnableAutomaticBackups": "Habilitar Respaldo Automático",
"LabelBackupsEnableAutomaticBackupsHelp": "Respaldo Guardado en /metadata/backups",
"LabelBackupsMaxBackupSize": "Tamaño Máximo de Respaldos (en GB)",
@@ -199,6 +203,7 @@
"LabelClosePlayer": "Close player",
"LabelCodec": "Codec",
"LabelCollapseSeries": "Colapsar Series",
"LabelCollection": "Collection",
"LabelCollections": "Colecciones",
"LabelComplete": "Completo",
"LabelConfirmPassword": "Confirmar Contraseña",
@@ -220,7 +225,9 @@
"LabelDirectory": "Directorio",
"LabelDiscFromFilename": "Disco a partir del Nombre del Archivo",
"LabelDiscFromMetadata": "Disco a partir de Metadata",
"LabelDiscover": "Discover",
"LabelDownload": "Descargar",
"LabelDownloadNEpisodes": "Download {0} episodes",
"LabelDuration": "Duración",
"LabelDurationFound": "Duración Comprobada:",
"LabelEbook": "Ebook",
@@ -230,6 +237,7 @@
"LabelEmailSettingsFromAddress": "From Address",
"LabelEmailSettingsSecure": "Secure",
"LabelEmailSettingsSecureHelp": "If true the connection will use TLS when connecting to server. If false then TLS is used if server supports the STARTTLS extension. In most cases set this value to true if you are connecting to port 465. For port 587 or 25 keep it false. (from nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Test Address",
"LabelEmbeddedCover": "Portada Integrada",
"LabelEnable": "Habilitar",
"LabelEnd": "Fin",
@@ -248,6 +256,7 @@
"LabelFinished": "Terminado",
"LabelFolder": "Carpeta",
"LabelFolders": "Carpetas",
"LabelFontScale": "Font scale",
"LabelFormat": "Formato",
"LabelGenre": "Genero",
"LabelGenres": "Géneros",
@@ -279,12 +288,16 @@
"LabelLastSeen": "Ultima Vez Visto",
"LabelLastTime": "Ultima Vez",
"LabelLastUpdate": "Ultima Actualización",
"LabelLayout": "Layout",
"LabelLayoutSinglePage": "Single page",
"LabelLayoutSplitPage": "Split page",
"LabelLess": "Menos",
"LabelLibrariesAccessibleToUser": "Bibliotecas Disponibles para el Usuario",
"LabelLibrary": "Biblioteca",
"LabelLibraryItem": "Elemento de Biblioteca",
"LabelLibraryName": "Nombre de Biblioteca",
"LabelLimit": "Limites",
"LabelLineSpacing": "Line spacing",
"LabelListenAgain": "Escuchar Otra Vez",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Info",
@@ -309,6 +322,7 @@
"LabelNewPassword": "Nueva Contraseña",
"LabelNextBackupDate": "Fecha del Siguiente Respaldo",
"LabelNextScheduledRun": "Próxima Ejecución Programada",
"LabelNoEpisodesSelected": "No episodes selected",
"LabelNotes": "Notas",
"LabelNotFinished": "No Terminado",
"LabelNotificationAppriseURL": "Apprise URL(s)",
@@ -368,6 +382,8 @@
"LabelSearchTitle": "Buscar Titulo",
"LabelSearchTitleOrASIN": "Buscar Titulo o ASIN",
"LabelSeason": "Temporada",
"LabelSelectAllEpisodes": "Select all episodes",
"LabelSelectEpisodesShowing": "Select {0} episodes showing",
"LabelSendEbookToDevice": "Send Ebook to...",
"LabelSequence": "Secuencia",
"LabelSeries": "Series",
@@ -383,10 +399,15 @@
"LabelSettingsDisableWatcher": "Deshabilitar Watcher",
"LabelSettingsDisableWatcherForLibrary": "Deshabilitar Watcher de Carpetas para esta biblioteca",
"LabelSettingsDisableWatcherHelp": "Deshabilitar la función automática de agregar/actualizar los elementos, cuando se detecta cambio en los archivos. *Require Reiniciar el Servidor",
"LabelSettingsEnableWatcher": "Enable Watcher",
"LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
"LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
"LabelSettingsExperimentalFeatures": "Funciones Experimentales",
"LabelSettingsExperimentalFeaturesHelp": "Funciones en desarrollo sobre las que esperamos sus comentarios y experiencia. Haga click aquí para abrir una conversación en Github.",
"LabelSettingsFindCovers": "Buscar Portadas",
"LabelSettingsFindCoversHelp": "Si tu audiolibro no tiene una portada incluida o la portada no esta dentro de la carpeta, el escaneador tratara de encontrar una portada.<br>Nota: Esto extenderá el tiempo de escaneo",
"LabelSettingsHideSingleBookSeries": "Hide single book series",
"LabelSettingsHideSingleBookSeriesHelp": "Series that have a single book will be hidden from the series page and home page shelves.",
"LabelSettingsHomePageBookshelfView": "La pagina de inicio usa la vista de librero",
"LabelSettingsLibraryBookshelfView": "La biblioteca usa la vista de librero",
"LabelSettingsOverdriveMediaMarkers": "Usar Markers de multimedia en Overdrive para estos capítulos",
@@ -413,6 +434,7 @@
"LabelShowAll": "Mostrar Todos",
"LabelSize": "Tamaño",
"LabelSleepTimer": "Temporizador para Dormir",
"LabelSlug": "Slug",
"LabelStart": "Iniciar",
"LabelStarted": "Indiciado",
"LabelStartedAt": "Iniciado En",
@@ -439,6 +461,9 @@
"LabelTagsAccessibleToUser": "Etiquetas Accessible para el Usuario",
"LabelTagsNotAccessibleToUser": "Tags not Accessible to User",
"LabelTasks": "Tareas Corriendo",
"LabelTheme": "Theme",
"LabelThemeDark": "Dark",
"LabelThemeLight": "Light",
"LabelTimeBase": "Time Base",
"LabelTimeListened": "Tiempo Escuchando",
"LabelTimeListenedToday": "Tiempo Escuchando Hoy",
@@ -457,6 +482,7 @@
"LabelTrackFromMetadata": "Pista desde Metadata",
"LabelTracks": "Pistas",
"LabelTracksMultiTrack": "Multi-track",
"LabelTracksNone": "No tracks",
"LabelTracksSingleTrack": "Single-track",
"LabelType": "Tipo",
"LabelUnabridged": "Unabridged",
@@ -497,14 +523,18 @@
"MessageChapterErrorStartLtPrev": "El tiempo de inicio no es válida debe ser mayor o igual que la hora de inicio del capítulo anterior",
"MessageChapterStartIsAfter": "El comienzo del capítulo es después del final de su audiolibro",
"MessageCheckingCron": "Checking cron...",
"MessageConfirmCloseFeed": "Are you sure you want to close this feed?",
"MessageConfirmDeleteBackup": "Esta seguro que desea eliminar el respaldo {0}?",
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
"MessageConfirmDeleteLibrary": "Esta seguro que desea eliminar permanentemente la biblioteca \"{0}\"?",
"MessageConfirmDeleteSession": "Esta seguro que desea eliminar esta session?",
"MessageConfirmForceReScan": "Esta seguro que desea forzar re-escanear?",
"MessageConfirmMarkAllEpisodesFinished": "Are you sure you want to mark all episodes as finished?",
"MessageConfirmMarkAllEpisodesNotFinished": "Are you sure you want to mark all episodes as not finished?",
"MessageConfirmMarkSeriesFinished": "Esta seguro que desea marcar todos los libros en esta serie como terminados?",
"MessageConfirmMarkSeriesNotFinished": "Esta seguro que desea marcar todos los libros en esta serie como no terminados?",
"MessageConfirmRemoveAllChapters": "Esta seguro que desea remover todos los capitulos?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Esta seguro que desea remover la colección \"{0}\"?",
"MessageConfirmRemoveEpisode": "Esta seguro que desea remover el episodio \"{0}\"?",
"MessageConfirmRemoveEpisodes": "Esta seguro que desea remover {0} episodios?",
@@ -535,6 +565,8 @@
"MessageM4BFailed": "M4B Fallo!",
"MessageM4BFinished": "M4B Terminado!",
"MessageMapChapterTitles": "Map chapter titles to your existing audiobook chapters without adjusting timestamps",
"MessageMarkAllEpisodesFinished": "Mark all episodes finished",
"MessageMarkAllEpisodesNotFinished": "Mark all episodes not finished",
"MessageMarkAsFinished": "Marcar como Terminado",
"MessageMarkAsNotFinished": "Marcar como No Terminado",
"MessageMatchBooksDescription": "intentará hacer coincidir los libros de la biblioteca con un libro del proveedor de búsqueda seleccionado y rellenará los detalles vacíos y la portada. No sobrescribe los detalles.",
@@ -575,7 +607,6 @@
"MessagePlaylistCreateFromCollection": "Crear lista de reproducción a partir de colección",
"MessagePodcastHasNoRSSFeedForMatching": "El podcast no tiene una URL de fuente RSS que pueda usar que coincida",
"MessageQuickMatchDescription": "Rellenar detalles de elementos vacíos y portada con los primeros resultados de '{0}'. No sobrescribe los detalles a menos que la configuración 'Prefer matched metadata' del servidor este habilita.",
"MessageRemoveAllItemsWarning": "ADVERTENCIA! Esta acción eliminará todos los elementos de la biblioteca de la base de datos incluyendo cualquier actualización o match. Esto no hace nada a sus archivos reales. Esta seguro que desea continuar?",
"MessageRemoveChapter": "Remover capítulos",
"MessageRemoveEpisodes": "Remover {0} episodio(s)",
"MessageRemoveFromPlayerQueue": "Romover la cola de reporduccion",
+77 -46
View File
@@ -97,12 +97,13 @@
"HeaderCover": "Couverture",
"HeaderCurrentDownloads": "Téléchargements en cours",
"HeaderDetails": "Détails",
"HeaderDownloadQueue": "File d'attente de téléchargements",
"HeaderEbookFiles": "Ebook Files",
"HeaderEmail": "E-mails",
"HeaderEmailSettings": "Configuration des e-mails",
"HeaderDownloadQueue": "File dattente de téléchargements",
"HeaderEbookFiles": "Fichier des livres numériques",
"HeaderEmail": "Courriels",
"HeaderEmailSettings": "Configuration des courriels",
"HeaderEpisodes": "Épisodes",
"HeaderEReaderDevices": "Lecteurs d'e-books",
"HeaderEreaderDevices": "Lecteur de livres numériques",
"HeaderEreaderSettings": "Options Ereader",
"HeaderFiles": "Fichiers",
"HeaderFindChapters": "Trouver les chapitres",
"HeaderIgnoredFiles": "Fichiers Ignorés",
@@ -137,6 +138,7 @@
"HeaderRemoveEpisodes": "Suppression de {0} épisodes",
"HeaderRSSFeedGeneral": "Détails de flux RSS",
"HeaderRSSFeedIsOpen": "Le Flux RSS est actif",
"HeaderRSSFeeds": "Flux RSS",
"HeaderSavedMediaProgress": "Progression de la sauvegarde des médias",
"HeaderSchedule": "Programmation",
"HeaderScheduleLibraryScans": "Analyse automatique de la bibliothèque",
@@ -146,7 +148,7 @@
"HeaderSettingsDisplay": "Affichage",
"HeaderSettingsExperimental": "Fonctionnalités expérimentales",
"HeaderSettingsGeneral": "Général",
"HeaderSettingsScanner": "Scanneur",
"HeaderSettingsScanner": "Analyseur",
"HeaderSleepTimer": "Minuterie",
"HeaderStatsLargestItems": "Articles les plus lourd",
"HeaderStatsLongestItems": "Articles les plus long (heures)",
@@ -154,6 +156,7 @@
"HeaderStatsRecentSessions": "Sessions récentes",
"HeaderStatsTop10Authors": "Top 10 Auteurs",
"HeaderStatsTop5Genres": "Top 5 Genres",
"HeaderTableOfContents": "Table des matières",
"HeaderTools": "Outils",
"HeaderUpdateAccount": "Mettre à jour le compte",
"HeaderUpdateAuthor": "Mettre à jour lauteur",
@@ -183,6 +186,7 @@
"LabelAuthors": "Auteurs",
"LabelAutoDownloadEpisodes": "Téléchargement automatique d’épisode",
"LabelBackToUser": "Revenir à lUtilisateur",
"LabelBackupLocation": "Backup Location",
"LabelBackupsEnableAutomaticBackups": "Activer les sauvegardes automatiques",
"LabelBackupsEnableAutomaticBackupsHelp": "Sauvegardes Enregistrées dans /metadata/backups",
"LabelBackupsMaxBackupSize": "Taille maximale de la sauvegarde (en Go)",
@@ -199,11 +203,12 @@
"LabelClosePlayer": "Fermer le lecteur",
"LabelCodec": "Codec",
"LabelCollapseSeries": "Réduire les séries",
"LabelCollection": "Collection",
"LabelCollections": "Collections",
"LabelComplete": "Complet",
"LabelConfirmPassword": "Confirmer le mot de passe",
"LabelContinueListening": "Continuer la lecture",
"LabelContinueReading": "Continue Reading",
"LabelContinueReading": "Continuer la lecture",
"LabelContinueSeries": "Continuer la série",
"LabelCover": "Couverture",
"LabelCoverImageURL": "URL vers limage de couverture",
@@ -220,16 +225,19 @@
"LabelDirectory": "Répertoire",
"LabelDiscFromFilename": "Disque depuis le fichier",
"LabelDiscFromMetadata": "Disque depuis les métadonnées",
"LabelDiscover": "Découvrir",
"LabelDownload": "Téléchargement",
"LabelDownloadNEpisodes": "Télécharger {0} épisode(s)",
"LabelDuration": "Durée",
"LabelDurationFound": "Durée trouvée :",
"LabelEbook": "E-book",
"LabelEbooks": "Ebooks",
"LabelEbook": "Livre numérique",
"LabelEbooks": "Livres numériques",
"LabelEdit": "Modifier",
"LabelEmail": "E-mail",
"LabelEmail": "Courriel",
"LabelEmailSettingsFromAddress": "Expéditeur",
"LabelEmailSettingsSecure": "Sécurisé",
"LabelEmailSettingsSecureHelp": "Si coché, la connexion utilisera TLS lors de la connexion au serveur. Sinon TLS est utilisé si le serveur prend en charge l'extension STARTTLS. Dans la plupart des cas, cochez si vous vous connectez au port 465. Décochez pour le port 587 ou 25. (source: nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsSecureHelp": "Utiliser TLS lors de la connexion au serveur, autrement TLS sera utilisé si le serveur prend en charge lextension STARTTLS. Dans la plupart des cas, actviez loption si vous vous connectez au port 465. Désactivez loption pour utiliser port 587 ou 25. (source: nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Adresse de test",
"LabelEmbeddedCover": "Couverture du livre intégrée",
"LabelEnable": "Activer",
"LabelEnd": "Fin",
@@ -248,12 +256,13 @@
"LabelFinished": "Fini(e)",
"LabelFolder": "Dossier",
"LabelFolders": "Dossiers",
"LabelFontScale": "Taille de la police de caractère",
"LabelFormat": "Format",
"LabelGenre": "Genre",
"LabelGenres": "Genres",
"LabelHardDeleteFile": "Suppression du fichier",
"LabelHasEbook": "Has ebook",
"LabelHasSupplementaryEbook": "Has supplementary ebook",
"LabelHasEbook": "Dispose dun livre numérique",
"LabelHasSupplementaryEbook": "Dispose dun livre numérique supplémentaire",
"LabelHost": "Hôte",
"LabelHour": "Heure",
"LabelIcon": "Icone",
@@ -279,12 +288,16 @@
"LabelLastSeen": "Vu dernièrement",
"LabelLastTime": "Progression",
"LabelLastUpdate": "Dernière mise à jour",
"LabelLayout": "Disposition",
"LabelLayoutSinglePage": "Vue unique",
"LabelLayoutSplitPage": "Vue partagée",
"LabelLess": "Moins",
"LabelLibrariesAccessibleToUser": "Bibliothèque accessible à lutilisateur",
"LabelLibrary": "Bibliothèque",
"LabelLibraryItem": "Article de bibliothèque",
"LabelLibraryName": "Nom de la bibliothèque",
"LabelLimit": "Limite",
"LabelLineSpacing": "Interligne",
"LabelListenAgain": "Écouter à nouveau",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Info",
@@ -309,6 +322,7 @@
"LabelNewPassword": "Nouveau mot de passe",
"LabelNextBackupDate": "Date de la prochaine sauvegarde",
"LabelNextScheduledRun": "Prochain lancement prévu",
"LabelNoEpisodesSelected": "Aucun épisode sélectionné",
"LabelNotes": "Notes",
"LabelNotFinished": "Non terminé(e)",
"LabelNotificationAppriseURL": "URL(s) dApprise",
@@ -343,22 +357,22 @@
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Préfixes à Ignorer (Insensible à la Casse)",
"LabelPreventIndexing": "Empêcher lindexation de votre flux par les bases de données iTunes et Google podcast",
"LabelPrimaryEbook": "Primary ebook",
"LabelPrimaryEbook": "Premier livre numérique",
"LabelProgress": "Progression",
"LabelProvider": "Fournisseur",
"LabelPubDate": "Date de publication",
"LabelPublisher": "Éditeur",
"LabelPublishYear": "Année d’édition",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRead": "Lire",
"LabelReadAgain": "Lire à nouveau",
"LabelReadEbookWithoutProgress": "Lire le livre numérique sans sauvegarder la progression",
"LabelRecentlyAdded": "Derniers ajouts",
"LabelRecentSeries": "Séries récentes",
"LabelRecommended": "Recommandé",
"LabelRegion": "Région",
"LabelReleaseDate": "Date de parution",
"LabelRemoveCover": "Supprimer la couverture",
"LabelRSSFeedCustomOwnerEmail": "E-mail propriétaire personnalisé",
"LabelRSSFeedCustomOwnerEmail": "Courriel du propriétaire personnalisé",
"LabelRSSFeedCustomOwnerName": "Nom propriétaire personnalisé",
"LabelRSSFeedOpen": "Flux RSS ouvert",
"LabelRSSFeedPreventIndexing": "Empêcher lindexation",
@@ -368,43 +382,50 @@
"LabelSearchTitle": "Titre de recherche",
"LabelSearchTitleOrASIN": "Recherche du titre ou ASIN",
"LabelSeason": "Saison",
"LabelSendEbookToDevice": "Envoyer l'e-book à...",
"LabelSelectAllEpisodes": "Sélectionner tous les épisodes",
"LabelSelectEpisodesShowing": "Sélectionner {0} episode(s) en cours",
"LabelSendEbookToDevice": "Envoyer le livre numérique à...",
"LabelSequence": "Séquence",
"LabelSeries": "Séries",
"LabelSeriesName": "Nom de la série",
"LabelSeriesProgress": "Progression de séries",
"LabelSetEbookAsPrimary": "Set as primary",
"LabelSetEbookAsSupplementary": "Set as supplementary",
"LabelSettingsAudiobooksOnly": "Audiobooks only",
"LabelSettingsAudiobooksOnlyHelp": "Enabling this setting will ignore ebook files unless they are inside an audiobook folder in which case they will be set as supplementary ebooks",
"LabelSetEbookAsPrimary": "Définir comme principale",
"LabelSetEbookAsSupplementary": "Définir comme supplémentaire",
"LabelSettingsAudiobooksOnly": "Livres audios seulement",
"LabelSettingsAudiobooksOnlyHelp": "Lactivation de ce paramètre ignorera les fichiers “ ebook ”, à moins quils ne se trouvent dans un dossier de livres audio, auquel cas ils seront définis comme des livres numériques supplémentaires.",
"LabelSettingsBookshelfViewHelp": "Interface skeuomorphique avec une étagère en bois",
"LabelSettingsChromecastSupport": "Support du Chromecast",
"LabelSettingsDateFormat": "Format de date",
"LabelSettingsDisableWatcher": "Désactiver la surveillance",
"LabelSettingsDisableWatcherForLibrary": "Désactiver la surveillance des dossiers pour la bibliothèque",
"LabelSettingsDisableWatcherHelp": "Désactive la mise à jour automatique lorsque les fichiers changent. *Nécessite un redémarrage*",
"LabelSettingsDisableWatcherHelp": "Désactive la mise à jour automatique lorsque des modifications de fichiers sont détectées. *Nécessite le redémarrage du serveur",
"LabelSettingsEnableWatcher": "Activer la veille",
"LabelSettingsEnableWatcherForLibrary": "Activer la surveillance des dossiers pour la bibliothèque",
"LabelSettingsEnableWatcherHelp": "Active la mise à jour automatique automatique lorsque des modifications de fichiers sont détectées. *Nécessite le redémarrage du serveur",
"LabelSettingsExperimentalFeatures": "Fonctionnalités expérimentales",
"LabelSettingsExperimentalFeaturesHelp": "Fonctionnalités en cours de développement sur lesquelles nous attendons votre retour et expérience. Cliquez pour ouvrir la discussion Github.",
"LabelSettingsFindCovers": "Chercher des couvertures de livre",
"LabelSettingsFindCoversHelp": "Si votre livre audio ne possède pas de couverture intégrée ou une image de couverture dans le dossier, lanalyseur tentera de récupérer une couverture.<br>Attention, cela peut augmenter le temps danalyse.",
"LabelSettingsHideSingleBookSeries": "Masquer les séries de livres uniques",
"LabelSettingsHideSingleBookSeriesHelp": "Les séries qui ne comportent quun seul livre seront masquées sur la page de la série et sur les étagères de la page daccueil.",
"LabelSettingsHomePageBookshelfView": "La page daccueil utilise la vue étagère",
"LabelSettingsLibraryBookshelfView": "La bibliothèque utilise la vue étagère",
"LabelSettingsOverdriveMediaMarkers": "Utiliser Overdrive Media Marker pour les chapitres",
"LabelSettingsOverdriveMediaMarkersHelp": "Les fichiers MP3 dOverdrive viennent avec les minutages des chapitres intégrés en métadonnées. Activer ce paramètre utilisera ces minutages pour les chapitres automatiquement.",
"LabelSettingsParseSubtitles": "Analyse des sous-titres",
"LabelSettingsParseSubtitles": "Analyser les sous-titres",
"LabelSettingsParseSubtitlesHelp": "Extrait les sous-titres depuis le dossier du Livre Audio.<br>Les sous-titres doivent être séparés par « - »<br>i.e. « Titre du Livre - Ceci est un sous-titre » aura le sous-titre « Ceci est un sous-titre »",
"LabelSettingsPreferAudioMetadata": "Préférer les Métadonnées audio",
"LabelSettingsPreferAudioMetadata": "Préférer les métadonnées audio",
"LabelSettingsPreferAudioMetadataHelp": "Les méta étiquettes ID3 des fichiers audios seront utilisés à la place des noms de dossier pour les détails du livre audio",
"LabelSettingsPreferMatchedMetadata": "Préférer les Métadonnées par correspondance",
"LabelSettingsPreferMatchedMetadata": "Préférer les métadonnées par correspondance",
"LabelSettingsPreferMatchedMetadataHelp": "Les métadonnées par correspondance écrase les détails de larticle lors dune recherche par correspondance rapide. Par défaut, la recherche par correspondance rapide ne comblera que les éléments manquant.",
"LabelSettingsPreferOPFMetadata": "Préférer les Métadonnées OPF",
"LabelSettingsPreferOPFMetadata": "Préférer les métadonnées OPF",
"LabelSettingsPreferOPFMetadataHelp": "Les fichiers de métadonnées OPF seront utilisés à la place des noms de dossier pour les détails du Livre Audio",
"LabelSettingsSkipMatchingBooksWithASIN": "Ignorer la recherche par correspondance sur les livres ayant déjà un ASIN",
"LabelSettingsSkipMatchingBooksWithISBN": "Ignorer la recherche par correspondance sur les livres ayant déjà un ISBN",
"LabelSettingsSortingIgnorePrefixes": "Ignorer les préfixes lors du tri",
"LabelSettingsSortingIgnorePrefixesHelp": "i.e. pour le préfixe « le », le livre avec pour titre « Le Titre du Livre » sera trié en tant que « Titre du Livre, Le »",
"LabelSettingsSquareBookCovers": "Utiliser des couvertures carrées",
"LabelSettingsSquareBookCoversHelp": "Préférer les couvertures carrées par rapport aux couvertures standardes de 1.6:1.",
"LabelSettingsSquareBookCoversHelp": "Préférer les couvertures carrées par rapport aux couvertures standards de ratio 1.6:1.",
"LabelSettingsStoreCoversWithItem": "Enregistrer la couverture avec les articles",
"LabelSettingsStoreCoversWithItemHelp": "Par défaut, les couvertures sont enregistrées dans /metadata/items. Activer ce paramètre enregistrera les couvertures dans le dossier avec les fichiers de larticle. Seul un fichier nommé « cover » sera conservé.",
"LabelSettingsStoreMetadataWithItem": "Enregistrer les Métadonnées avec les articles",
@@ -413,6 +434,7 @@
"LabelShowAll": "Afficher Tout",
"LabelSize": "Taille",
"LabelSleepTimer": "Minuterie",
"LabelSlug": "Slug",
"LabelStart": "Démarrer",
"LabelStarted": "Démarré",
"LabelStartedAt": "Démarré à",
@@ -437,8 +459,11 @@
"LabelTag": "Étiquette",
"LabelTags": "Étiquettes",
"LabelTagsAccessibleToUser": "Étiquettes accessibles à lutilisateur",
"LabelTagsNotAccessibleToUser": "Tags not Accessible to User",
"LabelTagsNotAccessibleToUser": "Étiquettes non accessibles à lutilisateur",
"LabelTasks": "Tâches en cours",
"LabelTheme": "Thème",
"LabelThemeDark": "Sombre",
"LabelThemeLight": "Clair",
"LabelTimeBase": "Base de temps",
"LabelTimeListened": "Temps d’écoute",
"LabelTimeListenedToday": "Nombres d’écoutes Aujourdhui",
@@ -457,6 +482,7 @@
"LabelTrackFromMetadata": "Piste depuis les métadonnées",
"LabelTracks": "Pistes",
"LabelTracksMultiTrack": "Piste multiple",
"LabelTracksNone": "No tracks",
"LabelTracksSingleTrack": "Piste simple",
"LabelType": "Type",
"LabelUnabridged": "Version intégrale",
@@ -495,20 +521,24 @@
"MessageChapterErrorFirstNotZero": "Le premier capitre doit débuter à 0",
"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 Chapitre Début est situé au début de votre Livre Audio",
"MessageChapterStartIsAfter": "Le premier chapitre est situé au début de votre livre audio",
"MessageCheckingCron": "Vérification du cron…",
"MessageConfirmDeleteBackup": "Êtes-vous sûr de vouloir supprimer la Sauvegarde de {0} ?",
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
"MessageConfirmCloseFeed": "Êtes-vous sûr de vouloir fermer ce flux ?",
"MessageConfirmDeleteBackup": "Êtes-vous sûr de vouloir supprimer la sauvegarde de « {0} » ?",
"MessageConfirmDeleteFile": "Cela supprimera le fichier de votre système de fichiers. Êtes-vous sûr ?",
"MessageConfirmDeleteLibrary": "Êtes-vous sûr de vouloir supprimer définitivement la bibliothèque « {0} » ?",
"MessageConfirmDeleteSession": "Êtes-vous sûr de vouloir supprimer cette session ?",
"MessageConfirmForceReScan": "Êtes-vous sûr de vouloir lancer une Analyse Forcée ?",
"MessageConfirmMarkSeriesFinished": "Êtes-vous sûr de vouloir marquer comme terminé tous les livres de cette série ?",
"MessageConfirmMarkSeriesNotFinished": "Êtes-vous sûr de vouloir marquer comme non terminé tous les livres de cette série ?",
"MessageConfirmForceReScan": "Êtes-vous sûr de vouloir lancer une analyse forcée ?",
"MessageConfirmMarkAllEpisodesFinished": "Êtes-vous sûr de marquer tous les épisodes comme terminés ?",
"MessageConfirmMarkAllEpisodesNotFinished": "Êtes-vous sûr de vouloir marquer tous les épisodes comme non terminés ?",
"MessageConfirmMarkSeriesFinished": "Êtes-vous sûr de vouloir marquer tous les livres de cette série comme terminées ?",
"MessageConfirmMarkSeriesNotFinished": "Êtes-vous sûr de vouloir marquer tous les livres de cette série comme comme non terminés ?",
"MessageConfirmRemoveAllChapters": "Êtes-vous sûr de vouloir supprimer tous les chapitres ?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Êtes-vous sûr de vouloir supprimer la collection « {0} » ?",
"MessageConfirmRemoveEpisode": "Êtes-vous sûr de vouloir supprimer l’épisode « {0} » ?",
"MessageConfirmRemoveEpisodes": "Êtes-vous sûr de vouloir supprimer {0} épisodes ?",
"MessageConfirmRemoveNarrator": "Êtes-vous sûr de vouloir supprimer le narrateur \"{0}\"?",
"MessageConfirmRemoveNarrator": "Êtes-vous sûr de vouloir supprimer le narrateur « {0} » ?",
"MessageConfirmRemovePlaylist": "Êtes-vous sûr de vouloir supprimer la liste de lecture « {0} » ?",
"MessageConfirmRenameGenre": "Êtes-vous sûr de vouloir renommer le genre « {0} » en « {1} » pour tous les articles ?",
"MessageConfirmRenameGenreMergeNote": "Information: Ce genre existe déjà et sera fusionné.",
@@ -516,12 +546,12 @@
"MessageConfirmRenameTag": "Êtes-vous sûr de vouloir renommer l’étiquette « {0} » en « {1} » pour tous les articles ?",
"MessageConfirmRenameTagMergeNote": "Information: Cette étiquette existe déjà et sera fusionnée.",
"MessageConfirmRenameTagWarning": "Attention ! Une étiquette similaire avec une casse différente existe déjà « {0} ».",
"MessageConfirmSendEbookToDevice": "Êtes-vous sûr de vouloir envoyer l'ebook {0} \"{1}\" à l'appareil \"{2}\"?",
"MessageConfirmSendEbookToDevice": "Êtes-vous sûr de vouloir envoyer le livre numérique {0} « {1} » à lappareil « {2} »?",
"MessageDownloadingEpisode": "Téléchargement de l’épisode",
"MessageDragFilesIntoTrackOrder": "Faire glisser les fichiers dans lordre correct",
"MessageEmbedFinished": "Intégration Terminée !",
"MessageEmbedFinished": "Intégration terminée !",
"MessageEpisodesQueuedForDownload": "{0} épisode(s) mis en file pour téléchargement",
"MessageFeedURLWillBe": "lURL du Flux sera {0}",
"MessageFeedURLWillBe": "lURL du flux sera {0}",
"MessageFetching": "Récupération…",
"MessageForceReScanDescription": "Analysera tous les fichiers de nouveau. Les étiquettes ID3 des fichiers audios, fichiers OPF, et les fichiers textes seront analysés comme sils étaient nouveaux.",
"MessageImportantNotice": "Information Importante !",
@@ -532,11 +562,13 @@
"MessageListeningSessionsInTheLastYear": "{0} sessions d’écoute lan dernier",
"MessageLoading": "Chargement…",
"MessageLoadingFolders": "Chargement des dossiers…",
"MessageM4BFailed": "M4B en échec !",
"MessageM4BFinished": "M4B terminé !",
"MessageM4BFailed": "M4B échec",
"MessageM4BFinished": "M4B terminé",
"MessageMapChapterTitles": "Faire correspondre les titres des chapitres aux chapitres existants de votre livre audio sans ajuster lhorodatage.",
"MessageMarkAllEpisodesFinished": "Marquer tous les épisodes terminés",
"MessageMarkAllEpisodesNotFinished": "Marquer tous les épisodes non terminés",
"MessageMarkAsFinished": "Marquer comme terminé",
"MessageMarkAsNotFinished": "Marquer comme non Terminé",
"MessageMarkAsNotFinished": "Marquer comme non terminé",
"MessageMatchBooksDescription": "tentera de faire correspondre les livres de la bibliothèque avec les livres du fournisseur sélectionné pour combler les détails et couverture manquants. N’écrase pas les données existantes.",
"MessageNoAudioTracks": "Aucune piste audio",
"MessageNoAuthors": "Aucun auteur",
@@ -575,7 +607,6 @@
"MessagePlaylistCreateFromCollection": "Créer une liste de lecture depuis la collection",
"MessagePodcastHasNoRSSFeedForMatching": "Le Podcast na pas dURL de flux RSS à utiliser pour la correspondance",
"MessageQuickMatchDescription": "Renseigne les détails manquants ainsi que la couverture avec la première correspondance de « {0} ». N’écrase pas les données présentes à moins que le paramètre « Préférer les Métadonnées par correspondance » soit activé.",
"MessageRemoveAllItemsWarning": "ATTENTION ! Cette action supprimera toute la base de données de la bibliothèque ainsi que les mises à jour ou correspondances qui auraient été effectuées. Cela na aucune incidence sur les fichiers de la bibliothèque. Souhaitez-vous continuer ?",
"MessageRemoveChapter": "Supprimer le chapitre",
"MessageRemoveEpisodes": "Suppression de {0} épisode(s)",
"MessageRemoveFromPlayerQueue": "Supprimer de la liste d’écoute",
@@ -671,8 +702,8 @@
"ToastRemoveItemFromCollectionSuccess": "Article supprimé de la collection",
"ToastRSSFeedCloseFailed": "Échec de la fermeture du flux RSS",
"ToastRSSFeedCloseSuccess": "Flux RSS fermé",
"ToastSendEbookToDeviceFailed": "Échec de l'envoi de l'e-book à l'appareil",
"ToastSendEbookToDeviceSuccess": "E-book envoyé à l'appareil \"{0}\"",
"ToastSendEbookToDeviceFailed": "Échec de lenvoi du livre numérique à lappareil",
"ToastSendEbookToDeviceSuccess": "Livre numérique envoyé à lappareil : {0}",
"ToastSeriesUpdateFailed": "Échec de la mise à jour de la série",
"ToastSeriesUpdateSuccess": "Mise à jour de la série réussie",
"ToastSessionDeleteFailed": "Échec de la suppression de session",
+33 -2
View File
@@ -102,7 +102,8 @@
"HeaderEmail": "Email",
"HeaderEmailSettings": "Email Settings",
"HeaderEpisodes": "Episodes",
"HeaderEReaderDevices": "E-Reader Devices",
"HeaderEreaderDevices": "Ereader Devices",
"HeaderEreaderSettings": "Ereader Settings",
"HeaderFiles": "Files",
"HeaderFindChapters": "Find Chapters",
"HeaderIgnoredFiles": "Ignored Files",
@@ -137,6 +138,7 @@
"HeaderRemoveEpisodes": "Remove {0} Episodes",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "RSS Feed is Open",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderSavedMediaProgress": "Saved Media Progress",
"HeaderSchedule": "Schedule",
"HeaderScheduleLibraryScans": "Schedule Automatic Library Scans",
@@ -154,6 +156,7 @@
"HeaderStatsRecentSessions": "Recent Sessions",
"HeaderStatsTop10Authors": "Top 10 Authors",
"HeaderStatsTop5Genres": "Top 5 Genres",
"HeaderTableOfContents": "Table of Contents",
"HeaderTools": "Tools",
"HeaderUpdateAccount": "Update Account",
"HeaderUpdateAuthor": "Update Author",
@@ -183,6 +186,7 @@
"LabelAuthors": "Authors",
"LabelAutoDownloadEpisodes": "Auto Download Episodes",
"LabelBackToUser": "Back to User",
"LabelBackupLocation": "Backup Location",
"LabelBackupsEnableAutomaticBackups": "Enable automatic backups",
"LabelBackupsEnableAutomaticBackupsHelp": "Backups saved in /metadata/backups",
"LabelBackupsMaxBackupSize": "Maximum backup size (in GB)",
@@ -199,6 +203,7 @@
"LabelClosePlayer": "Close player",
"LabelCodec": "Codec",
"LabelCollapseSeries": "Collapse Series",
"LabelCollection": "Collection",
"LabelCollections": "Collections",
"LabelComplete": "Complete",
"LabelConfirmPassword": "Confirm Password",
@@ -220,7 +225,9 @@
"LabelDirectory": "Directory",
"LabelDiscFromFilename": "Disc from Filename",
"LabelDiscFromMetadata": "Disc from Metadata",
"LabelDiscover": "Discover",
"LabelDownload": "Download",
"LabelDownloadNEpisodes": "Download {0} episodes",
"LabelDuration": "Duration",
"LabelDurationFound": "Duration found:",
"LabelEbook": "Ebook",
@@ -230,6 +237,7 @@
"LabelEmailSettingsFromAddress": "From Address",
"LabelEmailSettingsSecure": "Secure",
"LabelEmailSettingsSecureHelp": "If true the connection will use TLS when connecting to server. If false then TLS is used if server supports the STARTTLS extension. In most cases set this value to true if you are connecting to port 465. For port 587 or 25 keep it false. (from nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Test Address",
"LabelEmbeddedCover": "Embedded Cover",
"LabelEnable": "Enable",
"LabelEnd": "End",
@@ -248,6 +256,7 @@
"LabelFinished": "Finished",
"LabelFolder": "Folder",
"LabelFolders": "Folders",
"LabelFontScale": "Font scale",
"LabelFormat": "Format",
"LabelGenre": "Genre",
"LabelGenres": "Genres",
@@ -279,12 +288,16 @@
"LabelLastSeen": "Last Seen",
"LabelLastTime": "Last Time",
"LabelLastUpdate": "Last Update",
"LabelLayout": "Layout",
"LabelLayoutSinglePage": "Single page",
"LabelLayoutSplitPage": "Split page",
"LabelLess": "Less",
"LabelLibrariesAccessibleToUser": "Libraries Accessible to User",
"LabelLibrary": "Library",
"LabelLibraryItem": "Library Item",
"LabelLibraryName": "Library Name",
"LabelLimit": "Limit",
"LabelLineSpacing": "Line spacing",
"LabelListenAgain": "Listen Again",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Info",
@@ -309,6 +322,7 @@
"LabelNewPassword": "New Password",
"LabelNextBackupDate": "Next backup date",
"LabelNextScheduledRun": "Next scheduled run",
"LabelNoEpisodesSelected": "No episodes selected",
"LabelNotes": "Notes",
"LabelNotFinished": "Not Finished",
"LabelNotificationAppriseURL": "Apprise URL(s)",
@@ -368,6 +382,8 @@
"LabelSearchTitle": "Search Title",
"LabelSearchTitleOrASIN": "Search Title or ASIN",
"LabelSeason": "Season",
"LabelSelectAllEpisodes": "Select all episodes",
"LabelSelectEpisodesShowing": "Select {0} episodes showing",
"LabelSendEbookToDevice": "Send Ebook to...",
"LabelSequence": "Sequence",
"LabelSeries": "Series",
@@ -383,10 +399,15 @@
"LabelSettingsDisableWatcher": "Disable Watcher",
"LabelSettingsDisableWatcherForLibrary": "Disable folder watcher for library",
"LabelSettingsDisableWatcherHelp": "Disables the automatic adding/updating of items when file changes are detected. *Requires server restart",
"LabelSettingsEnableWatcher": "Enable Watcher",
"LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
"LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
"LabelSettingsExperimentalFeatures": "Experimental features",
"LabelSettingsExperimentalFeaturesHelp": "Features in development that could use your feedback and help testing. Click to open github discussion.",
"LabelSettingsFindCovers": "Find covers",
"LabelSettingsFindCoversHelp": "If your audiobook does not have an embedded cover or a cover image inside the folder, the scanner will attempt to find a cover.<br>Note: This will extend scan time",
"LabelSettingsHideSingleBookSeries": "Hide single book series",
"LabelSettingsHideSingleBookSeriesHelp": "Series that have a single book will be hidden from the series page and home page shelves.",
"LabelSettingsHomePageBookshelfView": "Home page use bookshelf view",
"LabelSettingsLibraryBookshelfView": "Library use bookshelf view",
"LabelSettingsOverdriveMediaMarkers": "Use Overdrive Media Markers for chapters",
@@ -413,6 +434,7 @@
"LabelShowAll": "Show All",
"LabelSize": "Size",
"LabelSleepTimer": "Sleep timer",
"LabelSlug": "Slug",
"LabelStart": "Start",
"LabelStarted": "Started",
"LabelStartedAt": "Started At",
@@ -439,6 +461,9 @@
"LabelTagsAccessibleToUser": "Tags Accessible to User",
"LabelTagsNotAccessibleToUser": "Tags not Accessible to User",
"LabelTasks": "Tasks Running",
"LabelTheme": "Theme",
"LabelThemeDark": "Dark",
"LabelThemeLight": "Light",
"LabelTimeBase": "Time Base",
"LabelTimeListened": "Time Listened",
"LabelTimeListenedToday": "Time Listened Today",
@@ -457,6 +482,7 @@
"LabelTrackFromMetadata": "Track from Metadata",
"LabelTracks": "Tracks",
"LabelTracksMultiTrack": "Multi-track",
"LabelTracksNone": "No tracks",
"LabelTracksSingleTrack": "Single-track",
"LabelType": "Type",
"LabelUnabridged": "Unabridged",
@@ -497,14 +523,18 @@
"MessageChapterErrorStartLtPrev": "Invalid start time must be greater than or equal to previous chapter start time",
"MessageChapterStartIsAfter": "Chapter start is after the end of your audiobook",
"MessageCheckingCron": "Checking cron...",
"MessageConfirmCloseFeed": "Are you sure you want to close this feed?",
"MessageConfirmDeleteBackup": "Are you sure you want to delete backup for {0}?",
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
"MessageConfirmDeleteLibrary": "Are you sure you want to permanently delete library \"{0}\"?",
"MessageConfirmDeleteSession": "Are you sure you want to delete this session?",
"MessageConfirmForceReScan": "Are you sure you want to force re-scan?",
"MessageConfirmMarkAllEpisodesFinished": "Are you sure you want to mark all episodes as finished?",
"MessageConfirmMarkAllEpisodesNotFinished": "Are you sure you want to mark all episodes as not finished?",
"MessageConfirmMarkSeriesFinished": "Are you sure you want to mark all books in this series as finished?",
"MessageConfirmMarkSeriesNotFinished": "Are you sure you want to mark all books in this series as not finished?",
"MessageConfirmRemoveAllChapters": "Are you sure you want to remove all chapters?",
"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}\"?",
"MessageConfirmRemoveEpisodes": "Are you sure you want to remove {0} episodes?",
@@ -535,6 +565,8 @@
"MessageM4BFailed": "M4B Failed!",
"MessageM4BFinished": "M4B Finished!",
"MessageMapChapterTitles": "Map chapter titles to your existing audiobook chapters without adjusting timestamps",
"MessageMarkAllEpisodesFinished": "Mark all episodes finished",
"MessageMarkAllEpisodesNotFinished": "Mark all episodes not finished",
"MessageMarkAsFinished": "Mark as Finished",
"MessageMarkAsNotFinished": "Mark as Not Finished",
"MessageMatchBooksDescription": "will attempt to match books in the library with a book from the selected search provider and fill in empty details and cover art. Does not overwrite details.",
@@ -575,7 +607,6 @@
"MessagePlaylistCreateFromCollection": "Create playlist from collection",
"MessagePodcastHasNoRSSFeedForMatching": "Podcast has no RSS feed url to use for matching",
"MessageQuickMatchDescription": "Populate empty item details & cover with first match result from '{0}'. Does not overwrite details unless 'Prefer matched metadata' server setting is enabled.",
"MessageRemoveAllItemsWarning": "WARNING! This action will remove all library items from the database including any updates or matches you have made. This does not do anything to your actual files. Are you sure?",
"MessageRemoveChapter": "Remove chapter",
"MessageRemoveEpisodes": "Remove {0} episode(s)",
"MessageRemoveFromPlayerQueue": "Remove from player queue",
+33 -2
View File
@@ -102,7 +102,8 @@
"HeaderEmail": "Email",
"HeaderEmailSettings": "Email Settings",
"HeaderEpisodes": "Episodes",
"HeaderEReaderDevices": "E-Reader Devices",
"HeaderEreaderDevices": "Ereader Devices",
"HeaderEreaderSettings": "Ereader Settings",
"HeaderFiles": "Files",
"HeaderFindChapters": "Find Chapters",
"HeaderIgnoredFiles": "Ignored Files",
@@ -137,6 +138,7 @@
"HeaderRemoveEpisodes": "Remove {0} Episodes",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "RSS Feed is Open",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderSavedMediaProgress": "Saved Media Progress",
"HeaderSchedule": "Schedule",
"HeaderScheduleLibraryScans": "Schedule Automatic Library Scans",
@@ -154,6 +156,7 @@
"HeaderStatsRecentSessions": "Recent Sessions",
"HeaderStatsTop10Authors": "Top 10 Authors",
"HeaderStatsTop5Genres": "Top 5 Genres",
"HeaderTableOfContents": "Table of Contents",
"HeaderTools": "Tools",
"HeaderUpdateAccount": "Update Account",
"HeaderUpdateAuthor": "Update Author",
@@ -183,6 +186,7 @@
"LabelAuthors": "Authors",
"LabelAutoDownloadEpisodes": "Auto Download Episodes",
"LabelBackToUser": "Back to User",
"LabelBackupLocation": "Backup Location",
"LabelBackupsEnableAutomaticBackups": "Enable automatic backups",
"LabelBackupsEnableAutomaticBackupsHelp": "Backups saved in /metadata/backups",
"LabelBackupsMaxBackupSize": "Maximum backup size (in GB)",
@@ -199,6 +203,7 @@
"LabelClosePlayer": "Close player",
"LabelCodec": "Codec",
"LabelCollapseSeries": "Collapse Series",
"LabelCollection": "Collection",
"LabelCollections": "Collections",
"LabelComplete": "Complete",
"LabelConfirmPassword": "Confirm Password",
@@ -220,7 +225,9 @@
"LabelDirectory": "Directory",
"LabelDiscFromFilename": "Disc from Filename",
"LabelDiscFromMetadata": "Disc from Metadata",
"LabelDiscover": "Discover",
"LabelDownload": "Download",
"LabelDownloadNEpisodes": "Download {0} episodes",
"LabelDuration": "Duration",
"LabelDurationFound": "Duration found:",
"LabelEbook": "Ebook",
@@ -230,6 +237,7 @@
"LabelEmailSettingsFromAddress": "From Address",
"LabelEmailSettingsSecure": "Secure",
"LabelEmailSettingsSecureHelp": "If true the connection will use TLS when connecting to server. If false then TLS is used if server supports the STARTTLS extension. In most cases set this value to true if you are connecting to port 465. For port 587 or 25 keep it false. (from nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Test Address",
"LabelEmbeddedCover": "Embedded Cover",
"LabelEnable": "Enable",
"LabelEnd": "End",
@@ -248,6 +256,7 @@
"LabelFinished": "Finished",
"LabelFolder": "Folder",
"LabelFolders": "Folders",
"LabelFontScale": "Font scale",
"LabelFormat": "Format",
"LabelGenre": "Genre",
"LabelGenres": "Genres",
@@ -279,12 +288,16 @@
"LabelLastSeen": "Last Seen",
"LabelLastTime": "Last Time",
"LabelLastUpdate": "Last Update",
"LabelLayout": "Layout",
"LabelLayoutSinglePage": "Single page",
"LabelLayoutSplitPage": "Split page",
"LabelLess": "Less",
"LabelLibrariesAccessibleToUser": "Libraries Accessible to User",
"LabelLibrary": "Library",
"LabelLibraryItem": "Library Item",
"LabelLibraryName": "Library Name",
"LabelLimit": "Limit",
"LabelLineSpacing": "Line spacing",
"LabelListenAgain": "Listen Again",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Info",
@@ -309,6 +322,7 @@
"LabelNewPassword": "New Password",
"LabelNextBackupDate": "Next backup date",
"LabelNextScheduledRun": "Next scheduled run",
"LabelNoEpisodesSelected": "No episodes selected",
"LabelNotes": "Notes",
"LabelNotFinished": "Not Finished",
"LabelNotificationAppriseURL": "Apprise URL(s)",
@@ -368,6 +382,8 @@
"LabelSearchTitle": "Search Title",
"LabelSearchTitleOrASIN": "Search Title or ASIN",
"LabelSeason": "Season",
"LabelSelectAllEpisodes": "Select all episodes",
"LabelSelectEpisodesShowing": "Select {0} episodes showing",
"LabelSendEbookToDevice": "Send Ebook to...",
"LabelSequence": "Sequence",
"LabelSeries": "Series",
@@ -383,10 +399,15 @@
"LabelSettingsDisableWatcher": "Disable Watcher",
"LabelSettingsDisableWatcherForLibrary": "Disable folder watcher for library",
"LabelSettingsDisableWatcherHelp": "Disables the automatic adding/updating of items when file changes are detected. *Requires server restart",
"LabelSettingsEnableWatcher": "Enable Watcher",
"LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
"LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
"LabelSettingsExperimentalFeatures": "Experimental features",
"LabelSettingsExperimentalFeaturesHelp": "Features in development that could use your feedback and help testing. Click to open github discussion.",
"LabelSettingsFindCovers": "Find covers",
"LabelSettingsFindCoversHelp": "If your audiobook does not have an embedded cover or a cover image inside the folder, the scanner will attempt to find a cover.<br>Note: This will extend scan time",
"LabelSettingsHideSingleBookSeries": "Hide single book series",
"LabelSettingsHideSingleBookSeriesHelp": "Series that have a single book will be hidden from the series page and home page shelves.",
"LabelSettingsHomePageBookshelfView": "Home page use bookshelf view",
"LabelSettingsLibraryBookshelfView": "Library use bookshelf view",
"LabelSettingsOverdriveMediaMarkers": "Use Overdrive Media Markers for chapters",
@@ -413,6 +434,7 @@
"LabelShowAll": "Show All",
"LabelSize": "Size",
"LabelSleepTimer": "Sleep timer",
"LabelSlug": "Slug",
"LabelStart": "Start",
"LabelStarted": "Started",
"LabelStartedAt": "Started At",
@@ -439,6 +461,9 @@
"LabelTagsAccessibleToUser": "Tags Accessible to User",
"LabelTagsNotAccessibleToUser": "Tags not Accessible to User",
"LabelTasks": "Tasks Running",
"LabelTheme": "Theme",
"LabelThemeDark": "Dark",
"LabelThemeLight": "Light",
"LabelTimeBase": "Time Base",
"LabelTimeListened": "Time Listened",
"LabelTimeListenedToday": "Time Listened Today",
@@ -457,6 +482,7 @@
"LabelTrackFromMetadata": "Track from Metadata",
"LabelTracks": "Tracks",
"LabelTracksMultiTrack": "Multi-track",
"LabelTracksNone": "No tracks",
"LabelTracksSingleTrack": "Single-track",
"LabelType": "Type",
"LabelUnabridged": "Unabridged",
@@ -497,14 +523,18 @@
"MessageChapterErrorStartLtPrev": "Invalid start time must be greater than or equal to previous chapter start time",
"MessageChapterStartIsAfter": "Chapter start is after the end of your audiobook",
"MessageCheckingCron": "Checking cron...",
"MessageConfirmCloseFeed": "Are you sure you want to close this feed?",
"MessageConfirmDeleteBackup": "Are you sure you want to delete backup for {0}?",
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
"MessageConfirmDeleteLibrary": "Are you sure you want to permanently delete library \"{0}\"?",
"MessageConfirmDeleteSession": "Are you sure you want to delete this session?",
"MessageConfirmForceReScan": "Are you sure you want to force re-scan?",
"MessageConfirmMarkAllEpisodesFinished": "Are you sure you want to mark all episodes as finished?",
"MessageConfirmMarkAllEpisodesNotFinished": "Are you sure you want to mark all episodes as not finished?",
"MessageConfirmMarkSeriesFinished": "Are you sure you want to mark all books in this series as finished?",
"MessageConfirmMarkSeriesNotFinished": "Are you sure you want to mark all books in this series as not finished?",
"MessageConfirmRemoveAllChapters": "Are you sure you want to remove all chapters?",
"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}\"?",
"MessageConfirmRemoveEpisodes": "Are you sure you want to remove {0} episodes?",
@@ -535,6 +565,8 @@
"MessageM4BFailed": "M4B Failed!",
"MessageM4BFinished": "M4B Finished!",
"MessageMapChapterTitles": "Map chapter titles to your existing audiobook chapters without adjusting timestamps",
"MessageMarkAllEpisodesFinished": "Mark all episodes finished",
"MessageMarkAllEpisodesNotFinished": "Mark all episodes not finished",
"MessageMarkAsFinished": "Mark as Finished",
"MessageMarkAsNotFinished": "Mark as Not Finished",
"MessageMatchBooksDescription": "will attempt to match books in the library with a book from the selected search provider and fill in empty details and cover art. Does not overwrite details.",
@@ -575,7 +607,6 @@
"MessagePlaylistCreateFromCollection": "Create playlist from collection",
"MessagePodcastHasNoRSSFeedForMatching": "Podcast has no RSS feed url to use for matching",
"MessageQuickMatchDescription": "Populate empty item details & cover with first match result from '{0}'. Does not overwrite details unless 'Prefer matched metadata' server setting is enabled.",
"MessageRemoveAllItemsWarning": "WARNING! This action will remove all library items from the database including any updates or matches you have made. This does not do anything to your actual files. Are you sure?",
"MessageRemoveChapter": "Remove chapter",
"MessageRemoveEpisodes": "Remove {0} episode(s)",
"MessageRemoveFromPlayerQueue": "Remove from player queue",
+33 -2
View File
@@ -102,7 +102,8 @@
"HeaderEmail": "Email",
"HeaderEmailSettings": "Email Settings",
"HeaderEpisodes": "Epizode",
"HeaderEReaderDevices": "E-Reader Devices",
"HeaderEreaderDevices": "Ereader Devices",
"HeaderEreaderSettings": "Ereader Settings",
"HeaderFiles": "Datoteke",
"HeaderFindChapters": "Pronađi poglavlja",
"HeaderIgnoredFiles": "Zanemarene datoteke",
@@ -137,6 +138,7 @@
"HeaderRemoveEpisodes": "Ukloni {0} epizoda/-e",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "RSS Feed je otvoren",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderSavedMediaProgress": "Spremljen Media Progress",
"HeaderSchedule": "Schedule",
"HeaderScheduleLibraryScans": "Zakaži automatsko skeniranje biblioteke",
@@ -154,6 +156,7 @@
"HeaderStatsRecentSessions": "Nedavne sesije",
"HeaderStatsTop10Authors": "Top 10 autora",
"HeaderStatsTop5Genres": "Top 5 žanrova",
"HeaderTableOfContents": "Table of Contents",
"HeaderTools": "Alati",
"HeaderUpdateAccount": "Aktualiziraj Korisnički račun",
"HeaderUpdateAuthor": "Aktualiziraj autora",
@@ -183,6 +186,7 @@
"LabelAuthors": "Autori",
"LabelAutoDownloadEpisodes": "Automatski preuzmi epizode",
"LabelBackToUser": "Nazad k korisniku",
"LabelBackupLocation": "Backup Location",
"LabelBackupsEnableAutomaticBackups": "Uključi automatski backup",
"LabelBackupsEnableAutomaticBackupsHelp": "Backups spremljeni u /metadata/backups",
"LabelBackupsMaxBackupSize": "Maksimalna količina backupa (u GB)",
@@ -199,6 +203,7 @@
"LabelClosePlayer": "Close player",
"LabelCodec": "Codec",
"LabelCollapseSeries": "Collapse Series",
"LabelCollection": "Collection",
"LabelCollections": "Kolekcije",
"LabelComplete": "Complete",
"LabelConfirmPassword": "Potvrdi lozinku",
@@ -220,7 +225,9 @@
"LabelDirectory": "Direktorij",
"LabelDiscFromFilename": "CD iz imena datoteke",
"LabelDiscFromMetadata": "CD iz metapodataka",
"LabelDiscover": "Discover",
"LabelDownload": "Preuzmi",
"LabelDownloadNEpisodes": "Download {0} episodes",
"LabelDuration": "Trajanje",
"LabelDurationFound": "Pronađeno trajanje:",
"LabelEbook": "Ebook",
@@ -230,6 +237,7 @@
"LabelEmailSettingsFromAddress": "From Address",
"LabelEmailSettingsSecure": "Secure",
"LabelEmailSettingsSecureHelp": "If true the connection will use TLS when connecting to server. If false then TLS is used if server supports the STARTTLS extension. In most cases set this value to true if you are connecting to port 465. For port 587 or 25 keep it false. (from nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Test Address",
"LabelEmbeddedCover": "Embedded Cover",
"LabelEnable": "Uključi",
"LabelEnd": "Kraj",
@@ -248,6 +256,7 @@
"LabelFinished": "Finished",
"LabelFolder": "Folder",
"LabelFolders": "Folderi",
"LabelFontScale": "Font scale",
"LabelFormat": "Format",
"LabelGenre": "Genre",
"LabelGenres": "Žanrovi",
@@ -279,12 +288,16 @@
"LabelLastSeen": "Zadnje pogledano",
"LabelLastTime": "Prošli put",
"LabelLastUpdate": "Zadnja aktualizacija",
"LabelLayout": "Layout",
"LabelLayoutSinglePage": "Single page",
"LabelLayoutSplitPage": "Split page",
"LabelLess": "Manje",
"LabelLibrariesAccessibleToUser": "Biblioteke pristupačne korisniku",
"LabelLibrary": "Biblioteka",
"LabelLibraryItem": "Stavka biblioteke",
"LabelLibraryName": "Ime biblioteke",
"LabelLimit": "Limit",
"LabelLineSpacing": "Line spacing",
"LabelListenAgain": "Slušaj ponovno",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Info",
@@ -309,6 +322,7 @@
"LabelNewPassword": "Nova lozinka",
"LabelNextBackupDate": "Next backup date",
"LabelNextScheduledRun": "Next scheduled run",
"LabelNoEpisodesSelected": "No episodes selected",
"LabelNotes": "Bilješke",
"LabelNotFinished": "Nedovršeno",
"LabelNotificationAppriseURL": "Apprise URL(s)",
@@ -368,6 +382,8 @@
"LabelSearchTitle": "Traži naslov",
"LabelSearchTitleOrASIN": "Traži naslov ili ASIN",
"LabelSeason": "Sezona",
"LabelSelectAllEpisodes": "Select all episodes",
"LabelSelectEpisodesShowing": "Select {0} episodes showing",
"LabelSendEbookToDevice": "Send Ebook to...",
"LabelSequence": "Sekvenca",
"LabelSeries": "Serije",
@@ -383,10 +399,15 @@
"LabelSettingsDisableWatcher": "Isključi Watchera",
"LabelSettingsDisableWatcherForLibrary": "Isključi folder watchera za biblioteku",
"LabelSettingsDisableWatcherHelp": "Isključi automatsko dodavanje/aktualiziranje stavci ako su promjene prepoznate. *Potreban restart servera",
"LabelSettingsEnableWatcher": "Enable Watcher",
"LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
"LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
"LabelSettingsExperimentalFeatures": "Eksperimentalni features",
"LabelSettingsExperimentalFeaturesHelp": "Features u razvoju trebaju vaš feedback i pomoć pri testiranju. Klikni da odeš to Github discussionsa.",
"LabelSettingsFindCovers": "Pronađi covers",
"LabelSettingsFindCoversHelp": "Ako audiobook nema embedani cover or a cover sliku unutar foldera, skener će probati pronaći cover.<br>Bilješka: Ovo će produžiti trjanje skeniranja",
"LabelSettingsHideSingleBookSeries": "Hide single book series",
"LabelSettingsHideSingleBookSeriesHelp": "Series that have a single book will be hidden from the series page and home page shelves.",
"LabelSettingsHomePageBookshelfView": "Koristi bookshelf pogled za početnu stranicu",
"LabelSettingsLibraryBookshelfView": "Koristi bookshelf pogled za biblioteku",
"LabelSettingsOverdriveMediaMarkers": "Koristi Overdrive Media Markers za poglavlja",
@@ -413,6 +434,7 @@
"LabelShowAll": "Prikaži sve",
"LabelSize": "Veličina",
"LabelSleepTimer": "Sleep timer",
"LabelSlug": "Slug",
"LabelStart": "Pokreni",
"LabelStarted": "Pokrenuto",
"LabelStartedAt": "Pokrenuto",
@@ -439,6 +461,9 @@
"LabelTagsAccessibleToUser": "Tags dostupni korisniku",
"LabelTagsNotAccessibleToUser": "Tags not Accessible to User",
"LabelTasks": "Tasks Running",
"LabelTheme": "Theme",
"LabelThemeDark": "Dark",
"LabelThemeLight": "Light",
"LabelTimeBase": "Time Base",
"LabelTimeListened": "Vremena odslušano",
"LabelTimeListenedToday": "Vremena odslušano danas",
@@ -457,6 +482,7 @@
"LabelTrackFromMetadata": "Track iz metapodataka",
"LabelTracks": "Tracks",
"LabelTracksMultiTrack": "Multi-track",
"LabelTracksNone": "No tracks",
"LabelTracksSingleTrack": "Single-track",
"LabelType": "Tip",
"LabelUnabridged": "Unabridged",
@@ -497,14 +523,18 @@
"MessageChapterErrorStartLtPrev": "Invalid start time must be greater than or equal to previous chapter start time",
"MessageChapterStartIsAfter": "Početak poglavlja je nakon kraja audioknjige.",
"MessageCheckingCron": "Provjeravam cron...",
"MessageConfirmCloseFeed": "Are you sure you want to close this feed?",
"MessageConfirmDeleteBackup": "Jeste li sigurni da želite obrisati backup za {0}?",
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
"MessageConfirmDeleteLibrary": "Jeste li sigurni da želite trajno obrisati biblioteku \"{0}\"?",
"MessageConfirmDeleteSession": "Jeste li sigurni da želite obrisati ovu sesiju?",
"MessageConfirmForceReScan": "Jeste li sigurni da želite ponovno skenirati?",
"MessageConfirmMarkAllEpisodesFinished": "Are you sure you want to mark all episodes as finished?",
"MessageConfirmMarkAllEpisodesNotFinished": "Are you sure you want to mark all episodes as not finished?",
"MessageConfirmMarkSeriesFinished": "Are you sure you want to mark all books in this series as finished?",
"MessageConfirmMarkSeriesNotFinished": "Are you sure you want to mark all books in this series as not finished?",
"MessageConfirmRemoveAllChapters": "Are you sure you want to remove all chapters?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "AJeste li sigurni da želite obrisati kolekciju \"{0}\"?",
"MessageConfirmRemoveEpisode": "Jeste li sigurni da želite obrisati epizodu \"{0}\"?",
"MessageConfirmRemoveEpisodes": "Jeste li sigurni da želite obrisati {0} epizoda/-u?",
@@ -535,6 +565,8 @@
"MessageM4BFailed": "M4B neuspješan!",
"MessageM4BFinished": "M4B završio!",
"MessageMapChapterTitles": "Mapiraj imena poglavlja u postoječa poglavlja bez izmijene timestampova.",
"MessageMarkAllEpisodesFinished": "Mark all episodes finished",
"MessageMarkAllEpisodesNotFinished": "Mark all episodes not finished",
"MessageMarkAsFinished": "Označi kao završeno",
"MessageMarkAsNotFinished": "Označi kao nezavršeno",
"MessageMatchBooksDescription": "će probati matchati knjige iz biblioteke sa knjigom od odabranog poslužitelja i popuniti prazne detalje i cover. Ne briše postojeće detalje.",
@@ -575,7 +607,6 @@
"MessagePlaylistCreateFromCollection": "Create playlist from collection",
"MessagePodcastHasNoRSSFeedForMatching": "Podcast nema RSS feed url za matchanje",
"MessageQuickMatchDescription": "Popuni prazne detalje stavki i cover sa prvim match rezultato iz '{0}'. Ne briše detalje osim ako 'Prefer matched metadata' server postavka nije uključena.",
"MessageRemoveAllItemsWarning": "UPOZORENJE! Ova radnja briše sve stavke iz biblioteke uključujući bilokakve aktualizacije ili matcheve. Ovo ne mjenja vaše lokalne datoteke. Jeste li sigurni?",
"MessageRemoveChapter": "Remove chapter",
"MessageRemoveEpisodes": "ukloni {0} epizoda/-e",
"MessageRemoveFromPlayerQueue": "Remove from player queue",
+70 -39
View File
@@ -55,7 +55,7 @@
"ButtonRemoveAll": "Rimuovi Tutto",
"ButtonRemoveAllLibraryItems": "Rimuovi tutto il contenuto della libreria",
"ButtonRemoveFromContinueListening": "Rimuovi per proseguire l'ascolto",
"ButtonRemoveFromContinueReading": "Remove from Continue Reading",
"ButtonRemoveFromContinueReading": "Rimuovi per proseguire la lettura",
"ButtonRemoveSeriesFromContinueSeries": "Rimuovi la Serie per Continuarla",
"ButtonReScan": "Ri-scansiona",
"ButtonReset": "Reset",
@@ -95,14 +95,15 @@
"HeaderCollection": "Raccolta",
"HeaderCollectionItems": "Elementi della Raccolta",
"HeaderCover": "Cover",
"HeaderCurrentDownloads": "Current Downloads",
"HeaderCurrentDownloads": "Download Correnti",
"HeaderDetails": "Dettagli",
"HeaderDownloadQueue": "Download Queue",
"HeaderEbookFiles": "Ebook Files",
"HeaderEmail": "Email",
"HeaderEmailSettings": "Email Settings",
"HeaderEpisodes": "Episodi",
"HeaderEReaderDevices": "E-Reader Devices",
"HeaderEreaderDevices": "Dispositivo Ereader",
"HeaderEreaderSettings": "Impostazioni Ereader",
"HeaderFiles": "File",
"HeaderFindChapters": "Trova Capitoli",
"HeaderIgnoredFiles": "File Ignorati",
@@ -137,6 +138,7 @@
"HeaderRemoveEpisodes": "Rimuovi {0} Episodi",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "RSS Feed è aperto",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderSavedMediaProgress": "Progressi salvati",
"HeaderSchedule": "Schedula",
"HeaderScheduleLibraryScans": "Schedula la scansione della libreria",
@@ -148,12 +150,13 @@
"HeaderSettingsGeneral": "Generale",
"HeaderSettingsScanner": "Scanner",
"HeaderSleepTimer": "Sveglia",
"HeaderStatsLargestItems": "Largest Items",
"HeaderStatsLargestItems": "Oggetti Grandi",
"HeaderStatsLongestItems": "libri più lunghi (ore)",
"HeaderStatsMinutesListeningChart": "Minuti ascoltati (Ultimi 7 Giorni)",
"HeaderStatsRecentSessions": "Sessioni Recenti",
"HeaderStatsTop10Authors": "Top 10 Autori",
"HeaderStatsTop5Genres": "Top 5 Generi",
"HeaderTableOfContents": "Tabellla dei Contenuti",
"HeaderTools": "Strumenti",
"HeaderUpdateAccount": "Aggiorna Account",
"HeaderUpdateAuthor": "Aggiorna Autore",
@@ -161,13 +164,13 @@
"HeaderUpdateLibrary": "Aggiorna Libreria",
"HeaderUsers": "Utenti",
"HeaderYourStats": "Statistiche Personali",
"LabelAbridged": "Abridged",
"LabelAbridged": "Abbreviato",
"LabelAccountType": "Tipo di Account",
"LabelAccountTypeAdmin": "Admin",
"LabelAccountTypeGuest": "Ospite",
"LabelAccountTypeUser": "Utente",
"LabelActivity": "Attività",
"LabelAdded": "Added",
"LabelAdded": "Aggiunto",
"LabelAddedAt": "Aggiunto il",
"LabelAddToCollection": "Aggiungi alla Raccolta",
"LabelAddToCollectionBatch": "Aggiungi {0} Libri alla Raccolta",
@@ -183,6 +186,7 @@
"LabelAuthors": "Autori",
"LabelAutoDownloadEpisodes": "Auto Download Episodi",
"LabelBackToUser": "Torna a Utenti",
"LabelBackupLocation": "Backup Location",
"LabelBackupsEnableAutomaticBackups": "Abilita backup Automatico",
"LabelBackupsEnableAutomaticBackupsHelp": "I Backup saranno salvati in /metadata/backups",
"LabelBackupsMaxBackupSize": "Dimensione massima backup (in GB)",
@@ -192,18 +196,19 @@
"LabelBitrate": "Bitrate",
"LabelBooks": "Libri",
"LabelChangePassword": "Cambia Password",
"LabelChannels": "Channels",
"LabelChapters": "Chapters",
"LabelChannels": "Canali",
"LabelChapters": "Capitoli",
"LabelChaptersFound": "Capitoli Trovati",
"LabelChapterTitle": "Titoli dei Capitoli",
"LabelClosePlayer": "Chiudi player",
"LabelCodec": "Codec",
"LabelCollapseSeries": "Comprimi Serie",
"LabelCollection": "Collection",
"LabelCollections": "Raccolte",
"LabelComplete": "Completo",
"LabelConfirmPassword": "Conferma Password",
"LabelContinueListening": "Continua ad Ascoltare",
"LabelContinueReading": "Continue Reading",
"LabelContinueReading": "Continua la Lettura",
"LabelContinueSeries": "Continua Serie",
"LabelCover": "Cover",
"LabelCoverImageURL": "Cover Image URL",
@@ -220,23 +225,26 @@
"LabelDirectory": "Elenco",
"LabelDiscFromFilename": "Disco dal nome file",
"LabelDiscFromMetadata": "Disco dal Metadata",
"LabelDiscover": "Discover",
"LabelDownload": "Download",
"LabelDownloadNEpisodes": "Download {0} episodes",
"LabelDuration": "Durata",
"LabelDurationFound": "Durata Trovata:",
"LabelEbook": "Ebook",
"LabelEbooks": "Ebooks",
"LabelEdit": "Modifica",
"LabelEmail": "Email",
"LabelEmailSettingsFromAddress": "From Address",
"LabelEmailSettingsFromAddress": "Da Indirizzo",
"LabelEmailSettingsSecure": "Secure",
"LabelEmailSettingsSecureHelp": "If true the connection will use TLS when connecting to server. If false then TLS is used if server supports the STARTTLS extension. In most cases set this value to true if you are connecting to port 465. For port 587 or 25 keep it false. (from nodemailer.com/smtp/#authentication)",
"LabelEmbeddedCover": "Embedded Cover",
"LabelEmailSettingsSecureHelp": "Se vero, la connessione utilizzerà TLS durante la connessione al server. Se false, viene utilizzato TLS se il server supporta l'estensione STARTTLS. Nella maggior parte dei casi impostare questo valore su true se ci si connette alla porta 465. Per la porta 587 o 25 mantenerlo false. (da nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Test Indirizzo",
"LabelEmbeddedCover": "Cover Integrata",
"LabelEnable": "Abilita",
"LabelEnd": "Fine",
"LabelEpisode": "Episodio",
"LabelEpisodeTitle": "Titolo Episodio",
"LabelEpisodeType": "Tipo Episodio",
"LabelExample": "Example",
"LabelExample": "Esempio",
"LabelExplicit": "Esplicito",
"LabelFeedURL": "Feed URL",
"LabelFile": "File",
@@ -248,12 +256,13 @@
"LabelFinished": "Finita",
"LabelFolder": "Cartella",
"LabelFolders": "Cartelle",
"LabelFormat": "Format",
"LabelFontScale": "Dimensione Font",
"LabelFormat": "Formato",
"LabelGenre": "Genere",
"LabelGenres": "Generi",
"LabelHardDeleteFile": "Elimina Definitivamente",
"LabelHasEbook": "Has ebook",
"LabelHasSupplementaryEbook": "Has supplementary ebook",
"LabelHasEbook": "Un ebook",
"LabelHasSupplementaryEbook": "Un ebook Supplementare",
"LabelHost": "Host",
"LabelHour": "Ora",
"LabelIcon": "Icona",
@@ -270,21 +279,25 @@
"LabelIntervalEveryDay": "Ogni Giorno",
"LabelIntervalEveryHour": "Ogni ora",
"LabelInvalidParts": "Parti Invalide",
"LabelInvert": "Invert",
"LabelInvert": "Inverti",
"LabelItem": "Oggetti",
"LabelLanguage": "Lingua",
"LabelLanguageDefaultServer": "Lingua di Default",
"LabelLastBookAdded": "Last Book Added",
"LabelLastBookUpdated": "Last Book Updated",
"LabelLastBookAdded": "Ultimo Libro Aggiunto",
"LabelLastBookUpdated": "Ultimo Libro Aggiornato",
"LabelLastSeen": "Ultimi Visti",
"LabelLastTime": "Ultima Volta",
"LabelLastUpdate": "Ultimo Aggiornamento",
"LabelLayout": "Layout",
"LabelLayoutSinglePage": "Pagina Singola",
"LabelLayoutSplitPage": "DIvidi Pagina",
"LabelLess": "Poco",
"LabelLibrariesAccessibleToUser": "Librerie Accessibili agli Utenti",
"LabelLibrary": "Libreria",
"LabelLibraryItem": "Elementi della Library",
"LabelLibraryName": "Nome Libreria",
"LabelLimit": "Limiti",
"LabelLineSpacing": "Line spacing",
"LabelListenAgain": "Ri-ascolta",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Info",
@@ -299,7 +312,7 @@
"LabelMissing": "Altro",
"LabelMissingParts": "Parti rimantenti",
"LabelMore": "Molto",
"LabelMoreInfo": "More Info",
"LabelMoreInfo": "Più Info",
"LabelName": "Nome",
"LabelNarrator": "Narratore",
"LabelNarrators": "Narratori",
@@ -309,6 +322,7 @@
"LabelNewPassword": "Nuova Password",
"LabelNextBackupDate": "Data Prossimo Backup",
"LabelNextScheduledRun": "Data prossima esecuzione schedulata",
"LabelNoEpisodesSelected": "Nessun Episodio Selezionato",
"LabelNotes": "Note",
"LabelNotFinished": "Da Completare",
"LabelNotificationAppriseURL": "Apprendi URL(s)",
@@ -339,19 +353,19 @@
"LabelPlayMethod": "Metodo di riproduzione",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastType": "Timo di Podcast",
"LabelPodcastType": "Tipo di Podcast",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Suffissi da ignorare (specificando maiuscole e minuscole)",
"LabelPreventIndexing": "Impedisci che il tuo feed venga indicizzato da iTunes e dalle directory dei podcast di Google",
"LabelPrimaryEbook": "Primary ebook",
"LabelPrimaryEbook": "Libri Principlae",
"LabelProgress": "Cominciati",
"LabelProvider": "Provider",
"LabelPubDate": "Data Pubblicazione",
"LabelPublisher": "Editore",
"LabelPublishYear": "Anno Pubblicazione",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRead": "Leggi",
"LabelReadAgain": "Leggi Ancora",
"LabelReadEbookWithoutProgress": "Leggi l'ebook senza mantenere i progressi",
"LabelRecentlyAdded": "Aggiunti Recentemente",
"LabelRecentSeries": "Serie Recenti",
"LabelRecommended": "Raccomandati",
@@ -368,25 +382,32 @@
"LabelSearchTitle": "Cerca Titolo",
"LabelSearchTitleOrASIN": "Cerca titolo o ASIN",
"LabelSeason": "Stagione",
"LabelSendEbookToDevice": "Send Ebook to...",
"LabelSelectAllEpisodes": "Seleziona tutti gli Episodi",
"LabelSelectEpisodesShowing": "Episodi {0} selezionati ",
"LabelSendEbookToDevice": "Invia ebook a...",
"LabelSequence": "Sequenza",
"LabelSeries": "Serie",
"LabelSeriesName": "Nome Serie",
"LabelSeriesProgress": "Cominciato",
"LabelSetEbookAsPrimary": "Set as primary",
"LabelSetEbookAsSupplementary": "Set as supplementary",
"LabelSettingsAudiobooksOnly": "Audiobooks only",
"LabelSettingsAudiobooksOnlyHelp": "Enabling this setting will ignore ebook files unless they are inside an audiobook folder in which case they will be set as supplementary ebooks",
"LabelSetEbookAsPrimary": "Immposta come Primario",
"LabelSetEbookAsSupplementary": "Imposta come Suplementare",
"LabelSettingsAudiobooksOnly": "Solo Audiolibri",
"LabelSettingsAudiobooksOnlyHelp": "L'abilitazione di questa impostazione ignorerà i file di ebook a meno che non si trovino all'interno di una cartella di audiolibri, nel qual caso verranno impostati come ebook supplementari",
"LabelSettingsBookshelfViewHelp": "Design con scaffali in legno",
"LabelSettingsChromecastSupport": "Supporto a Chromecast",
"LabelSettingsDateFormat": "Formato Data",
"LabelSettingsDisableWatcher": "Disattiva Watcher",
"LabelSettingsDisableWatcherForLibrary": "Disattiva Watcher per le librerie",
"LabelSettingsDisableWatcherHelp": "Disattiva il controllo automatico libri nelle cartelle delle librerie. *Richiede il Riavvio del Server",
"LabelSettingsEnableWatcher": "Enable Watcher",
"LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
"LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
"LabelSettingsExperimentalFeatures": "Opzioni Sperimentali",
"LabelSettingsExperimentalFeaturesHelp": "Funzionalità in fase di sviluppo che potrebbero utilizzare i tuoi feedback e aiutare i test. Fare clic per aprire la discussione github.",
"LabelSettingsFindCovers": "Trova covers",
"LabelSettingsFindCoversHelp": "Se il tuo audiolibro non ha una copertina incorporata o un'immagine di copertina all'interno della cartella, questa funzione tenterà di trovare una copertina.<br>Nota: aumenta il tempo di scansione",
"LabelSettingsHideSingleBookSeries": "Nascondi una singola serie di libri",
"LabelSettingsHideSingleBookSeriesHelp": "Le serie che hanno un solo libro saranno nascoste dalla pagina della serie e dagli scaffali della home page.",
"LabelSettingsHomePageBookshelfView": "Home page con sfondo legno",
"LabelSettingsLibraryBookshelfView": "Libreria con sfondo legno",
"LabelSettingsOverdriveMediaMarkers": "Usa Overdrive Media Markers per i capitoli",
@@ -413,6 +434,7 @@
"LabelShowAll": "Mostra Tutto",
"LabelSize": "Dimensione",
"LabelSleepTimer": "Sleep timer",
"LabelSlug": "Slug",
"LabelStart": "Inizo",
"LabelStarted": "Iniziato",
"LabelStartedAt": "Iniziato al",
@@ -437,8 +459,11 @@
"LabelTag": "Tag",
"LabelTags": "Tags",
"LabelTagsAccessibleToUser": "Tags permessi agli Utenti",
"LabelTagsNotAccessibleToUser": "Tags not Accessible to User",
"LabelTagsNotAccessibleToUser": "Tags non accessibile agli Utenti",
"LabelTasks": "Processi in esecuzione",
"LabelTheme": "Tema",
"LabelThemeDark": "Dark",
"LabelThemeLight": "Light",
"LabelTimeBase": "Time Base",
"LabelTimeListened": "Tempo di Ascolto",
"LabelTimeListenedToday": "Tempo di Ascolto Oggi",
@@ -457,9 +482,10 @@
"LabelTrackFromMetadata": "Traccia da Metadata",
"LabelTracks": "Traccia",
"LabelTracksMultiTrack": "Multi-traccia",
"LabelTracksNone": "No tracks",
"LabelTracksSingleTrack": "Traccia-singola",
"LabelType": "Tipo",
"LabelUnabridged": "Unabridged",
"LabelUnabridged": "Integrale",
"LabelUnknown": "Sconosciuto",
"LabelUpdateCover": "Aggiornamento Cover",
"LabelUpdateCoverHelp": "Consenti la sovrascrittura delle copertine esistenti per i libri selezionati quando viene trovata una corrispondenza",
@@ -497,18 +523,22 @@
"MessageChapterErrorStartLtPrev": "L'ora di inizio non valida deve essere maggiore o uguale all'ora di inizio del capitolo precedente",
"MessageChapterStartIsAfter": "L'inizio del capitolo è dopo la fine del tuo audiolibro",
"MessageCheckingCron": "Controllo cron...",
"MessageConfirmCloseFeed": "Are you sure you want to close this feed?",
"MessageConfirmDeleteBackup": "Sei sicuro di voler eliminare il backup {0}?",
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
"MessageConfirmDeleteFile": "Questo eliminerà il file dal tuo file system. Sei sicuro?",
"MessageConfirmDeleteLibrary": "Sei sicuro di voler eliminare definitivamente la libreria \"{0}\"?",
"MessageConfirmDeleteSession": "Sei sicuro di voler eliminare questa sessione?",
"MessageConfirmForceReScan": "Sei sicuro di voler forzare una nuova scansione?",
"MessageConfirmMarkAllEpisodesFinished": "Sei sicuro di voler contrassegnare tutti gli episodi come finiti?",
"MessageConfirmMarkAllEpisodesNotFinished": "Are you sure you want to mark all episodes as not finished?",
"MessageConfirmMarkSeriesFinished": "Sei sicuro di voler contrassegnare tutti i libri di questa serie come completati?",
"MessageConfirmMarkSeriesNotFinished": "Sei sicuro di voler contrassegnare tutti i libri di questa serie come non completati?",
"MessageConfirmRemoveAllChapters": "Are you sure you want to remove all chapters?",
"MessageConfirmRemoveAllChapters": "Sei sicuro di voler rimuovere tutti i capitoli?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Sei sicuro di voler rimuovere la Raccolta \"{0}\"?",
"MessageConfirmRemoveEpisode": "Sei sicuro di voler rimuovere l'episodio \"{0}\"?",
"MessageConfirmRemoveEpisodes": "Sei sicuro di voler rimuovere {0} episodi?",
"MessageConfirmRemoveNarrator": "Are you sure you want to remove narrator \"{0}\"?",
"MessageConfirmRemoveNarrator": "Sei sicuro di voler rimuovere il narratore \"{0}\"?",
"MessageConfirmRemovePlaylist": "Sei sicuro di voler rimuovere la tua playlist \"{0}\"?",
"MessageConfirmRenameGenre": "Sei sicuro di voler rinominare il genere \"{0}\" in \"{1}\" per tutti gli oggetti?",
"MessageConfirmRenameGenreMergeNote": "Note: Questo genere esiste già quindi verra unito.",
@@ -516,7 +546,7 @@
"MessageConfirmRenameTag": "Sei sicuro di voler rinominare il tag \"{0}\" in \"{1}\" per tutti gli oggetti?",
"MessageConfirmRenameTagMergeNote": "Nota: Questo tag esiste già e verrà unito nel vecchio.",
"MessageConfirmRenameTagWarning": "Avvertimento! Esiste già un tag simile con un nome simile \"{0}\".",
"MessageConfirmSendEbookToDevice": "Are you sure you want to send {0} ebook \"{1}\" to device \"{2}\"?",
"MessageConfirmSendEbookToDevice": "Sei sicuro di voler inviare {0} ebook \"{1}\" al Device \"{2}\"?",
"MessageDownloadingEpisode": "Download episodio in corso",
"MessageDragFilesIntoTrackOrder": "Trascina i file nell'ordine di traccia corretto",
"MessageEmbedFinished": "Incorporamento finito!",
@@ -535,6 +565,8 @@
"MessageM4BFailed": "M4B Fallito!",
"MessageM4BFinished": "M4B Finito!",
"MessageMapChapterTitles": "Associa i titoli dei capitoli ai capitoli dell'audiolibro esistente senza modificare i timestamp",
"MessageMarkAllEpisodesFinished": "Segna tutti gli episodi come finiti",
"MessageMarkAllEpisodesNotFinished": "Segna tutti gli episodi come non finiti",
"MessageMarkAsFinished": "Segna come finito",
"MessageMarkAsNotFinished": "Segna come da completare",
"MessageMatchBooksDescription": "tenterà di abbinare i libri nella biblioteca con un libro del provider di ricerca selezionato e inserirà i dettagli vuoti e la copertina. Non sovrascrive i dettagli.",
@@ -575,7 +607,6 @@
"MessagePlaylistCreateFromCollection": "Crea playlist da una Raccolta",
"MessagePodcastHasNoRSSFeedForMatching": "Podcast non ha l'URL del feed RSS da utilizzare per il match",
"MessageQuickMatchDescription": "Compila i dettagli dell'articolo vuoto e copri con il risultato della prima corrispondenza di '{0}'. Non sovrascrive i dettagli a meno che non sia abilitata l'impostazione del server \"Preferisci metadati corrispondenti\".",
"MessageRemoveAllItemsWarning": "AVVERTIMENTO! Questa azione rimuoverà tutti gli elementi della libreria dal database, inclusi eventuali aggiornamenti o corrispondenze apportate. Questo non fa nulla ai tuoi file effettivi. Sei sicuro?",
"MessageRemoveChapter": "Rimuovi Capitolo",
"MessageRemoveEpisodes": "rimuovi {0} episodio(i)",
"MessageRemoveFromPlayerQueue": "Rimuovi dalla coda di riproduzione",
@@ -671,8 +702,8 @@
"ToastRemoveItemFromCollectionSuccess": "Oggetto rimosso dalla Raccolta",
"ToastRSSFeedCloseFailed": "Errore chiusura RSS feed",
"ToastRSSFeedCloseSuccess": "RSS feed chiuso",
"ToastSendEbookToDeviceFailed": "Failed to Send Ebook to device",
"ToastSendEbookToDeviceSuccess": "Ebook sent to device \"{0}\"",
"ToastSendEbookToDeviceFailed": "Impossibile inviare l'ebook al dispositivo",
"ToastSendEbookToDeviceSuccess": "Ebook inviato al dispositivo \"{0}\"",
"ToastSeriesUpdateFailed": "Aggiornaento Serie Fallito",
"ToastSeriesUpdateSuccess": "Serie Aggornate",
"ToastSessionDeleteFailed": "Errore eliminazione sessione",
+716
View File
@@ -0,0 +1,716 @@
{
"ButtonAdd": "Pridėti",
"ButtonAddChapters": "Pridėti skyrius",
"ButtonAddPodcasts": "Pridėti tinklalaides",
"ButtonAddYourFirstLibrary": "Pridėkite savo pirmąją biblioteką",
"ButtonApply": "Taikyti",
"ButtonApplyChapters": "Taikyti skyrius",
"ButtonAuthors": "Autoriai",
"ButtonBrowseForFolder": "Naršyti aplanko",
"ButtonCancel": "Atšaukti",
"ButtonCancelEncode": "Atšaukti kodavimą",
"ButtonChangeRootPassword": "Keisti root slaptažodį",
"ButtonCheckAndDownloadNewEpisodes": "Patikrinti ir parsiųsti naujus epizodus",
"ButtonChooseAFolder": "Pasirinkite aplanką",
"ButtonChooseFiles": "Pasirinkite failus",
"ButtonClearFilter": "Valyti filtrą",
"ButtonCloseFeed": "Uždaryti srautą",
"ButtonCollections": "Kolekcijos",
"ButtonConfigureScanner": "Konfigūruoti skenerį",
"ButtonCreate": "Kurti",
"ButtonCreateBackup": "Kurti atsarginę kopiją",
"ButtonDelete": "Ištrinti",
"ButtonDownloadQueue": "Parsisiuntimų eilė",
"ButtonEdit": "Redaguoti",
"ButtonEditChapters": "Redaguoti skyrius",
"ButtonEditPodcast": "Redaguoti tinklalaidę",
"ButtonForceReScan": "Priverstinai nuskaityti iš naujo",
"ButtonFullPath": "Visas kelias",
"ButtonHide": "Slėpti",
"ButtonHome": "Pradžia",
"ButtonIssues": "Problemos",
"ButtonLatest": "Naujausias",
"ButtonLibrary": "Biblioteka",
"ButtonLogout": "Atsijungti",
"ButtonLookup": "Ieškoti",
"ButtonManageTracks": "Tvarkyti takelius",
"ButtonMapChapterTitles": "Suderinti skyrių pavadinimus",
"ButtonMatchAllAuthors": "Pritaikyti visus autorius",
"ButtonMatchBooks": "Pritaikyti knygas",
"ButtonNevermind": "Nesvarbu",
"ButtonOk": "Ok",
"ButtonOpenFeed": "Atidaryti srautą",
"ButtonOpenManager": "Atidaryti tvarkyklę",
"ButtonPlay": "Groti",
"ButtonPlaying": "Grojama",
"ButtonPlaylists": "Grojaraščiai",
"ButtonPurgeAllCache": "Valyti visą saugyklą",
"ButtonPurgeItemsCache": "Valyti elementų saugyklą",
"ButtonPurgeMediaProgress": "Valyti medijos progresą",
"ButtonQueueAddItem": "Pridėti į eilę",
"ButtonQueueRemoveItem": "Pašalinti iš eilės",
"ButtonQuickMatch": "Greitas pritaikymas",
"ButtonRead": "Skaityti",
"ButtonRemove": "Pašalinti",
"ButtonRemoveAll": "Pašalinti viską",
"ButtonRemoveAllLibraryItems": "Pašalinti visus bibliotekos elementus",
"ButtonRemoveFromContinueListening": "Pašalinti iš Tęsti Klausimą",
"ButtonRemoveFromContinueReading": "Pašalinti iš Tęsti Skaitymą",
"ButtonRemoveSeriesFromContinueSeries": "Pašalinti seriją iš Tęsti Seriją",
"ButtonReScan": "Iš naujo nuskaityti",
"ButtonReset": "Atstatyti",
"ButtonRestore": "Atkurti",
"ButtonSave": "Išsaugoti",
"ButtonSaveAndClose": "Išsaugoti ir uždaryti",
"ButtonSaveTracklist": "Išsaugoti takelių sąrašą",
"ButtonScan": "Nuskaityti",
"ButtonScanLibrary": "Nuskaityti biblioteką",
"ButtonSearch": "Ieškoti",
"ButtonSelectFolderPath": "Pasirinkti aplanko kelią",
"ButtonSeries": "Serijos",
"ButtonSetChaptersFromTracks": "Nustatyti skyrius iš takelių",
"ButtonShiftTimes": "Perstumti laikus",
"ButtonShow": "Rodyti",
"ButtonStartM4BEncode": "Pradėti M4B kodavimą",
"ButtonStartMetadataEmbed": "Pradėti metaduomenų įterpimą",
"ButtonSubmit": "Pateikti",
"ButtonTest": "Testuoti",
"ButtonUpload": "Įkelti",
"ButtonUploadBackup": "Įkelti atsarginę kopiją",
"ButtonUploadCover": "Įkelti viršelį",
"ButtonUploadOPMLFile": "Įkelti OPML failą",
"ButtonUserDelete": "Ištrinti naudotoją {0}",
"ButtonUserEdit": "Redaguoti naudotoją {0}",
"ButtonViewAll": "Peržiūrėti visus",
"ButtonYes": "Taip",
"HeaderAccount": "Paskyra",
"HeaderAdvanced": "Papildomi",
"HeaderAppriseNotificationSettings": "Apprise pranešimo nustatymai",
"HeaderAudiobookTools": "Audioknygų failų valdymo įrankiai",
"HeaderAudioTracks": "Garso takeliai",
"HeaderBackups": "Atsarginės kopijos",
"HeaderChangePassword": "Pakeisti slaptažodį",
"HeaderChapters": "Skyriai",
"HeaderChooseAFolder": "Pasirinkti aplanką",
"HeaderCollection": "Kolekcija",
"HeaderCollectionItems": "Kolekcijos elementai",
"HeaderCover": "Viršelis",
"HeaderCurrentDownloads": "Dabartiniai parsisiuntimai",
"HeaderDetails": "Detalės",
"HeaderDownloadQueue": "Parsisiuntimo eilė",
"HeaderEbookFiles": "Eknygos failai",
"HeaderEmail": "El. paštas",
"HeaderEmailSettings": "El. pašto nustatymai",
"HeaderEpisodes": "Epizodai",
"HeaderEreaderDevices": "Elektroniniai skaitytuvai",
"HeaderEreaderSettings": "Elektroninių skaitytuvų nustatymai",
"HeaderFiles": "Failai",
"HeaderFindChapters": "Rasti skyrius",
"HeaderIgnoredFiles": "Ignoruojami failai",
"HeaderItemFiles": "Elemento failai",
"HeaderItemMetadataUtils": "Elemento metaduomenų įrankiai",
"HeaderLastListeningSession": "Paskutinė klausymosi sesija",
"HeaderLatestEpisodes": "Naujausi epizodai",
"HeaderLibraries": "Bibliotekos",
"HeaderLibraryFiles": "Bibliotekos failai",
"HeaderLibraryStats": "Bibliotekos statistika",
"HeaderListeningSessions": "Klausymosi sesijos",
"HeaderListeningStats": "Klausymosi statistika",
"HeaderLogin": "Prisijungti",
"HeaderLogs": "Žurnalai",
"HeaderManageGenres": "Tvarkyti žanrus",
"HeaderManageTags": "Tvarkyti žymas",
"HeaderMapDetails": "Susieti detales",
"HeaderMatch": "Atitaikyti",
"HeaderMetadataToEmbed": "Metaduomenys įterpimui",
"HeaderNewAccount": "Nauja paskyra",
"HeaderNewLibrary": "Nauja biblioteka",
"HeaderNotifications": "Pranešimai",
"HeaderOpenRSSFeed": "Atidaryti RSS srautą",
"HeaderOtherFiles": "Kiti failai",
"HeaderPermissions": "Leidimai",
"HeaderPlayerQueue": "Grotuvo eilė",
"HeaderPlaylist": "Grojaraštis",
"HeaderPlaylistItems": "Grojaraščio elementai",
"HeaderPodcastsToAdd": "Pridėti tinklalaides",
"HeaderPreviewCover": "Peržiūrėti viršelį",
"HeaderRemoveEpisode": "Pašalinti epizodą",
"HeaderRemoveEpisodes": "Pašalinti {0} epizodus",
"HeaderRSSFeedGeneral": "RSS informacija",
"HeaderRSSFeedIsOpen": "RSS srautas yra atidarytas",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderSavedMediaProgress": "Išsaugota medijos pažanga",
"HeaderSchedule": "Tvarkaraštis",
"HeaderScheduleLibraryScans": "Nustatyti bibliotekų nuskaitymo tvarkaraštį",
"HeaderSession": "Sesija",
"HeaderSetBackupSchedule": "Nustatyti atsarginių kopijų tvarkaraštį",
"HeaderSettings": "Nustatymai",
"HeaderSettingsDisplay": "Rodymas",
"HeaderSettingsExperimental": "Eksperimentinės funkcijos",
"HeaderSettingsGeneral": "Bendra",
"HeaderSettingsScanner": "Skaitytuvas",
"HeaderSleepTimer": "Miego laikmatis",
"HeaderStatsLargestItems": "Didžiausi elementai",
"HeaderStatsLongestItems": "Ilgiausi elementai (val.)",
"HeaderStatsMinutesListeningChart": "Klausymo minutės (paskutinės 7 dienos)",
"HeaderStatsRecentSessions": "Naujausios sesijos",
"HeaderStatsTop10Authors": "Top 10 autorių",
"HeaderStatsTop5Genres": "Top 5 žanrai",
"HeaderTableOfContents": "Turinys",
"HeaderTools": "Įrankiai",
"HeaderUpdateAccount": "Atnaujinti paskyrą",
"HeaderUpdateAuthor": "Atnaujinti autorių",
"HeaderUpdateDetails": "Atnaujinti informaciją",
"HeaderUpdateLibrary": "Atnaujinti biblioteką",
"HeaderUsers": "Naudotojai",
"HeaderYourStats": "Jūsų statistika",
"LabelAbridged": "Santrauka",
"LabelAccountType": "Paskyros tipas",
"LabelAccountTypeAdmin": "Administratorius",
"LabelAccountTypeGuest": "Svečias",
"LabelAccountTypeUser": "Naudotojas",
"LabelActivity": "Veikla",
"LabelAdded": "Pridėta",
"LabelAddedAt": "Pridėta {0}",
"LabelAddToCollection": "Pridėti į kolekciją",
"LabelAddToCollectionBatch": "Pridėti {0} knygas į kolekciją",
"LabelAddToPlaylist": "Pridėti į grojaraštį",
"LabelAddToPlaylistBatch": "Pridėti {0} elementus į grojaraštį",
"LabelAll": "Visi",
"LabelAllUsers": "Visi naudotojai",
"LabelAlreadyInYourLibrary": "Jau yra jūsų bibliotekoje",
"LabelAppend": "Pridėti",
"LabelAuthor": "Autorius",
"LabelAuthorFirstLast": "Autorius (Vardas Pavardė)",
"LabelAuthorLastFirst": "Autorius (Pavardė, Vardas)",
"LabelAuthors": "Autoriai",
"LabelAutoDownloadEpisodes": "Automatiškai atsisiųsti epizodus",
"LabelBackToUser": "Grįžti į naudotoją",
"LabelBackupLocation": "Backup Location",
"LabelBackupsEnableAutomaticBackups": "Įjungti automatinį atsarginių kopijų kūrimą",
"LabelBackupsEnableAutomaticBackupsHelp": "Atsarginės kopijos bus išsaugotos /metadata/backups aplanke",
"LabelBackupsMaxBackupSize": "Maksimalus atsarginių kopijų dydis (GB)",
"LabelBackupsMaxBackupSizeHelp": "Jei konfigūruotas dydis viršijamas, atsarginės kopijos nebus sukurtos, kad būtų išvengta klaidingų konfigūracijų.",
"LabelBackupsNumberToKeep": "Laikytinų atsarginių kopijų skaičius",
"LabelBackupsNumberToKeepHelp": "Tik viena atsarginė kopija bus pašalinta vienu metu, todėl jei jau turite daugiau atsarginių kopijų nei nurodyta, turite jas pašalinti rankiniu būdu.",
"LabelBitrate": "Bitų sparta",
"LabelBooks": "Knygos",
"LabelChangePassword": "Pakeisti slaptažodį",
"LabelChannels": "Kanalai",
"LabelChapters": "Skyriai",
"LabelChaptersFound": "rasti skyriai",
"LabelChapterTitle": "Skyriaus pavadinimas",
"LabelClosePlayer": "Uždaryti grotuvą",
"LabelCodec": "Kodekas",
"LabelCollapseSeries": "Suskleisti seriją",
"LabelCollection": "Collection",
"LabelCollections": "Kolekcijos",
"LabelComplete": "Baigta",
"LabelConfirmPassword": "Patvirtinkite slaptažodį",
"LabelContinueListening": "Tęsti klausymąsi",
"LabelContinueReading": "Tęsti skaitymą",
"LabelContinueSeries": "Tęsti seriją",
"LabelCover": "Viršelis",
"LabelCoverImageURL": "Viršelio paveikslėlio URL",
"LabelCreatedAt": "Sukurta",
"LabelCronExpression": "Cron išraiška",
"LabelCurrent": "Dabartinė",
"LabelCurrently": "Šiuo metu:",
"LabelCustomCronExpression": "Nestandartinė Cron išraiška:",
"LabelDatetime": "Data ir laikas",
"LabelDescription": "Aprašymas",
"LabelDeselectAll": "Išvalyti pasirinktus",
"LabelDevice": "Įrenginys",
"LabelDeviceInfo": "Įrenginio informacija",
"LabelDirectory": "Katalogas",
"LabelDiscFromFilename": "Diskas pagal failo pavadinimą",
"LabelDiscFromMetadata": "Diskas pagal metaduomenis",
"LabelDiscover": "Discover",
"LabelDownload": "Atsisiųsti",
"LabelDownloadNEpisodes": "Atsisiųsti {0} epizodų",
"LabelDuration": "Trukmė",
"LabelDurationFound": "Rasta trukmė:",
"LabelEbook": "Elektroninė knyga",
"LabelEbooks": "Elektroninės knygos",
"LabelEdit": "Redaguoti",
"LabelEmail": "El. paštas",
"LabelEmailSettingsFromAddress": "Siuntėjo adresas",
"LabelEmailSettingsSecure": "Apsaugota",
"LabelEmailSettingsSecureHelp": "Jei ši reikšmė yra \"true\", ryšys naudos TLS protokolą. Jei \"false\", TLS bus naudojamas tik tada, jei serveris palaiko STARTTLS plėtinį. Daugumos atveju, jei jungiamasi prie 465 prievado, šią reikšmę turėtumėte nustatyti kaip \"true\". Jei jungiamasi prie 587 arba 25 prievado, turi būti nustatyta \"false\". (iš nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Testinis adresas",
"LabelEmbeddedCover": "Įterptas viršelis",
"LabelEnable": "Įjungti",
"LabelEnd": "Pabaiga",
"LabelEpisode": "Epizodas",
"LabelEpisodeTitle": "Epizodo pavadinimas",
"LabelEpisodeType": "Epizodo tipas",
"LabelExample": "Pavyzdys",
"LabelExplicit": "Suaugusiems",
"LabelFeedURL": "Srauto URL",
"LabelFile": "Failas",
"LabelFileBirthtime": "Failo kūrimo laikas",
"LabelFileModified": "Failo keitimo laikas",
"LabelFilename": "Failo pavadinimas",
"LabelFilterByUser": "Filtruoti pagal naudotoją",
"LabelFindEpisodes": "Rasti epizodus",
"LabelFinished": "Baigta",
"LabelFolder": "Aplankas",
"LabelFolders": "Aplankai",
"LabelFontScale": "Šrifto mastelis",
"LabelFormat": "Formatas",
"LabelGenre": "Žanras",
"LabelGenres": "Žanrai",
"LabelHardDeleteFile": "Galutinai ištrinti failą",
"LabelHasEbook": "Turi e-knygą",
"LabelHasSupplementaryEbook": "Turi papildomą e-knygą",
"LabelHost": "Serveris",
"LabelHour": "Valanda",
"LabelIcon": "Piktograma",
"LabelIncludeInTracklist": "Įtraukti į takelių sąrašą",
"LabelIncomplete": "Nebaigta",
"LabelInProgress": "Vyksta",
"LabelInterval": "Intervalas",
"LabelIntervalCustomDailyWeekly": "Pasirinktinis kasdieninės/savaitinės periodiškumas",
"LabelIntervalEvery12Hours": "Kas 12 valandų",
"LabelIntervalEvery15Minutes": "Kas 15 minučių",
"LabelIntervalEvery2Hours": "Kas 2 valandas",
"LabelIntervalEvery30Minutes": "Kas 30 minučių",
"LabelIntervalEvery6Hours": "Kas 6 valandas",
"LabelIntervalEveryDay": "Kasdien",
"LabelIntervalEveryHour": "Kiekvieną valandą",
"LabelInvalidParts": "Netinkamos dalys",
"LabelInvert": "Apversti",
"LabelItem": "Elementas",
"LabelLanguage": "Kalba",
"LabelLanguageDefaultServer": "Numatytoji serverio kalba",
"LabelLastBookAdded": "Paskutinė pridėta knyga",
"LabelLastBookUpdated": "Paskutinė atnaujinta knyga",
"LabelLastSeen": "Paskutinį kartą matyta",
"LabelLastTime": "Paskutinį kartą",
"LabelLastUpdate": "Paskutinė atnaujinimo data",
"LabelLayout": "Išdėstymas",
"LabelLayoutSinglePage": "Vieno puslapio",
"LabelLayoutSplitPage": "Padalinto puslapio",
"LabelLess": "Mažiau",
"LabelLibrariesAccessibleToUser": "Naudotojui pasiekiamos bibliotekos",
"LabelLibrary": "Biblioteka",
"LabelLibraryItem": "Bibliotekos elementas",
"LabelLibraryName": "Bibliotekos pavadinimas",
"LabelLimit": "Limitas",
"LabelLineSpacing": "Tarpas tarp eilučių",
"LabelListenAgain": "Klausytis iš naujo",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Info",
"LabelLogLevelWarn": "Warn",
"LabelLookForNewEpisodesAfterDate": "Ieškoti naujų epizodų po šios datos",
"LabelMediaPlayer": "Grotuvas",
"LabelMediaType": "Medijos tipas",
"LabelMetadataProvider": "Metaduomenų tiekėjas",
"LabelMetaTag": "Meta žymė",
"LabelMetaTags": "Meta žymos",
"LabelMinute": "Minutė",
"LabelMissing": "Trūksta",
"LabelMissingParts": "Trūkstamos dalys",
"LabelMore": "Daugiau",
"LabelMoreInfo": "Daugiau informacijos",
"LabelName": "Pavadinimas",
"LabelNarrator": "Skaitytojas",
"LabelNarrators": "Skaitytojai",
"LabelNew": "Nauja",
"LabelNewestAuthors": "Naujausi autoriai",
"LabelNewestEpisodes": "Naujausi epizodai",
"LabelNewPassword": "Naujas slaptažodis",
"LabelNextBackupDate": "Kitos atsarginės kopijos data",
"LabelNextScheduledRun": "Kito planuoto vykdymo data",
"LabelNoEpisodesSelected": "Nepasirinkti jokie epizodai",
"LabelNotes": "Užrašai",
"LabelNotFinished": "Nebaigta",
"LabelNotificationAppriseURL": "Pranešimo (Apprise) URL",
"LabelNotificationAvailableVariables": "Galimi kintamieji",
"LabelNotificationBodyTemplate": "Turinio šablonas",
"LabelNotificationEvent": "Pranešimo įvykis",
"LabelNotificationsMaxFailedAttempts": "Maksimalus nesėkmingų bandymų skaičius",
"LabelNotificationsMaxFailedAttemptsHelp": "Pranešimai bus išjungti, jei nepavyks jų išsiųsti nurodytą kartų",
"LabelNotificationsMaxQueueSize": "Maksimalus pranešimų eilių dydis",
"LabelNotificationsMaxQueueSizeHelp": "Įvykiai yra apriboti vienu įvykiu per sekundę. Įvykiai bus ignoruojami, jei eilė yra maksimalaus dydžio. Tai apsaugo nuo pranešimų šlamšto.",
"LabelNotificationTitleTemplate": "Pavadinimo šablonas",
"LabelNotStarted": "Nepasileista",
"LabelNumberOfBooks": "Knygų skaičius",
"LabelNumberOfEpisodes": "Epizodų skaičius",
"LabelOpenRSSFeed": "Atidaryti RSS srautą",
"LabelOverwrite": "Perrašyti",
"LabelPassword": "Slaptažodis",
"LabelPath": "Kelias",
"LabelPermissionsAccessAllLibraries": "Gali pasiekti visas bibliotekas",
"LabelPermissionsAccessAllTags": "Gali pasiekti visas žymes",
"LabelPermissionsAccessExplicitContent": "Gali pasiekti turinį suaugusiems",
"LabelPermissionsDelete": "Gali trinti",
"LabelPermissionsDownload": "Gali atsisiųsti",
"LabelPermissionsUpdate": "Gali atnaujinti",
"LabelPermissionsUpload": "Gali įkelti",
"LabelPhotoPathURL": "Nuotraukos kelias/URL",
"LabelPlaylists": "Grojaraščiai",
"LabelPlayMethod": "Grojimo metodas",
"LabelPodcast": "Tinklalaidė",
"LabelPodcasts": "Tinklalaidės",
"LabelPodcastType": "Tinklalaidės tipas",
"LabelPort": "Prievadas",
"LabelPrefixesToIgnore": "Ignoruojami priešdėliai (didžiosios/mažosios nesvarbu)",
"LabelPreventIndexing": "Neleisti indeksuoti jūsų srauto „iTunes“ ir Google podcast kataloguose",
"LabelPrimaryEbook": "Pagrindinė e-knyga",
"LabelProgress": "Progresas",
"LabelProvider": "Tiekėjas",
"LabelPubDate": "Publikavimo data",
"LabelPublisher": "Leidėjas",
"LabelPublishYear": "Leidimo metai",
"LabelRead": "Skaityta",
"LabelReadAgain": "Skaityti dar kartą",
"LabelReadEbookWithoutProgress": "Skaityti e-knygą be pažangos saugojimo",
"LabelRecentlyAdded": "Neseniai pridėta",
"LabelRecentSeries": "Naujausios serijos",
"LabelRecommended": "Rekomenduojama",
"LabelRegion": "Regionas",
"LabelReleaseDate": "Išleidimo data",
"LabelRemoveCover": "Pašalinti viršelį",
"LabelRSSFeedCustomOwnerEmail": "Pasirinktinis savininko el. paštas",
"LabelRSSFeedCustomOwnerName": "Pasirinktinis savininko vardas",
"LabelRSSFeedOpen": "Atidarytas RSS srautas",
"LabelRSSFeedPreventIndexing": "Neleisti indeksuoti",
"LabelRSSFeedSlug": "RSS srauto identifikatorius",
"LabelRSSFeedURL": "RSS srauto URL",
"LabelSearchTerm": "Paieškos žodis",
"LabelSearchTitle": "Ieškoti pavadinimo",
"LabelSearchTitleOrASIN": "Ieškoti pavadinimo arba ASIN",
"LabelSeason": "Sezonas",
"LabelSelectAllEpisodes": "Pažymėti visus epizodus",
"LabelSelectEpisodesShowing": "Pažymėti {0} rodomus epizodus",
"LabelSendEbookToDevice": "Siųsti e-knygą į...",
"LabelSequence": "Seka",
"LabelSeries": "Serija",
"LabelSeriesName": "Serijos pavadinimas",
"LabelSeriesProgress": "Serijos progresas",
"LabelSetEbookAsPrimary": "Nustatyti kaip pagrindinę",
"LabelSetEbookAsSupplementary": "Nustatyti kaip papildomą",
"LabelSettingsAudiobooksOnly": "Tik garso knygos",
"LabelSettingsAudiobooksOnlyHelp": "Įjungus šią parinktį, e-knygų failai bus ignoruojami, nebent jie būtų audioknygų aplankuose, kurie tada būtų rodomi kaip papildomos e-knygos",
"LabelSettingsBookshelfViewHelp": "Knygų lentynos dizainas su medinėmis lentynomis",
"LabelSettingsChromecastSupport": "„Chromecast“ palaikymas",
"LabelSettingsDateFormat": "Datos formatas",
"LabelSettingsDisableWatcher": "Išjungti stebėtoją",
"LabelSettingsDisableWatcherForLibrary": "Išjungti aplankų stebėtoją bibliotekai",
"LabelSettingsDisableWatcherHelp": "Išjungia automatinį elementų pridėjimą/atnaujinimą, jei pastebėti failų pokyčiai. *Reikalingas serverio paleidimas iš naujo",
"LabelSettingsEnableWatcher": "Enable Watcher",
"LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
"LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
"LabelSettingsExperimentalFeatures": "Eksperimentiniai funkcionalumai",
"LabelSettingsExperimentalFeaturesHelp": "Funkcijos, kurios yra kuriamos ir laukiami jūsų komentarai. Spustelėkite, kad atidarytumėte „GitHub“ diskusiją.",
"LabelSettingsFindCovers": "Rasti viršelius",
"LabelSettingsFindCoversHelp": "Jei jūsų audioknyga neturi įterpto viršelio arba viršelio paveikslėlio aplanko, skeneris bandys rasti viršelį.<br>Pastaba: Tai padidins skenavimo trukmę.",
"LabelSettingsHideSingleBookSeries": "Slėpti serijas, turinčias tik vieną knygą",
"LabelSettingsHideSingleBookSeriesHelp": "Serijos, turinčios tik vieną knygą, bus paslėptos nuo serijų puslapio ir pagrindinio puslapio lentynų.",
"LabelSettingsHomePageBookshelfView": "Naudoti pagrindinio puslapio knygų lentynų vaizdą",
"LabelSettingsLibraryBookshelfView": "Naudoti bibliotekos knygų lentynų vaizdą",
"LabelSettingsOverdriveMediaMarkers": "Naudoti Overdrive žymeklius skyriams",
"LabelSettingsOverdriveMediaMarkersHelp": "MP3 failai iš Overdrive turi įterptus skyrių laikus kaip papildomą metaduomenį. Įjungus šią funkciją, skyrių laikai bus automatiškai naudojami.",
"LabelSettingsParseSubtitles": "Analizuoti subtitrus",
"LabelSettingsParseSubtitlesHelp": "Išskleisti subtitrus iš audioknygos aplanko pavadinimų.<br>Subtitrai turi būti atskirti brūkšniu \"-\"<br>pavyzdžiui, \"Knygos pavadinimas - Čia yra subtitrai\" turi subtitrą \"Čia yra subtitrai\"",
"LabelSettingsPreferAudioMetadata": "Pirmenybė failo metaduomenis",
"LabelSettingsPreferAudioMetadataHelp": "Garso failo ID3 metaduomenys bus naudojami knygos informacijai (vietoj aplankų pavadinimų)",
"LabelSettingsPreferMatchedMetadata": "Pirmenybė atitaikytiems metaduomenis",
"LabelSettingsPreferMatchedMetadataHelp": "Atitaikyti duomenys pakeis elementų informaciją naudojant Greitą atitikimą. Pagal nutylėjimą Greitas atitaikymas užpildys tik trūkstamas detales.",
"LabelSettingsPreferOPFMetadata": "Pirmenybė OPF metaduomenis",
"LabelSettingsPreferOPFMetadataHelp": "OPF failo metaduomenys bus naudojami knygos informacijai (vietoj aplankų pavadinimų)",
"LabelSettingsSkipMatchingBooksWithASIN": "Praleisti knygas, kurios jau turi ASIN",
"LabelSettingsSkipMatchingBooksWithISBN": "Praleisti knygas, kurios jau turi ISBN",
"LabelSettingsSortingIgnorePrefixes": "Ignoruoti priešdėlius rūšiuojant",
"LabelSettingsSortingIgnorePrefixesHelp": "pvz., su priešdėliu \"the\" knygos pavadinimas \"The Book Title\" bus rūšiuojamas kaip \"Book Title, The\"",
"LabelSettingsSquareBookCovers": "Naudoti kvadratinius knygos viršelius",
"LabelSettingsSquareBookCoversHelp": "Naudoti kvadratinius viršelius vietoj standartinių 1.6:1 knygų viršelių",
"LabelSettingsStoreCoversWithItem": "Saugoti viršelius su elementu",
"LabelSettingsStoreCoversWithItemHelp": "Pagal nutylėjimą viršeliai saugomi /metadata/items aplanke, įjungus šią parinktį viršeliai bus saugomi jūsų bibliotekos elemento aplanke. Bus išsaugotas tik vienas „cover“ pavadinimo failas.",
"LabelSettingsStoreMetadataWithItem": "Saugoti metaduomenis su elementu",
"LabelSettingsStoreMetadataWithItemHelp": "Pagal nutylėjimą metaduomenų failai saugomi /metadata/items aplanke, įjungus šią parinktį metaduomenų failai bus saugomi jūsų bibliotekos elemento aplanke. Naudojamas .abs plėtinys.",
"LabelSettingsTimeFormat": "Laiko formatas",
"LabelShowAll": "Rodyti viską",
"LabelSize": "Dydis",
"LabelSleepTimer": "Miego laikmatis",
"LabelSlug": "Slug",
"LabelStart": "Pradėti",
"LabelStarted": "Pradėta",
"LabelStartedAt": "Pradėta",
"LabelStartTime": "Pradžios laikas",
"LabelStatsAudioTracks": "Garsiniai takeliai",
"LabelStatsAuthors": "Autoriai",
"LabelStatsBestDay": "Geriausia diena",
"LabelStatsDailyAverage": "Vidutiniškai per dieną",
"LabelStatsDays": "Dienos",
"LabelStatsDaysListened": "Klausyta dienų",
"LabelStatsHours": "Valandos",
"LabelStatsInARow": "iš eilės",
"LabelStatsItemsFinished": "Baigti elementai",
"LabelStatsItemsInLibrary": "Elementai bibliotekoje",
"LabelStatsMinutes": "minutės",
"LabelStatsMinutesListening": "Klausyta minučių",
"LabelStatsOverallDays": "Iš viso dienų",
"LabelStatsOverallHours": "Iš viso valandų",
"LabelStatsWeekListening": "Savaitės klausymas",
"LabelSubtitle": "Subtitrai",
"LabelSupportedFileTypes": "Palaikomi failų tipai",
"LabelTag": "Žyma",
"LabelTags": "Žymos",
"LabelTagsAccessibleToUser": "Žymos, pasiekiamos vartotojui",
"LabelTagsNotAccessibleToUser": "Žymos, nepasiekiamos vartotojui",
"LabelTasks": "Vykdomos užduotys",
"LabelTheme": "Tema",
"LabelThemeDark": "Tamsi",
"LabelThemeLight": "Šviesi",
"LabelTimeBase": "Laiko pagrindas",
"LabelTimeListened": "Klausytas laikas",
"LabelTimeListenedToday": "Klausytas laikas šiandien",
"LabelTimeRemaining": "{0} likę",
"LabelTimeToShift": "Laiko perkėlimas sekundėmis",
"LabelTitle": "Pavadinimas",
"LabelToolsEmbedMetadata": "Įterpti metaduomenis",
"LabelToolsEmbedMetadataDescription": "Įterpti metaduomenis į garso failus, įskaitant viršelio paveikslu ir skyrius.",
"LabelToolsMakeM4b": "Sukurti M4B garso knygų failą",
"LabelToolsMakeM4bDescription": "Sukurti .M4B garso knygų failą su įterptais metaduomenimis, viršelio paveikslu ir skyriais.",
"LabelToolsSplitM4b": "Skaidyti M4B į MP3 failus",
"LabelToolsSplitM4bDescription": "Sukurti MP3 failus iš M4B su skyrių skaldymu ir įterptais metaduomenimis, viršelio paveikslu ir skyriais.",
"LabelTotalDuration": "Viso trukmė",
"LabelTotalTimeListened": "Iš viso klausyta laiko",
"LabelTrackFromFilename": "Takelis iš failo pavadinimo",
"LabelTrackFromMetadata": "Takelis iš metaduomenų",
"LabelTracks": "Takeliai",
"LabelTracksMultiTrack": "Keli takeliai",
"LabelTracksNone": "No tracks",
"LabelTracksSingleTrack": "Vienas takelis",
"LabelType": "Tipas",
"LabelUnabridged": "Neprikurptas",
"LabelUnknown": "Nežinoma",
"LabelUpdateCover": "Atnaujinti viršelį",
"LabelUpdateCoverHelp": "Leisti perrašyti esamus viršelius pasirinktoms knygoms, kai yra rasta atitikmenų",
"LabelUpdatedAt": "Atnaujinta",
"LabelUpdateDetails": "Atnaujinti duomenis",
"LabelUpdateDetailsHelp": "Leisti perrašyti esamus duomenis pasirinktoms knygoms, kai yra rasta atitikmenų",
"LabelUploaderDragAndDrop": "Tempkite ir paleiskite failus ar aplankus",
"LabelUploaderDropFiles": "Nutempti failus",
"LabelUseChapterTrack": "Naudoti skyrių takelį",
"LabelUseFullTrack": "Naudoti visą takelį",
"LabelUser": "Vartotojas",
"LabelUsername": "Vartotojo vardas",
"LabelValue": "Reikšmė",
"LabelVersion": "Versija",
"LabelViewBookmarks": "Peržiūrėti skirtukus",
"LabelViewChapters": "Peržiūrėti skyrius",
"LabelViewQueue": "Peržiūrėti grotuvo eilę",
"LabelVolume": "Garsumas",
"LabelWeekdaysToRun": "Dienos, kuriomis vykdyti",
"LabelYourAudiobookDuration": "Jūsų garso knygos trukmė",
"LabelYourBookmarks": "Jūsų skirtukai",
"LabelYourPlaylists": "Jūsų grojaraščiai",
"LabelYourProgress": "Jūsų pažanga",
"MessageAddToPlayerQueue": "Pridėti į grotuvo eilę",
"MessageAppriseDescription": "Norint naudoti šią funkciją, reikės turėti <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> veikiantį arba API, kuris tvarkys tas pačias užklausas.<br />Apprise API URL turėtų būti visi kelio takai iki pranešimo siuntimo, pvz., jei jūsų API pasiekiamas adresu <code>http://192.168.1.1:8337</code>, tada įveskite <code>http://192.168.1.1:8337/notify</code>.",
"MessageBackupsDescription": "Atsarginės kopijos apima vartotojus, vartotojų pažangą, bibliotekos elemento informaciją, serverio nustatymus ir vaizdus, saugomus <code>/metadata/items</code> ir <code>/metadata/authors</code>. Atsarginės kopijos <strong>neįtraukia</strong> jokių failų, saugomų jūsų bibliotekos aplankuose.",
"MessageBatchQuickMatchDescription": "Greitas atitikmens rasti bandys pridėti trūkstamus viršelius ir metaduomenis pasirinktiems elementams. Įjunkite žemiau esančias parinktis, kad leistumėte Greitajam atitikmeniui perrašyti esamus viršelius ir/ar metaduomenis.",
"MessageBookshelfNoCollections": "Dar nepridėjote jokių kolekcijų",
"MessageBookshelfNoResultsForFilter": "Rezultatų pagal filtrą \"{0}: {1}\" nėra",
"MessageBookshelfNoRSSFeeds": "Nėra atvertų RSS srautų",
"MessageBookshelfNoSeries": "Neturite jokių serijų",
"MessageChapterEndIsAfter": "Skyriaus pabaiga yra po jūsų garso knygos pabaigos",
"MessageChapterErrorFirstNotZero": "Pirmasis skyrius turi prasidėti nuo 0",
"MessageChapterErrorStartGteDuration": "Netinkamas pradžios laikas. Turi būti mažesnis nei garso knygos trukmė",
"MessageChapterErrorStartLtPrev": "Netinkamas pradžios laikas. Turi būti didesnis arba lygus ankstesnio skyriaus pradžios laikui",
"MessageChapterStartIsAfter": "Skyriaus pradžia yra po jūsų garso knygos pabaigos",
"MessageCheckingCron": "Tikrinamas cron...",
"MessageConfirmCloseFeed": "Are you sure you want to close this feed?",
"MessageConfirmDeleteBackup": "Ar tikrai norite ištrinti atsarginę kopiją, skirtą {0}?",
"MessageConfirmDeleteFile": "Tai ištrins failą iš jūsų failų sistemos. Ar tikrai?",
"MessageConfirmDeleteLibrary": "Ar tikrai norite visam laikui ištrinti biblioteką \"{0}\"?",
"MessageConfirmDeleteSession": "Ar tikrai norite ištrinti šią sesiją?",
"MessageConfirmForceReScan": "Ar tikrai norite priversti perskenavimą?",
"MessageConfirmMarkAllEpisodesFinished": "Ar tikrai norite pažymėti visus epizodus kaip užbaigtus?",
"MessageConfirmMarkAllEpisodesNotFinished": "Ar tikrai norite pažymėti visus epizodus kaip nebaigtus?",
"MessageConfirmMarkSeriesFinished": "Ar tikrai norite pažymėti visas knygas šioje serijoje kaip užbaigtas?",
"MessageConfirmMarkSeriesNotFinished": "Ar tikrai norite pažymėti visas knygas šioje serijoje kaip nebaigtas?",
"MessageConfirmRemoveAllChapters": "Ar tikrai norite pašalinti visus skyrius?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Ar tikrai norite pašalinti kolekciją \"{0}\"?",
"MessageConfirmRemoveEpisode": "Ar tikrai norite pašalinti epizodą \"{0}\"?",
"MessageConfirmRemoveEpisodes": "Ar tikrai norite pašalinti {0} epizodus?",
"MessageConfirmRemoveNarrator": "Ar tikrai norite pašalinti skaitytoją \"{0}\"?",
"MessageConfirmRemovePlaylist": "Ar tikrai norite pašalinti savo grojaraštį \"{0}\"?",
"MessageConfirmRenameGenre": "Ar tikrai norite pervadinti žanrą \"{0}\" į \"{1}\" visiems elementams?",
"MessageConfirmRenameGenreMergeNote": "Pastaba: šis žanras jau yra, todėl jie bus sujungti.",
"MessageConfirmRenameGenreWarning": "Įspėjimas! Panašus žanras jau yra \"{0}\".",
"MessageConfirmRenameTag": "Ar tikrai norite pervadinti žymą \"{0}\" į \"{1}\" visiems elementams?",
"MessageConfirmRenameTagMergeNote": "Pastaba: ši žyma jau egzistuoja, todėl jos bus sujungtos.",
"MessageConfirmRenameTagWarning": "Įspėjimas! Panaši žyma jau egzistuoja \"{0}\".",
"MessageConfirmSendEbookToDevice": "Ar tikrai norite nusiųsti {0} el. knygą \"{1}\" į įrenginį \"{2}\"?",
"MessageDownloadingEpisode": "Epizodas atsisiunčiamas",
"MessageDragFilesIntoTrackOrder": "Surikiuokite takelius vilkdami failus",
"MessageEmbedFinished": "Įterpimas baigtas!",
"MessageEpisodesQueuedForDownload": "{0} epizodai laukia atsisiuntimo",
"MessageFeedURLWillBe": "Srauto URL bus {0}",
"MessageFetching": "Surenkama...",
"MessageForceReScanDescription": "skenuos visus failus lyg iš naujo. Garsinių failų ID3 žymos, OPF failai ir tekstiniai failai bus nuskenuoti kaip nauji.",
"MessageImportantNotice": "Svarbus pranešimas!",
"MessageInsertChapterBelow": "Įterpti skyrių žemiau",
"MessageItemsSelected": "Pasirinkti {0} elementai (-ų)",
"MessageItemsUpdated": "Atnaujinti {0} elementai (-ų)",
"MessageJoinUsOn": "Prisijunkite prie mūsų",
"MessageListeningSessionsInTheLastYear": "{0} klausymo sesijų per paskutinius metus",
"MessageLoading": "Kraunama...",
"MessageLoadingFolders": "Kraunami aplankai...",
"MessageM4BFailed": "M4B Nepavyko!",
"MessageM4BFinished": "M4B Baigta!",
"MessageMapChapterTitles": "Susieti skyriaus pavadinimus su jūsų esamais garso knygos skyriais, neredaguojant laiko žymų",
"MessageMarkAllEpisodesFinished": "Pažymėti visus epizodus kaip užbaigtus",
"MessageMarkAllEpisodesNotFinished": "Pažymėti visus epizodus kaip nebaigtus",
"MessageMarkAsFinished": "Pažymėti kaip užbaigtą",
"MessageMarkAsNotFinished": "Pažymėti kaip nebaigtą",
"MessageMatchBooksDescription": "bandys suderinti bibliotekos knygas su knyga iš pasirinkto paieškos tiekėjo ir užpildys tuščius duomenis ir viršelius. Neperrašo detalių.",
"MessageNoAudioTracks": "Nėra garso takelių",
"MessageNoAuthors": "Nėra autorių",
"MessageNoBackups": "Nėra atsarginių kopijų",
"MessageNoBookmarks": "Nėra žymų",
"MessageNoChapters": "Nėra skyrių",
"MessageNoCollections": "Nėra kolekcijų",
"MessageNoCoversFound": "Nerasta viršelių",
"MessageNoDescription": "Nėra aprašymo",
"MessageNoDownloadsInProgress": "Nėra vykstančių atsisiuntimų",
"MessageNoDownloadsQueued": "Nėra eilėje esančių atsisiuntimų",
"MessageNoEpisodeMatchesFound": "Nerasta epizodo atitikmenų",
"MessageNoEpisodes": "Nėra epizodų",
"MessageNoFoldersAvailable": "Nėra prieinamų aplankų",
"MessageNoGenres": "Nėra žanrų",
"MessageNoIssues": "Nėra problemų",
"MessageNoItems": "Nėra elementų",
"MessageNoItemsFound": "Elementų nerasta",
"MessageNoListeningSessions": "Klausymo sesijų nėra",
"MessageNoLogs": "Žurnalo įrašų nėra",
"MessageNoMediaProgress": "Nėra medijos pažangos",
"MessageNoNotifications": "Nėra pranešimų",
"MessageNoPodcastsFound": "Tinklalaidžių nerasta",
"MessageNoResults": "Rezultatų nėra",
"MessageNoSearchResultsFor": "Paieškos rezultatų nėra „{0}“",
"MessageNoSeries": "Serijų nėra",
"MessageNoTags": "Žymų nėra",
"MessageNoTasksRunning": "Nėra vykstančių užduočių",
"MessageNotYetImplemented": "Dar neįgyvendinta",
"MessageNoUpdateNecessary": "Atnaujinimai nereikalingi",
"MessageNoUpdatesWereNecessary": "Nereikalingi jokie atnaujinimai",
"MessageNoUserPlaylists": "Neturite grojaraščių",
"MessageOr": "arba",
"MessagePauseChapter": "Pristabdyti skyriaus grojimą",
"MessagePlayChapter": "Paklausyti skyriaus pradžios",
"MessagePlaylistCreateFromCollection": "Sukurti grojaraštį iš kolekcijos",
"MessagePodcastHasNoRSSFeedForMatching": "Tinklalidė neturi RSS srauto URL kuriuo būtų galima sulyginti",
"MessageQuickMatchDescription": "Užpildykite tuščius elementų duomenis ir viršelius su pirmuoju atitikimo rezultatu iš „{0}“. Neneperrašo detalių, nebent įgalintas serverio nustatymas „Pirmenybė atitaikytiems metaduomenis“.",
"MessageRemoveChapter": "Pašalinti skyrių",
"MessageRemoveEpisodes": "Pašalinti {0} epizodų (-ą)",
"MessageRemoveFromPlayerQueue": "Pašalinti iš grojaraščio",
"MessageRemoveUserWarning": "Ar tikrai norite visam laikui ištrinti naudotoją „{0}“?",
"MessageReportBugsAndContribute": "Praneškite apie klaidas, prašykite naujovių ir prisidėkite",
"MessageResetChaptersConfirm": "Ar tikrai norite atkurti skyrius ir atšaukti pakeitimus, kuriuos atlikote?",
"MessageRestoreBackupConfirm": "Ar tikrai norite atkurti atsarginę kopiją, sukurtą",
"MessageRestoreBackupWarning": "Atkurdami atsarginę kopiją perrašysite visą duomenų bazę, esančią /config ir viršelių vaizdus /metadata/items ir /metadata/authors.<br /><br />Atsarginės kopijos nekeičia jokių failų jūsų bibliotekos aplankuose. Jei esate įgalinę serverio nustatymus, kad viršelio meną ir metaduomenis saugotumėte savo bibliotekos aplankuose, šie neperrašomi ar atkuriami.<br /><br />Visi klientai, naudojantys jūsų serverį, bus automatiškai atnaujinti.",
"MessageSearchResultsFor": "Paieškos rezultatai „{0}“",
"MessageServerCouldNotBeReached": "Nepavyko pasiekti serverio",
"MessageSetChaptersFromTracksDescription": "Nustatyti skyrius, naudojant kiekvieną garso failą kaip skyrių ir skyriaus pavadinimą kaip garso failo pavadinimą",
"MessageStartPlaybackAtTime": "Paleisti klausymą „{0}“ nuo {1}?",
"MessageThinking": "Mąstau...",
"MessageUploaderItemFailed": "Įkelti nepavyko",
"MessageUploaderItemSuccess": "Sėkmingai įkelta!",
"MessageUploading": "Įkeliama...",
"MessageValidCronExpression": "Galiojanti cron išraiška",
"MessageWatcherIsDisabledGlobally": "Serverio nustatymuose stebėtojas išjungtas visuotinai",
"MessageXLibraryIsEmpty": "{0} biblioteka tuščia!",
"MessageYourAudiobookDurationIsLonger": "Jūsų garso knygos trukmė yra ilgesnė nei rasta trukmė",
"MessageYourAudiobookDurationIsShorter": "Jūsų garso knygos trukmė yra trumpesnė nei rasta trukmė",
"NoteChangeRootPassword": "Tik root vartotojas gali turėti tuščią slaptažodį",
"NoteChapterEditorTimes": "Pastaba: Pirmasis skyriaus pradžios laikas turi likti 0:00, o paskutinio skyriaus pradžios laikas negali viršyti šios garso knygos trukmės.",
"NoteFolderPicker": "Pastaba: jau susieti aplankai nebus rodomi",
"NoteFolderPickerDebian": "Pastaba: Aplanko pasirinkimo įrankis „Debian“ sistemoje nėra visiškai įgyvendintas. Turėtumėte tiesiogiai įvesti kelią į savo biblioteką.",
"NoteRSSFeedPodcastAppsHttps": "Įspėjimas: Dauguma tinklalaidžių programų reikalauja, kad RSS kanalo URL būtų naudojamas su HTTPS",
"NoteRSSFeedPodcastAppsPubDate": "Įspėjimas: Vienas ar daugiau jūsų epizodų neturi publikavimo datos. Kai kurios tinklalaidžių programos to reikalauja.",
"NoteUploaderFoldersWithMediaFiles": "Aplankai su medijos failais bus tvarkomi kaip atskiri bibliotekos elementai.",
"NoteUploaderOnlyAudioFiles": "Jei įkeliami tik garso failai, kiekvienas garso failas bus tvarkomas kaip atskira garso knyga.",
"NoteUploaderUnsupportedFiles": "Nepalaikomi failai yra ignoruojami. Pasirinkus ar atidarant aplanką, kiti failai, nesantys elementų aplankuose, yra ignoruojami.",
"PlaceholderNewCollection": "Naujas kolekcijos pavadinimas",
"PlaceholderNewFolderPath": "Naujas aplanko kelias",
"PlaceholderNewPlaylist": "Naujas grojaraščio pavadinimas",
"PlaceholderSearch": "Ieškoti..",
"PlaceholderSearchEpisode": "Ieškoti epizodo..",
"ToastAccountUpdateFailed": "Paskyros atnaujinimas nepavyko",
"ToastAccountUpdateSuccess": "Paskyra atnaujinta",
"ToastAuthorImageRemoveFailed": "Nepavyko pašalinti autoriaus paveiksliuko",
"ToastAuthorImageRemoveSuccess": "Autoriaus paveiksliukas pašalintas",
"ToastAuthorUpdateFailed": "Nepavyko atnaujinti autoriaus",
"ToastAuthorUpdateMerged": "Autorius sujungtas",
"ToastAuthorUpdateSuccess": "Autorius atnaujintas",
"ToastAuthorUpdateSuccessNoImageFound": "Autorius atnaujintas (paveiksliukas nerastas)",
"ToastBackupCreateFailed": "Atsarginės kopijos sukurti nepavyko",
"ToastBackupCreateSuccess": "Atsarginė kopija sukurta",
"ToastBackupDeleteFailed": "Atsarginės kopijos ištrinti nepavyko",
"ToastBackupDeleteSuccess": "Atsarginė kopija ištrinta",
"ToastBackupRestoreFailed": "Atsarginės kopijos atkurti nepavyko",
"ToastBackupUploadFailed": "Atsarginės kopijos įkelti nepavyko",
"ToastBackupUploadSuccess": "Atsarginė kopija įkelta",
"ToastBatchUpdateFailed": "Masinis atnaujinimas nepavyko",
"ToastBatchUpdateSuccess": "Masinis atnaujinimas sėkmingas",
"ToastBookmarkCreateFailed": "Žymos sukurti nepavyko",
"ToastBookmarkCreateSuccess": "Žyma pridėta",
"ToastBookmarkRemoveFailed": "Žymos pašalinti nepavyko",
"ToastBookmarkRemoveSuccess": "Žyma pašalinta",
"ToastBookmarkUpdateFailed": "Žymos atnaujinti nepavyko",
"ToastBookmarkUpdateSuccess": "Žyma atnaujinta",
"ToastChaptersHaveErrors": "Skyriai turi klaidų",
"ToastChaptersMustHaveTitles": "Skyriai turi turėti pavadinimus",
"ToastCollectionItemsRemoveFailed": "Elementų pašalinti iš kolekcijos nepavyko",
"ToastCollectionItemsRemoveSuccess": "Elementai pašalinti iš kolekcijos",
"ToastCollectionRemoveFailed": "Kolekcijos pašalinti nepavyko",
"ToastCollectionRemoveSuccess": "Kolekcija pašalinta",
"ToastCollectionUpdateFailed": "Kolekcijos atnaujinti nepavyko",
"ToastCollectionUpdateSuccess": "Kolekcija atnaujinta",
"ToastItemCoverUpdateFailed": "Elemento viršelio atnaujinti nepavyko",
"ToastItemCoverUpdateSuccess": "Elemento viršelis atnaujintas",
"ToastItemDetailsUpdateFailed": "Elemento detalių atnaujinti nepavyko",
"ToastItemDetailsUpdateSuccess": "Elemento detalės atnaujintos",
"ToastItemDetailsUpdateUnneeded": "Elemento detalės atnaujinimas nereikalingas",
"ToastItemMarkedAsFinishedFailed": "Pažymėti kaip Baigta nepavyko",
"ToastItemMarkedAsFinishedSuccess": "Elementas pažymėtas kaip Baigta",
"ToastItemMarkedAsNotFinishedFailed": "Pažymėti kaip Nebaigta nepavyko",
"ToastItemMarkedAsNotFinishedSuccess": "Elementas pažymėtas kaip Nebaigta",
"ToastLibraryCreateFailed": "Bibliotekos sukurti nepavyko",
"ToastLibraryCreateSuccess": "Biblioteka \"{0}\" sukurta",
"ToastLibraryDeleteFailed": "Bibliotekos ištrinti nepavyko",
"ToastLibraryDeleteSuccess": "Biblioteka ištrinta",
"ToastLibraryScanFailedToStart": "Nepavyko pradėti bibliotekos skenavimo",
"ToastLibraryScanStarted": "Bibliotekos skenavimas pradėtas",
"ToastLibraryUpdateFailed": "Bibliotekos atnaujinti nepavyko",
"ToastLibraryUpdateSuccess": "Biblioteka \"{0}\" atnaujinta",
"ToastPlaylistCreateFailed": "Grojaraščio sukurti nepavyko",
"ToastPlaylistCreateSuccess": "Grojaraštis sukurtas",
"ToastPlaylistRemoveFailed": "Grojaraščio pašalinti nepavyko",
"ToastPlaylistRemoveSuccess": "Grojaraštis pašalintas",
"ToastPlaylistUpdateFailed": "Grojaraščio atnaujinti nepavyko",
"ToastPlaylistUpdateSuccess": "Grojaraštis atnaujintas",
"ToastPodcastCreateFailed": "Tinklalaidės sukurti nepavyko",
"ToastPodcastCreateSuccess": "Tinklalaidė sėkmingai sukurta",
"ToastRemoveItemFromCollectionFailed": "Elemento pašalinti iš kolekcijos nepavyko",
"ToastRemoveItemFromCollectionSuccess": "Elementas pašalintas iš kolekcijos",
"ToastRSSFeedCloseFailed": "RSS srauto uždaryti nepavyko",
"ToastRSSFeedCloseSuccess": "RSS srautas uždarytas",
"ToastSendEbookToDeviceFailed": "Nepavyko nusiųsti e-knygos į įrenginį",
"ToastSendEbookToDeviceSuccess": "E-knyga išsiųsta į įrenginį \"{0}\"",
"ToastSeriesUpdateFailed": "Serijos atnaujinti nepavyko",
"ToastSeriesUpdateSuccess": "Serijos atnaujintos",
"ToastSessionDeleteFailed": "Sesijos ištrinti nepavyko",
"ToastSessionDeleteSuccess": "Sesija ištrinta",
"ToastSocketConnected": "Serveris prijungtas",
"ToastSocketDisconnected": "Severis atjungtas",
"ToastSocketFailedToConnect": "Nepavyko prisijungti prie serverio",
"ToastUserDeleteFailed": "Nepavyko ištrinti naudotojo",
"ToastUserDeleteSuccess": "Naudotojas ištrintas"
}
+61 -30
View File
@@ -99,10 +99,11 @@
"HeaderDetails": "Details",
"HeaderDownloadQueue": "Download-wachtrij",
"HeaderEbookFiles": "Ebook Files",
"HeaderEmail": "Email",
"HeaderEmailSettings": "Email Settings",
"HeaderEmail": "E-mail",
"HeaderEmailSettings": "E-mail instellingen",
"HeaderEpisodes": "Afleveringen",
"HeaderEReaderDevices": "E-Reader Devices",
"HeaderEreaderDevices": "Ereader-apparaten",
"HeaderEreaderSettings": "Ereader-instellingen",
"HeaderFiles": "Bestanden",
"HeaderFindChapters": "Zoek hoofdstukken",
"HeaderIgnoredFiles": "Genegeerde bestanden",
@@ -137,6 +138,7 @@
"HeaderRemoveEpisodes": "Verwijder {0} afleveringen",
"HeaderRSSFeedGeneral": "RSS-details",
"HeaderRSSFeedIsOpen": "RSS-feed is open",
"HeaderRSSFeeds": "RSS-feeds",
"HeaderSavedMediaProgress": "Opgeslagen mediavoortgang",
"HeaderSchedule": "Schema",
"HeaderScheduleLibraryScans": "Schema automatische bibliotheekscans",
@@ -154,6 +156,7 @@
"HeaderStatsRecentSessions": "Recente sessies",
"HeaderStatsTop10Authors": "Top 10 auteurs",
"HeaderStatsTop5Genres": "Top 5 genres",
"HeaderTableOfContents": "Inhoudsopgave",
"HeaderTools": "Tools",
"HeaderUpdateAccount": "Account bijwerken",
"HeaderUpdateAuthor": "Auteur bijwerken",
@@ -176,13 +179,14 @@
"LabelAll": "Alle",
"LabelAllUsers": "Alle gebruikers",
"LabelAlreadyInYourLibrary": "Reeds in je bibliotheek",
"LabelAppend": "Append",
"LabelAppend": "Achteraan toevoegen",
"LabelAuthor": "Auteur",
"LabelAuthorFirstLast": "Auteur (Voornaam Achternaam)",
"LabelAuthorLastFirst": "Auteur (Achternaam, Voornaam)",
"LabelAuthors": "Auteurs",
"LabelAutoDownloadEpisodes": "Afleveringen automatisch downloaden",
"LabelBackToUser": "Terug naar gebruiker",
"LabelBackupLocation": "Back-up locatie",
"LabelBackupsEnableAutomaticBackups": "Automatische back-ups inschakelen",
"LabelBackupsEnableAutomaticBackupsHelp": "Back-ups opgeslagen in /metadata/backups",
"LabelBackupsMaxBackupSize": "Maximale back-up-grootte (in GB)",
@@ -199,11 +203,12 @@
"LabelClosePlayer": "Sluit speler",
"LabelCodec": "Codec",
"LabelCollapseSeries": "Series inklappen",
"LabelCollection": "Collection",
"LabelCollections": "Collecties",
"LabelComplete": "Compleet",
"LabelConfirmPassword": "Bevestig wachtwoord",
"LabelContinueListening": "Verder luisteren",
"LabelContinueReading": "Continue Reading",
"LabelContinueReading": "Verder luisteren",
"LabelContinueSeries": "Ga verder met serie",
"LabelCover": "Cover",
"LabelCoverImageURL": "Coverafbeelding URL",
@@ -220,16 +225,19 @@
"LabelDirectory": "Map",
"LabelDiscFromFilename": "Schijf uit bestandsnaam",
"LabelDiscFromMetadata": "Schijf uit metadata",
"LabelDiscover": "Ontdek",
"LabelDownload": "Download",
"LabelDownloadNEpisodes": "Download {0} episodes",
"LabelDuration": "Duur",
"LabelDurationFound": "Gevonden duur:",
"LabelEbook": "Ebook",
"LabelEbooks": "Ebooks",
"LabelEdit": "Wijzig",
"LabelEmail": "Email",
"LabelEmailSettingsFromAddress": "From Address",
"LabelEmailSettingsSecure": "Secure",
"LabelEmailSettingsSecureHelp": "If true the connection will use TLS when connecting to server. If false then TLS is used if server supports the STARTTLS extension. In most cases set this value to true if you are connecting to port 465. For port 587 or 25 keep it false. (from nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsFromAddress": "Van-adres",
"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",
"LabelEnable": "Inschakelen",
"LabelEnd": "Einde",
@@ -248,12 +256,13 @@
"LabelFinished": "Voltooid",
"LabelFolder": "Map",
"LabelFolders": "Mappen",
"LabelFormat": "Format",
"LabelFontScale": "Lettertype schaal",
"LabelFormat": "Formaat",
"LabelGenre": "Genre",
"LabelGenres": "Genres",
"LabelHardDeleteFile": "Hard-delete bestand",
"LabelHasEbook": "Has ebook",
"LabelHasSupplementaryEbook": "Has supplementary ebook",
"LabelHasEbook": "Heeft ebook",
"LabelHasSupplementaryEbook": "Heeft supplementair ebook",
"LabelHost": "Host",
"LabelHour": "Uur",
"LabelIcon": "Icoon",
@@ -279,12 +288,16 @@
"LabelLastSeen": "Laatst gezien",
"LabelLastTime": "Laatste keer",
"LabelLastUpdate": "Laatste update",
"LabelLayout": "Layout",
"LabelLayoutSinglePage": "Enkele pagina",
"LabelLayoutSplitPage": "Gesplitste pagina",
"LabelLess": "Minder",
"LabelLibrariesAccessibleToUser": "Voor gebruiker toegankelijke bibliotheken",
"LabelLibrary": "Bibliotheek",
"LabelLibraryItem": "Library Item",
"LabelLibraryName": "Library Name",
"LabelLibraryItem": "Bibliotheekonderdeel",
"LabelLibraryName": "Bibliotheeknaam",
"LabelLimit": "Limiet",
"LabelLineSpacing": "Regelruimte",
"LabelListenAgain": "Luister opnieuw",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Info",
@@ -309,6 +322,7 @@
"LabelNewPassword": "Nieuw wachtwoord",
"LabelNextBackupDate": "Volgende back-up datum",
"LabelNextScheduledRun": "Volgende geplande run",
"LabelNoEpisodesSelected": "Geen afleveringen geselecteerd",
"LabelNotes": "Notities",
"LabelNotFinished": "Niet Voltooid",
"LabelNotificationAppriseURL": "Apprise URL(s)",
@@ -340,18 +354,18 @@
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastType": "Podcasttype",
"LabelPort": "Port",
"LabelPort": "Poort",
"LabelPrefixesToIgnore": "Te negeren voorzetsels (ongeacht hoofdlettergebruik)",
"LabelPreventIndexing": "Voorkom indexering van je feed door iTunes- en Google podcastmappen",
"LabelPrimaryEbook": "Primary ebook",
"LabelPrimaryEbook": "Primair ebook",
"LabelProgress": "Voortgang",
"LabelProvider": "Bron",
"LabelPubDate": "Publicatiedatum",
"LabelPublisher": "Uitgever",
"LabelPublishYear": "Jaar van uitgave",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRead": "Lees",
"LabelReadAgain": "Lees opnieuw",
"LabelReadEbookWithoutProgress": "Lees ebook zonder voortgang bij te houden",
"LabelRecentlyAdded": "Recent toegevoegd",
"LabelRecentSeries": "Recente series",
"LabelRecommended": "Aangeraden",
@@ -368,25 +382,32 @@
"LabelSearchTitle": "Zoek titel",
"LabelSearchTitleOrASIN": "Zoek titel of ASIN",
"LabelSeason": "Seizoen",
"LabelSendEbookToDevice": "Send Ebook to...",
"LabelSelectAllEpisodes": "Selecteer alle afleveringen",
"LabelSelectEpisodesShowing": "Selecteer {0} afleveringen laten zien",
"LabelSendEbookToDevice": "Stuur ebook naar...",
"LabelSequence": "Sequentie",
"LabelSeries": "Serie",
"LabelSeriesName": "Naam serie",
"LabelSeriesProgress": "Voortgang serie",
"LabelSetEbookAsPrimary": "Set as primary",
"LabelSetEbookAsSupplementary": "Set as supplementary",
"LabelSettingsAudiobooksOnly": "Audiobooks only",
"LabelSettingsAudiobooksOnlyHelp": "Enabling this setting will ignore ebook files unless they are inside an audiobook folder in which case they will be set as supplementary ebooks",
"LabelSetEbookAsPrimary": "Stel in als primair",
"LabelSetEbookAsSupplementary": "Stel in als supplementair",
"LabelSettingsAudiobooksOnly": "Alleen audiobooks",
"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 support",
"LabelSettingsDateFormat": "Datum format",
"LabelSettingsDisableWatcher": "Watcher uitschakelen",
"LabelSettingsDisableWatcherForLibrary": "Map-watcher voor bibliotheek uitschakelen",
"LabelSettingsDisableWatcherHelp": "Schakelt het automatisch toevoegen/bijwerken van onderdelen wanneer bestandswijzigingen gedetecteerd zijn uit. *Vereist herstart server",
"LabelSettingsEnableWatcher": "Watcher inschakelen",
"LabelSettingsEnableWatcherForLibrary": "Map-watcher voor bibliotheek inschakelen",
"LabelSettingsEnableWatcherHelp": "Zorgt voor het automatisch toevoegen/bijwerken van onderdelen als bestandswijzigingen worden gedetecteerd. *Vereist herstarten van server",
"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",
"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",
"LabelSettingsLibraryBookshelfView": "Boekenplank-view voor bibliotheek",
"LabelSettingsOverdriveMediaMarkers": "Gebruik Overdrive media markers voor hoofdstukken",
@@ -413,6 +434,7 @@
"LabelShowAll": "Toon alle",
"LabelSize": "Grootte",
"LabelSleepTimer": "Slaaptimer",
"LabelSlug": "Slug",
"LabelStart": "Start",
"LabelStarted": "Gestart",
"LabelStartedAt": "Gestart op",
@@ -439,6 +461,9 @@
"LabelTagsAccessibleToUser": "Tags toegankelijk voor de gebruiker",
"LabelTagsNotAccessibleToUser": "Tags niet toegankelijk voor de gebruiker",
"LabelTasks": "Lopende taken",
"LabelTheme": "Thema",
"LabelThemeDark": "Donker",
"LabelThemeLight": "Licht",
"LabelTimeBase": "Tijdsbasis",
"LabelTimeListened": "Tijd geluisterd",
"LabelTimeListenedToday": "Tijd geluisterd vandaag",
@@ -457,7 +482,8 @@
"LabelTrackFromMetadata": "Track vanuit metadata",
"LabelTracks": "Tracks",
"LabelTracksMultiTrack": "Multi-track",
"LabelTracksSingleTrack": "Single-track",
"LabelTracksNone": "Geen tracks",
"LabelTracksSingleTrack": "Enkele track",
"LabelType": "Type",
"LabelUnabridged": "Onverkort",
"LabelUnknown": "Onbekend",
@@ -497,14 +523,18 @@
"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",
"MessageCheckingCron": "Cron aan het checken...",
"MessageConfirmCloseFeed": "Are you sure you want to close this feed?",
"MessageConfirmDeleteBackup": "Weet je zeker dat je de backup voor {0} wil verwijderen?",
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
"MessageConfirmDeleteFile": "Dit verwijdert het bestand uit het bestandssysteem. Weet je het zeker?",
"MessageConfirmDeleteLibrary": "Weet je zeker dat je de bibliotheek \"{0}\" permanent wil verwijderen?",
"MessageConfirmDeleteSession": "Weet je zeker dat je deze sessie wil verwijderen?",
"MessageConfirmForceReScan": "Weet je zeker dat je geforceerd opnieuw wil scannen?",
"MessageConfirmMarkAllEpisodesFinished": "Weet je zeker dat je alle afleveringen als voltooid wil markeren?",
"MessageConfirmMarkAllEpisodesNotFinished": "Weet je zeker dat je alle afleveringen als niet-voltooid wil markeren?",
"MessageConfirmMarkSeriesFinished": "Weet je zeker dat je alle boeken in deze serie wil markeren als voltooid?",
"MessageConfirmMarkSeriesNotFinished": "Weet je zeker dat je alle boeken in deze serie wil markeren als niet voltooid?",
"MessageConfirmRemoveAllChapters": "Weet je zeker dat je alle hoofdstukken wil verwijderen?",
"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?",
"MessageConfirmRemoveEpisodes": "Weet je zeker dat je {0} afleveringen wil verwijderen?",
@@ -516,7 +546,7 @@
"MessageConfirmRenameTag": "Weet je zeker dat je tag \"{0}\" wil hernoemen naar\"{1}\" voor alle onderdelen?",
"MessageConfirmRenameTagMergeNote": "Opmerking: Deze tag bestaat al, dus zullen ze worden samengevoegd.",
"MessageConfirmRenameTagWarning": "Waarschuwing! Een gelijknamige tag met ander hoofdlettergebruik bestaat al: \"{0}\".",
"MessageConfirmSendEbookToDevice": "Are you sure you want to send {0} ebook \"{1}\" to device \"{2}\"?",
"MessageConfirmSendEbookToDevice": "Weet je zeker dat je {0} ebook \"{1}\" naar apparaat \"{2}\" wil sturen?",
"MessageDownloadingEpisode": "Aflevering aan het dowloaden",
"MessageDragFilesIntoTrackOrder": "Sleep bestanden in de juiste trackvolgorde",
"MessageEmbedFinished": "Insluiting voltooid!",
@@ -535,6 +565,8 @@
"MessageM4BFailed": "M4B mislukt!",
"MessageM4BFinished": "M4B voltooid!",
"MessageMapChapterTitles": "Map hoofdstuktitels naar je bestaande audioboekhoofdstukken zonder aanpassing van tijden",
"MessageMarkAllEpisodesFinished": "Markeer alle afleveringen als voltooid",
"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.",
@@ -575,7 +607,6 @@
"MessagePlaylistCreateFromCollection": "Afspeellijst aanmaken vanuit collectie",
"MessagePodcastHasNoRSSFeedForMatching": "Podcast heeft geen RSS-feed URL om te gebruiken voor matching",
"MessageQuickMatchDescription": "Vul lege onderdeeldetails & cover met eerste matchresultaat van '{0}'. Overschrijft geen details tenzij 'Prefereer gematchte metadata' serverinstelling is ingeschakeld.",
"MessageRemoveAllItemsWarning": "WAARSCHUWING! Deze actie zal alle onderdelen in de bibliotheek verwijderen uit de database, inclusief enige bijwerkingen of matches die je hebt gemaakt. Dit doet niets met je onderliggende bestanden. Weet je het zeker?",
"MessageRemoveChapter": "Verwijder hoofdstuk",
"MessageRemoveEpisodes": "Verwijder {0} aflevering(en)",
"MessageRemoveFromPlayerQueue": "Verwijder uit afspeelwachtrij",
@@ -671,8 +702,8 @@
"ToastRemoveItemFromCollectionSuccess": "Onderdeel verwijderd uit collectie",
"ToastRSSFeedCloseFailed": "Sluiten RSS-feed mislukt",
"ToastRSSFeedCloseSuccess": "RSS-feed gesloten",
"ToastSendEbookToDeviceFailed": "Failed to Send Ebook to device",
"ToastSendEbookToDeviceSuccess": "Ebook sent to device \"{0}\"",
"ToastSendEbookToDeviceFailed": "Ebook naar apparaat sturen mislukt",
"ToastSendEbookToDeviceSuccess": "Ebook verstuurd naar apparaat \"{0}\"",
"ToastSeriesUpdateFailed": "Bijwerken serie mislukt",
"ToastSeriesUpdateSuccess": "Bijwerken serie gelukt",
"ToastSessionDeleteFailed": "Verwijderen sessie mislukt",
@@ -682,4 +713,4 @@
"ToastSocketFailedToConnect": "Verbinding Socket mislukt",
"ToastUserDeleteFailed": "Verwijderen gebruiker mislukt",
"ToastUserDeleteSuccess": "Gebruiker verwijderd"
}
}
+716
View File
@@ -0,0 +1,716 @@
{
"ButtonAdd": "Legg til",
"ButtonAddChapters": "Legg til kapittel",
"ButtonAddPodcasts": "Legg til podcast",
"ButtonAddYourFirstLibrary": "Legg til ditt første bibliotek",
"ButtonApply": "Bruk",
"ButtonApplyChapters": "Bruk kapittel",
"ButtonAuthors": "Forfatter",
"ButtonBrowseForFolder": "Bla gjennom mappe",
"ButtonCancel": "Avbryt",
"ButtonCancelEncode": "Avbryt Encode",
"ButtonChangeRootPassword": "Bytt Root-bruker passord",
"ButtonCheckAndDownloadNewEpisodes": "Sjekk og last ned nye episoder",
"ButtonChooseAFolder": "Velg mappe",
"ButtonChooseFiles": "Velg filer",
"ButtonClearFilter": "Bytt filter",
"ButtonCloseFeed": "Lukk Feed",
"ButtonCollections": "Samlinger",
"ButtonConfigureScanner": "Konfigurer skanner",
"ButtonCreate": "Opprett",
"ButtonCreateBackup": "Opprett sikkerhetskopi",
"ButtonDelete": "Slett",
"ButtonDownloadQueue": "Kø",
"ButtonEdit": "Rediger",
"ButtonEditChapters": "Rediger kapittel",
"ButtonEditPodcast": "Rediger podcast",
"ButtonForceReScan": "Tving skann",
"ButtonFullPath": "Full sti",
"ButtonHide": "Gjøm",
"ButtonHome": "Hjem",
"ButtonIssues": "Problemer",
"ButtonLatest": "Siste",
"ButtonLibrary": "Bibliotek",
"ButtonLogout": "Logg ut",
"ButtonLookup": "Slå opp",
"ButtonManageTracks": "Administrer spor",
"ButtonMapChapterTitles": "Kartlegg kapittel titler",
"ButtonMatchAllAuthors": "Søk opp alle forfattere",
"ButtonMatchBooks": "Søk opp bøker",
"ButtonNevermind": "Avbryt",
"ButtonOk": "Ok",
"ButtonOpenFeed": "Åpne Feed",
"ButtonOpenManager": "Åpne behandler",
"ButtonPlay": "Spill av",
"ButtonPlaying": "Spiller av",
"ButtonPlaylists": "Spilleliste",
"ButtonPurgeAllCache": "Tøm alle mellomlager",
"ButtonPurgeItemsCache": "Tøm mellomlager",
"ButtonPurgeMediaProgress": "Slett medie fremgang",
"ButtonQueueAddItem": "Legg til kø",
"ButtonQueueRemoveItem": "Fjern fra kø",
"ButtonQuickMatch": "Kjapt søk",
"ButtonRead": "Les",
"ButtonRemove": "Fjern",
"ButtonRemoveAll": "Fjern alle",
"ButtonRemoveAllLibraryItems": "Fjern alle bibliotekobjekter",
"ButtonRemoveFromContinueListening": "Fjern fra Fortsett å lytte",
"ButtonRemoveFromContinueReading": "Fjern fra Fortsett å lese",
"ButtonRemoveSeriesFromContinueSeries": "Fjern serie fra Fortsett serie",
"ButtonReScan": "Skann på nytt",
"ButtonReset": "Nullstill",
"ButtonRestore": "Gjenopprett",
"ButtonSave": "Lagre",
"ButtonSaveAndClose": "Lagre og lukk",
"ButtonSaveTracklist": "Lagre spilleliste",
"ButtonScan": "Skann",
"ButtonScanLibrary": "Skann bibliotek",
"ButtonSearch": "Søk",
"ButtonSelectFolderPath": "Velg mappe",
"ButtonSeries": "Serier",
"ButtonSetChaptersFromTracks": "Sett kapittel fra spor",
"ButtonShiftTimes": "Forskyv tider",
"ButtonShow": "Vis",
"ButtonStartM4BEncode": "Start M4B Koding",
"ButtonStartMetadataEmbed": "Start Metadata innbaking",
"ButtonSubmit": "Send inn",
"ButtonTest": "Test",
"ButtonUpload": "Last opp",
"ButtonUploadBackup": "Last opp sikkerhetskopi",
"ButtonUploadCover": "Last opp cover",
"ButtonUploadOPMLFile": "Last opp OPML fil",
"ButtonUserDelete": "Slett bruker {0}",
"ButtonUserEdit": "Rediger bruker {0}",
"ButtonViewAll": "Vis alt",
"ButtonYes": "Ja",
"HeaderAccount": "Konto",
"HeaderAdvanced": "Avansert",
"HeaderAppriseNotificationSettings": "Apprise notifikasjonsinstillinger",
"HeaderAudiobookTools": "Lydbok Filbehandlingsverktøy",
"HeaderAudioTracks": "Lydspor",
"HeaderBackups": "Sikkerhetskopier",
"HeaderChangePassword": "Bytt passord",
"HeaderChapters": "Kapittel",
"HeaderChooseAFolder": "Velg en mappe",
"HeaderCollection": "Samlinger",
"HeaderCollectionItems": "Samlingsgjenstander",
"HeaderCover": "Omslag",
"HeaderCurrentDownloads": "Aktive nedlastinger",
"HeaderDetails": "Detaljer",
"HeaderDownloadQueue": "Last ned kø",
"HeaderEbookFiles": "Ebook filer",
"HeaderEmail": "Epost",
"HeaderEmailSettings": "Epost innstillinger",
"HeaderEpisodes": "Episoder",
"HeaderEreaderDevices": "Ereader enheter",
"HeaderEreaderSettings": "Ereader innstillinger",
"HeaderFiles": "Filer",
"HeaderFindChapters": "Finn Kapittel",
"HeaderIgnoredFiles": "Ignorerte filer",
"HeaderItemFiles": "Elementfiler",
"HeaderItemMetadataUtils": "Enhet Metadata verktøy",
"HeaderLastListeningSession": "Siste lyttesesjon",
"HeaderLatestEpisodes": "Siste episoder",
"HeaderLibraries": "Biblioteker",
"HeaderLibraryFiles": "Bibliotek filer",
"HeaderLibraryStats": "Bibliotek statistikk",
"HeaderListeningSessions": "Lyttesesjoner",
"HeaderListeningStats": "Lyttestatistikk",
"HeaderLogin": "Logg inn",
"HeaderLogs": "Loggfiler",
"HeaderManageGenres": "Behandle sjangere",
"HeaderManageTags": "Behandle tags",
"HeaderMapDetails": "Kartleggingsdetaljer",
"HeaderMatch": "Tilpasse",
"HeaderMetadataToEmbed": "Metadata å bake inn",
"HeaderNewAccount": "Ny konto",
"HeaderNewLibrary": "Ny bibliotek",
"HeaderNotifications": "Notifikasjoner",
"HeaderOpenRSSFeed": "Åpne RSS Feed",
"HeaderOtherFiles": "Andre filer",
"HeaderPermissions": "Rettigheter",
"HeaderPlayerQueue": "Spiller kø",
"HeaderPlaylist": "Spilleliste",
"HeaderPlaylistItems": "Spillelisteelement",
"HeaderPodcastsToAdd": "Podcaster å legge til",
"HeaderPreviewCover": "Forhåndsvis omslag",
"HeaderRemoveEpisode": "Fjern episode",
"HeaderRemoveEpisodes": "Fjern {0} episoder",
"HeaderRSSFeedGeneral": "RSS Detailer",
"HeaderRSSFeedIsOpen": "RSS Feed er åpen",
"HeaderRSSFeeds": "RSS Feeder",
"HeaderSavedMediaProgress": "Lagret mediefremgang",
"HeaderSchedule": "Timeplan",
"HeaderScheduleLibraryScans": "Planlegg automatisk bibliotek skann",
"HeaderSession": "Sesjon",
"HeaderSetBackupSchedule": "Sett timeplan for sikkerhetskopi",
"HeaderSettings": "Innstillinger",
"HeaderSettingsDisplay": "Vis",
"HeaderSettingsExperimental": "Eksperimentelle funksjoner",
"HeaderSettingsGeneral": "Generell",
"HeaderSettingsScanner": "Skanner",
"HeaderSleepTimer": "Sove timer",
"HeaderStatsLargestItems": "Største enheter",
"HeaderStatsLongestItems": "Lengste enheter (timer)",
"HeaderStatsMinutesListeningChart": "Minutter lyttet (siste 7 dagene)",
"HeaderStatsRecentSessions": "Siste sesjoner",
"HeaderStatsTop10Authors": "Top 10 forfattere",
"HeaderStatsTop5Genres": "Top 5 sjangere",
"HeaderTableOfContents": "Innholdsfortegnelse",
"HeaderTools": "Verktøy",
"HeaderUpdateAccount": "Oppdater konto",
"HeaderUpdateAuthor": "Oppdater forfatter",
"HeaderUpdateDetails": "Oppdater detaljer",
"HeaderUpdateLibrary": "Oppdater bibliotek",
"HeaderUsers": "Brukere",
"HeaderYourStats": "Din statistikk",
"LabelAbridged": "Forkortet",
"LabelAccountType": "Kontotype",
"LabelAccountTypeAdmin": "Admin",
"LabelAccountTypeGuest": "Gjest",
"LabelAccountTypeUser": "Bruker",
"LabelActivity": "Aktivitet",
"LabelAdded": "Lagt til",
"LabelAddedAt": "Dato lagt til ",
"LabelAddToCollection": "Legg til i samling",
"LabelAddToCollectionBatch": "Legg {0} bøker til samling",
"LabelAddToPlaylist": "Legg til i spilleliste",
"LabelAddToPlaylistBatch": "Legg {0} enheter til i spilleliste",
"LabelAll": "Alle",
"LabelAllUsers": "Alle brukere",
"LabelAlreadyInYourLibrary": "Allerede i biblioteket",
"LabelAppend": "Legge til",
"LabelAuthor": "Forfatter",
"LabelAuthorFirstLast": "Forfatter (Fornavn Etternavn)",
"LabelAuthorLastFirst": "Forfatter (Etternavn Fornavn)",
"LabelAuthors": "Forfattere",
"LabelAutoDownloadEpisodes": "Last ned episoder automatisk",
"LabelBackToUser": "Tilbake til bruker",
"LabelBackupLocation": "Backup Location",
"LabelBackupsEnableAutomaticBackups": "Aktiver automatisk sikkerhetskopi",
"LabelBackupsEnableAutomaticBackupsHelp": "Sikkerhetskopier lagret under /metadata/backups",
"LabelBackupsMaxBackupSize": "Maks sikkerhetskopi størrelse (i GB)",
"LabelBackupsMaxBackupSizeHelp": "For å forhindre feilkonfigurasjon, vil sikkerhetskopier mislykkes hvis de oveskride konfigurert størrelse.",
"LabelBackupsNumberToKeep": "Antall sikkerhetskopier som skal beholdes",
"LabelBackupsNumberToKeepHelp": "Kun 1 sikkerhetskopi vil bli fjernet om gangen, hvis du allerede har flere sikkerhetskopier enn dette bør du fjerne de manuelt.",
"LabelBitrate": "Bithastighet",
"LabelBooks": "Bøker",
"LabelChangePassword": "Endre passord",
"LabelChannels": "Kanaler",
"LabelChapters": "Kapitler",
"LabelChaptersFound": "kapitler funnet",
"LabelChapterTitle": "Kapittel tittel",
"LabelClosePlayer": "Lukk spiller",
"LabelCodec": "Kodek",
"LabelCollapseSeries": "Minimer serier",
"LabelCollection": "Samling",
"LabelCollections": "Samlings",
"LabelComplete": "Fullfør",
"LabelConfirmPassword": "Bekreft passord",
"LabelContinueListening": "Forsett å lytte",
"LabelContinueReading": "Fortsett å lese",
"LabelContinueSeries": "Fortsett serie",
"LabelCover": "Omslag",
"LabelCoverImageURL": "Omslagsbilde URL",
"LabelCreatedAt": "Dato opprettet",
"LabelCronExpression": "Cron uttrykk",
"LabelCurrent": "Nåværende",
"LabelCurrently": "Nåværende:",
"LabelCustomCronExpression": "Tilpasset Cron utrykk:",
"LabelDatetime": "Dato tid",
"LabelDescription": "Beskrivelse",
"LabelDeselectAll": "Fjern valg",
"LabelDevice": "Enhet",
"LabelDeviceInfo": "Enhetsinformasjon",
"LabelDirectory": "Mappe",
"LabelDiscFromFilename": "Disk fra filnavn",
"LabelDiscFromMetadata": "Disk fra metadata",
"LabelDiscover": "Oppdag",
"LabelDownload": "Last ned",
"LabelDownloadNEpisodes": "Last ned {0} episoder",
"LabelDuration": "Varighet",
"LabelDurationFound": "Varighet funnet:",
"LabelEbook": "Ebok",
"LabelEbooks": "Ebøker",
"LabelEdit": "Rediger",
"LabelEmail": "Epost",
"LabelEmailSettingsFromAddress": "Fra Adresse",
"LabelEmailSettingsSecure": "Sikker",
"LabelEmailSettingsSecureHelp": "Hvis aktivert, vil tilkoblingen bruke TLS under tilkobling til tjeneren. Ellers vil TLS bli brukt hvis tjeneren støtter STARTTLS utvidelsen. I de fleste tilfeller aktiver valget hvis du kobler til med port 465. Med port 587 eller 25 deaktiver valget. (fra nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Test Adresse",
"LabelEmbeddedCover": "Bak inn omslag",
"LabelEnable": "Aktiver",
"LabelEnd": "Slutt",
"LabelEpisode": "Episode",
"LabelEpisodeTitle": "Episode tittel",
"LabelEpisodeType": "Episode type",
"LabelExample": "Eksempel",
"LabelExplicit": "Eksplisitt",
"LabelFeedURL": "Feed Adresse",
"LabelFile": "Fil",
"LabelFileBirthtime": "Fil Opprettelsesdato",
"LabelFileModified": "Fil Endret",
"LabelFilename": "Filnavn",
"LabelFilterByUser": "Filtrer etter bruker",
"LabelFindEpisodes": "Finn episoder",
"LabelFinished": "Fullført",
"LabelFolder": "Mappe",
"LabelFolders": "Mapper",
"LabelFontScale": "Font størrelse",
"LabelFormat": "Format",
"LabelGenre": "Sjanger",
"LabelGenres": "Sjangers",
"LabelHardDeleteFile": "Tving sletting av fil",
"LabelHasEbook": "Har ebok",
"LabelHasSupplementaryEbook": "Har supplerende ebok",
"LabelHost": "Tjener",
"LabelHour": "Time",
"LabelIcon": "Ikon",
"LabelIncludeInTracklist": "Inkluder i sporliste",
"LabelIncomplete": "Ufullstendig",
"LabelInProgress": "I gang",
"LabelInterval": "Intervall",
"LabelIntervalCustomDailyWeekly": "Egendefinert daglig/ukentlig",
"LabelIntervalEvery12Hours": "Hver 12. timer",
"LabelIntervalEvery15Minutes": "Hver 15. minutter",
"LabelIntervalEvery2Hours": "Hver 2. timer",
"LabelIntervalEvery30Minutes": "Hver 30. minutter",
"LabelIntervalEvery6Hours": "Hver 6. timer",
"LabelIntervalEveryDay": "Hver dag",
"LabelIntervalEveryHour": "Hver time",
"LabelInvalidParts": "Ugyldige deler",
"LabelInvert": "Inverter",
"LabelItem": "Enhet",
"LabelLanguage": "Språk",
"LabelLanguageDefaultServer": "Standard tjener språk",
"LabelLastBookAdded": "Siste bok lagt til",
"LabelLastBookUpdated": "Siste bok oppdatert",
"LabelLastSeen": "Sist sett",
"LabelLastTime": "Siste tid",
"LabelLastUpdate": "Siste oppdatering",
"LabelLayout": "Oppsett",
"LabelLayoutSinglePage": "Enkel side",
"LabelLayoutSplitPage": "Del side",
"LabelLess": "Mindre",
"LabelLibrariesAccessibleToUser": "Biblioteker tilgjengelig for bruker",
"LabelLibrary": "Bibliotek",
"LabelLibraryItem": "Bibliotek enhet",
"LabelLibraryName": "Bibliotek navn",
"LabelLimit": "Begrensning",
"LabelLineSpacing": "Linjemellomrom",
"LabelListenAgain": "Lytt på nytt",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Info",
"LabelLogLevelWarn": "Warn",
"LabelLookForNewEpisodesAfterDate": "Se etter nye episoder etter denne datoen",
"LabelMediaPlayer": "Mediespiller",
"LabelMediaType": "Medie type",
"LabelMetadataProvider": "Metadata Leverandør",
"LabelMetaTag": "Meta Tag",
"LabelMetaTags": "Meta Tags",
"LabelMinute": "Minutt",
"LabelMissing": "Mangler",
"LabelMissingParts": "Manglende deler",
"LabelMore": "Mer",
"LabelMoreInfo": "Mer info",
"LabelName": "Navn",
"LabelNarrator": "Forteller",
"LabelNarrators": "Fortellere",
"LabelNew": "Ny",
"LabelNewestAuthors": "Nyeste forfattere",
"LabelNewestEpisodes": "Nyeste episoder",
"LabelNewPassword": "Nytt passord",
"LabelNextBackupDate": "Neste sikkerhetskopi dato",
"LabelNextScheduledRun": "Neste planlagte kjøring",
"LabelNoEpisodesSelected": "Ingen episoder valgt",
"LabelNotes": "Notat",
"LabelNotFinished": "Ikke fullført",
"LabelNotificationAppriseURL": "Apprise URL(er)",
"LabelNotificationAvailableVariables": "Tilgjengelige variabler",
"LabelNotificationBodyTemplate": "Kroppsmal",
"LabelNotificationEvent": "Notifikasjons hendelse",
"LabelNotificationsMaxFailedAttempts": "Maks mislykkede forsøk",
"LabelNotificationsMaxFailedAttemptsHelp": "Notifikasjoner er deaktivert når de mislykkes på sende dette flere ganger",
"LabelNotificationsMaxQueueSize": "Maks kø lengde for Notifikasjonshendelser",
"LabelNotificationsMaxQueueSizeHelp": "Hendelser er begrenset til avfyre 1 gang per sekund. Hendelser vil bli ignorert om køen er full. Dette forhindrer Notifikasjon spam.",
"LabelNotificationTitleTemplate": "Tittel mal",
"LabelNotStarted": "Ikke startet",
"LabelNumberOfBooks": "Antall bøker",
"LabelNumberOfEpisodes": "Antall episoder",
"LabelOpenRSSFeed": "Åpne RSS Feed",
"LabelOverwrite": "Overskriv",
"LabelPassword": "Passord",
"LabelPath": "Sti",
"LabelPermissionsAccessAllLibraries": "Har tilgang til alle bibliotek",
"LabelPermissionsAccessAllTags": "Har til gang til alle tags",
"LabelPermissionsAccessExplicitContent": "Har tilgang til eksplisitt material",
"LabelPermissionsDelete": "Kan slette",
"LabelPermissionsDownload": "Kan laste ned",
"LabelPermissionsUpdate": "Kan oppdatere",
"LabelPermissionsUpload": "Kan laste opp",
"LabelPhotoPathURL": "Bilde sti/URL",
"LabelPlaylists": "Spilleliste",
"LabelPlayMethod": "Avspillingsmetode",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcaster",
"LabelPodcastType": "Podcast type",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Prefiks som skal ignoreres (skiller ikke mellom store og små bokstaver)",
"LabelPreventIndexing": "Forhindre at din feed fra å bli indeksert av iTunes og Google podcast kataloger",
"LabelPrimaryEbook": "Primær ebok",
"LabelProgress": "Framgang",
"LabelProvider": "Tilbyder",
"LabelPubDate": "Publiseringsdato",
"LabelPublisher": "Forlegger",
"LabelPublishYear": "Publikasjonsår",
"LabelRead": "Les",
"LabelReadAgain": "Les igjen",
"LabelReadEbookWithoutProgress": "Les ebok uten å beholde fremgang",
"LabelRecentlyAdded": "Nylig lagt til",
"LabelRecentSeries": "Nylige serier",
"LabelRecommended": "Anbefalte",
"LabelRegion": "Region",
"LabelReleaseDate": "Utgivelsesdato",
"LabelRemoveCover": "Fjern omslag",
"LabelRSSFeedCustomOwnerEmail": "Tilpasset eier Epost",
"LabelRSSFeedCustomOwnerName": "Tilpasset eier Navn",
"LabelRSSFeedOpen": "RSS Feed åpne",
"LabelRSSFeedPreventIndexing": "Forhindre indeksering",
"LabelRSSFeedSlug": "RSS Feed Slug",
"LabelRSSFeedURL": "RSS Feed URL",
"LabelSearchTerm": "Søkeord",
"LabelSearchTitle": "Søk tittel",
"LabelSearchTitleOrASIN": "Søk tittel eller ASIN",
"LabelSeason": "Sesong",
"LabelSelectAllEpisodes": "Velg alle episoder",
"LabelSelectEpisodesShowing": "Velg {0} episoder vist",
"LabelSendEbookToDevice": "Send Ebok til...",
"LabelSequence": "Sekvens",
"LabelSeries": "Serier",
"LabelSeriesName": "Serier Navn",
"LabelSeriesProgress": "Serier fremgang",
"LabelSetEbookAsPrimary": "Sett som primær",
"LabelSetEbookAsSupplementary": "Sett som supplerende",
"LabelSettingsAudiobooksOnly": "Kun lydbøker",
"LabelSettingsAudiobooksOnlyHelp": "Aktivering av dette valget til ignorere ebok filer utenom de er i en lydbok mappe hvor de vil bli satt som supplerende ebøker",
"LabelSettingsBookshelfViewHelp": "Skeuomorf design med hyller av ved",
"LabelSettingsChromecastSupport": "Chromecast støtte",
"LabelSettingsDateFormat": "Dato Format",
"LabelSettingsDisableWatcher": "Deaktiver overvåker",
"LabelSettingsDisableWatcherForLibrary": "Deaktiver mappe overvåker for bibliotek",
"LabelSettingsDisableWatcherHelp": "Deaktiverer automatisk opprettelse/oppdatering av enheter når filendringer er oppdaget. *Krever restart av server*",
"LabelSettingsEnableWatcher": "Aktiver overvåker",
"LabelSettingsEnableWatcherForLibrary": "Aktiver mappe overvåker for bibliotek",
"LabelSettingsEnableWatcherHelp": "Aktiverer automatisk opprettelse/oppdatering av enheter når filendringer er oppdaget. *Krever restart av server*",
"LabelSettingsExperimentalFeatures": "Eksperimentelle funksjoner",
"LabelSettingsExperimentalFeaturesHelp": "Funksjoner under utvikling som kan trenge din tilbakemelding og hjelp med testing. Klikk for å åpne GitHub diskusjon.",
"LabelSettingsFindCovers": "Finn omslag",
"LabelSettingsFindCoversHelp": "Hvis lydboken ikke har innbakt omslag eller ett omslagsbilde i mappen, vil skanneren prøve å finne ett.<br>Notis: Dette vil øke søketiden",
"LabelSettingsHideSingleBookSeries": "Gjem bokserie med en bok",
"LabelSettingsHideSingleBookSeriesHelp": "Serier som har kun en bok vil bli gjemt på serie- og hjemmeside hyllen.",
"LabelSettingsHomePageBookshelfView": "Hjemmeside bruk bokhyllevisning",
"LabelSettingsLibraryBookshelfView": "Bibliotek bruk bokhyllevisning",
"LabelSettingsOverdriveMediaMarkers": "Bruk Overdrive mediemerker for kapittel",
"LabelSettingsOverdriveMediaMarkersHelp": "MP3 filer fra Overdrive kommer med kapittel tider bakt inn so egendefinert metadata. Aktiveres dette vil disse taggene bli brukt som kapittel tider automatisk",
"LabelSettingsParseSubtitles": "Analyser undertekster",
"LabelSettingsParseSubtitlesHelp": "Trekk ut undertekster fra lydbok mappenavn.<br>undertekster må være separert med \" - \"<br>f.eks. \"Boktittel - Undertekst her\" har Undertekst \"Undertekst her\"",
"LabelSettingsPreferAudioMetadata": "Foretrekk lyd metadata",
"LabelSettingsPreferAudioMetadataHelp": "Lydfil ID3 meta tagger vil bli brukt som bokdetaljer i stedet fro mappenavn",
"LabelSettingsPreferMatchedMetadata": "Foretrekk funnet metadata",
"LabelSettingsPreferMatchedMetadataHelp": "Funnet data vil overskrive enhetens detaljene når man bruker Kjapt søk. Som standard vil Kjapt søk kun fylle inn manglende detaljer.",
"LabelSettingsPreferOPFMetadata": "Foretrekk OPF metadata",
"LabelSettingsPreferOPFMetadataHelp": "OPF fil metadata vil bli brukt som bokdetaljer i stedet fro mappenavn",
"LabelSettingsSkipMatchingBooksWithASIN": "Hopp over bøker som allerede har ASIN",
"LabelSettingsSkipMatchingBooksWithISBN": "Hopp over bøker som allerede har ISBN",
"LabelSettingsSortingIgnorePrefixes": "Ignorer prefiks når under sortering",
"LabelSettingsSortingIgnorePrefixesHelp": "f.eks. for prefiks \"Den\" bok tittel \"Den Lille Havfruen\" vil bli sortert som \"Lille havfruen, Den\"",
"LabelSettingsSquareBookCovers": "Bruk kvadratiske bokomslag",
"LabelSettingsSquareBookCoversHelp": "Foretrekk å bruke kvadratiske bokomslag i stedet for den standard 1.6:1 bokomslag",
"LabelSettingsStoreCoversWithItem": "Lagre bokomslag med gjenstand",
"LabelSettingsStoreCoversWithItemHelp": "Som standard vil bokomslag bli lagret under /metadata/items, aktiveres dette valget vil bokomslag bli lagret i samme mappe som gjenstanden. Kun en fil med navn \"cover\" vil bli beholdt",
"LabelSettingsStoreMetadataWithItem": "Lagre metadata med gjenstand",
"LabelSettingsStoreMetadataWithItemHelp": "Som standard vil metadata bli lagret under /metadata/items, aktiveres dette valget vil metadata bli lagret i samme mappe som gjenstanden. Bruker .abs filetternavn",
"LabelSettingsTimeFormat": "Tid format",
"LabelShowAll": "Vis alt",
"LabelSize": "Størrelse",
"LabelSleepTimer": "Sove-timer",
"LabelSlug": "Slug",
"LabelStart": "Start",
"LabelStarted": "Startet",
"LabelStartedAt": "Startet",
"LabelStartTime": "Start Tid",
"LabelStatsAudioTracks": "Lydspor",
"LabelStatsAuthors": "Forfattere",
"LabelStatsBestDay": "Beste dag",
"LabelStatsDailyAverage": "Daglig gjennomsnitt",
"LabelStatsDays": "Dager",
"LabelStatsDaysListened": "Dager lyttet",
"LabelStatsHours": "Timer",
"LabelStatsInARow": "på rad",
"LabelStatsItemsFinished": "Gjenstander fullført",
"LabelStatsItemsInLibrary": "Gjenstander i biblioteket",
"LabelStatsMinutes": "minuter",
"LabelStatsMinutesListening": "Minutter lyttet",
"LabelStatsOverallDays": "Totale dager",
"LabelStatsOverallHours": "Totale timer",
"LabelStatsWeekListening": "Uker lyttet",
"LabelSubtitle": "undertekster",
"LabelSupportedFileTypes": "Støttede filtyper",
"LabelTag": "Tag",
"LabelTags": "Tagger",
"LabelTagsAccessibleToUser": "Tagger tilgjengelig for bruker",
"LabelTagsNotAccessibleToUser": "Tagger ikke tilgjengelig for bruker",
"LabelTasks": "Oppgaver som kjører",
"LabelTheme": "Tema",
"LabelThemeDark": "Mørk",
"LabelThemeLight": "Lys",
"LabelTimeBase": "Tidsbase",
"LabelTimeListened": "Tid lyttet",
"LabelTimeListenedToday": "Tid lyttet idag",
"LabelTimeRemaining": "{0} gjennstående",
"LabelTimeToShift": "Tid å forflytte i sekunder",
"LabelTitle": "Tittel",
"LabelToolsEmbedMetadata": "Bak inn metadata",
"LabelToolsEmbedMetadataDescription": "Bak inn metadata i lydfilen, inkludert omslagsbilde og kapitler.",
"LabelToolsMakeM4b": "Lag M4B Lydbokfil",
"LabelToolsMakeM4bDescription": "Lager en.M4B lydbokfil med innbakte omslagsbilde og kapitler.",
"LabelToolsSplitM4b": "Del M4B inn i MP3er",
"LabelToolsSplitM4bDescription": "Lager MP3er fra en M4B inndelt i kapitler med innbakt metadata, omslagsbilde og kapitler.",
"LabelTotalDuration": "Total lengde",
"LabelTotalTimeListened": "Total tid lyttet",
"LabelTrackFromFilename": "Spor fra Filnavn",
"LabelTrackFromMetadata": "Spor fra Metadata",
"LabelTracks": "Spor",
"LabelTracksMultiTrack": "Flerspor",
"LabelTracksNone": "Ingen spor",
"LabelTracksSingleTrack": "Enkelspor",
"LabelType": "Type",
"LabelUnabridged": "Uavkortet",
"LabelUnknown": "Ukjent",
"LabelUpdateCover": "Oppdater omslag",
"LabelUpdateCoverHelp": "Tillat overskriving av eksisterende omslag for de valgte bøkene når en lik bok er funnet",
"LabelUpdatedAt": "Oppdatert",
"LabelUpdateDetails": "Oppdater detaljer",
"LabelUpdateDetailsHelp": "Tillat overskriving av eksisterende detaljer for de valgte bøkene når en lik bok er funnet",
"LabelUploaderDragAndDrop": "Dra og slipp filer eller mapper",
"LabelUploaderDropFiles": "Slipp filer",
"LabelUseChapterTrack": "Bruk kapittelspor",
"LabelUseFullTrack": "Bruke hele sporet",
"LabelUser": "Bruker",
"LabelUsername": "Brukernavn",
"LabelValue": "Verdi",
"LabelVersion": "Versjon",
"LabelViewBookmarks": "Vis bokmerker",
"LabelViewChapters": "Vis kapitler",
"LabelViewQueue": "Vis spillerkø",
"LabelVolume": "Volum",
"LabelWeekdaysToRun": "Ukedager å kjøre",
"LabelYourAudiobookDuration": "Din lydbok lengde",
"LabelYourBookmarks": "Dine bokmerker",
"LabelYourPlaylists": "Dine spillelister",
"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 ett api som vil håndere disse forespørslene. <br />Apprise API Url skal være den fulle URL stien for å sende Notifikasjonen, f.eks., hvis din API instans er hos <code>http://192.168.1.1:8337</code> vil du bruke <code>http://192.168.1.1:8337/notify</code>.",
"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.",
"MessageBatchQuickMatchDescription": "Kjapt søk vil forsøke å legge til manglende omslag og metadata for de valgte gjenstandene. Aktiver dette valget for å tillate Kjapt søk til å overskrive eksisterende omslag og/eller metadata.",
"MessageBookshelfNoCollections": "Du har ikke laget noen samlinger ennå",
"MessageBookshelfNoResultsForFilter": "Ingen resultat for filter \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Ingen RSS feed er åpen",
"MessageBookshelfNoSeries": "Du har ingen serier",
"MessageChapterEndIsAfter": "Kapittel slutt er etter slutt av lydboken",
"MessageChapterErrorFirstNotZero": "Første kapittel starter på 0",
"MessageChapterErrorStartGteDuration": "Feil start tid, må være mindre enn lengde på lydbok",
"MessageChapterErrorStartLtPrev": "Feil start tid, må være større eller det samme som forrige kapittel start tid",
"MessageChapterStartIsAfter": "Kapittel start er etter slutten av din lydbok",
"MessageCheckingCron": "Sjekker cron...",
"MessageConfirmCloseFeed": "Er du sikker på at du vil lukke denne feeden?",
"MessageConfirmDeleteBackup": "Er du sikker på at du vil slette sikkerhetskopi for {0}?",
"MessageConfirmDeleteFile": "Dette vil slette filen fra filsystemet. Er du sikker?",
"MessageConfirmDeleteLibrary": "Er du sikker på at du vil slette biblioteket \"{0}\" for godt?",
"MessageConfirmDeleteSession": "Er du sikker på at du vil slette denne sesjonen?",
"MessageConfirmForceReScan": "Er du sikker på at du vil tvinge en ny skann?",
"MessageConfirmMarkAllEpisodesFinished": "Er du sikker på at du vil markere alle episodene som fullført?",
"MessageConfirmMarkAllEpisodesNotFinished": "Er du sikker på at du vil markere alle episodene som ikke fullført?",
"MessageConfirmMarkSeriesFinished": "Er du sikker på at du vil markere alle bøkene i serien som fullført?",
"MessageConfirmMarkSeriesNotFinished": "Er du sikker på at du vil markere alle bøkene i serien som ikke fullført?",
"MessageConfirmRemoveAllChapters": "Er du sikker på at du vil fjerne alle kapitler?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Er du sikker på at du vil fjerne samling\"{0}\"?",
"MessageConfirmRemoveEpisode": "Er du sikker på at du vil fjerne episode \"{0}\"?",
"MessageConfirmRemoveEpisodes": "Er du sikker på at du vil fjerne {0} episoder?",
"MessageConfirmRemoveNarrator": "Er du sikker på at du vil fjerne forteller \"{0}\"?",
"MessageConfirmRemovePlaylist": "Er du sikker på at du vil fjerne spillelisten \"{0}\"?",
"MessageConfirmRenameGenre": "Er du sikker på at du vil endre sjanger \"{0}\" til \"{1}\" for alle gjenstandene?",
"MessageConfirmRenameGenreMergeNote": "Notis: Denne sjangeren finnes allerede så de vil bli slått sammen.",
"MessageConfirmRenameGenreWarning": "Advarsel! En lignende sjanger eksisterer allerede (med forsjellige store / små bokstaver) \"{0}\".",
"MessageConfirmRenameTag": "Er du sikker på at du vil endre tag \"{0}\" til \"{1}\" for alle gjenstandene?",
"MessageConfirmRenameTagMergeNote": "Notis: Denne taggen finnes allerede så de vil bli slått sammen.",
"MessageConfirmRenameTagWarning": "Advarsel! En lignende tag eksisterer allerede (med forsjellige store / små bokstaver) \"{0}\".",
"MessageConfirmSendEbookToDevice": "Er du sikker på at du vil sende {0} ebok \"{1}\" til enhet \"{2}\"?",
"MessageDownloadingEpisode": "Laster ned episode",
"MessageDragFilesIntoTrackOrder": "Dra filene i rett spor rekkefølge",
"MessageEmbedFinished": "Bak inn Fullført!",
"MessageEpisodesQueuedForDownload": "{0} Episode(r) lagt til i kø for nedlasting",
"MessageFeedURLWillBe": "Feed URL vil bli {0}",
"MessageFetching": "Henter...",
"MessageForceReScanDescription": "vil skanne alle filene igjen som en ny skann. Lyd fil ID3 tagger, OPF filer og tekstfiler vil bli skannet som nye.",
"MessageImportantNotice": "Viktig varsel!",
"MessageInsertChapterBelow": "Sett inn kapittel under",
"MessageItemsSelected": "{0} Gjenstander valgt",
"MessageItemsUpdated": "{0} Gjenstander oppdatert",
"MessageJoinUsOn": "Følg oss nå",
"MessageListeningSessionsInTheLastYear": "{0} Lyttesesjoner iløpet av siste året",
"MessageLoading": "Laster...",
"MessageLoadingFolders": "Laster mapper...",
"MessageM4BFailed": "M4B mislykkes!",
"MessageM4BFinished": "M4B fullført!",
"MessageMapChapterTitles": "Bruk kapittel titler fra din eksisterende lydbok kapitler uten å justere tidsstempel",
"MessageMarkAllEpisodesFinished": "Marker alle episoder som fullført",
"MessageMarkAllEpisodesNotFinished": "Marker alle episoder som ikke fullført",
"MessageMarkAsFinished": "Marker som Fullført",
"MessageMarkAsNotFinished": "Marker som Ikke Fullført",
"MessageMatchBooksDescription": "vil forsøke å oppdatere en bok i ditt bibliotek med en bok fra den valgte søketilbyderen og legge til manglende detaljer og omslag. Overskriver ikke detaljer.",
"MessageNoAudioTracks": "Ingen lydspor",
"MessageNoAuthors": "Ingen forfatter",
"MessageNoBackups": "Ingen sikkerhetskopier",
"MessageNoBookmarks": "Ingen bokmerker",
"MessageNoChapters": "Ingen kapitler",
"MessageNoCollections": "Ingen samlinger",
"MessageNoCoversFound": "Ingen omslagsbilde funnet",
"MessageNoDescription": "Ingen beskrivelse",
"MessageNoDownloadsInProgress": "Ingen aktive nedlastinger",
"MessageNoDownloadsQueued": "Ingen nedlastinger i kø",
"MessageNoEpisodeMatchesFound": "Ingen lik episode funnet",
"MessageNoEpisodes": "Ingen Episoder",
"MessageNoFoldersAvailable": "Ingen mapper tilgjengelige",
"MessageNoGenres": "Ingen sjangere",
"MessageNoIssues": "Ingen feil",
"MessageNoItems": "Ingen gjenstander",
"MessageNoItemsFound": "Ingen gjenstander funnet",
"MessageNoListeningSessions": "Ingen Lyttesesjoner",
"MessageNoLogs": "Ingen logger",
"MessageNoMediaProgress": "Ingen mediefremgang",
"MessageNoNotifications": "Ingen notifikasjoner",
"MessageNoPodcastsFound": "Ingen podcaster funnet",
"MessageNoResults": "Ingen resultat",
"MessageNoSearchResultsFor": "Ingen søkeresultat for \"{0}\"",
"MessageNoSeries": "Ingen serier",
"MessageNoTags": "Ingen tags",
"MessageNoTasksRunning": "Ingen oppgaver kjører",
"MessageNotYetImplemented": "Ikke implementert ennå",
"MessageNoUpdateNecessary": "Ingen oppdatering nødvendig",
"MessageNoUpdatesWereNecessary": "Ingen oppdatering var nødvendig",
"MessageNoUserPlaylists": "Du har ingen spillelister",
"MessageOr": "eller",
"MessagePauseChapter": "Pause avspilling av kapittel",
"MessagePlayChapter": "Lytter på begynnelsen av kapittel",
"MessagePlaylistCreateFromCollection": "Lag spilleliste fra samling",
"MessagePodcastHasNoRSSFeedForMatching": "Podcast har ingen RSS feed url til bruk av sammenligning",
"MessageQuickMatchDescription": "Fyll inn tomme gjenstandsdetaljer og omslagsbilde med første resultat fra '{0}'. Overskriver ikke detaljene utenom 'Foretrekk funnet metadata' tjenerinstilling er aktivert.",
"MessageRemoveChapter": "fjerne kapittel",
"MessageRemoveEpisodes": "fjerne {0} kapitler",
"MessageRemoveFromPlayerQueue": "fjerne fra avspillingskø",
"MessageRemoveUserWarning": "Er du sikker på at du vil slette bruker \"{0}\" for godt?",
"MessageReportBugsAndContribute": "Rapporter feil, forespør funksjoner og tillegg og bidra på",
"MessageResetChaptersConfirm": "Er du sikker på at du vil nullstille kapitler og angre endringene du har gjort?",
"MessageRestoreBackupConfirm": "Er du sikker på at du vil gjenopprette sikkerhetskopien som var laget",
"MessageRestoreBackupWarning": "gjenoppretting av sikkerhetskopi vil overskrive hele databasen under /config og omslagsbilde under /metadata/items og /metadata/authors.<br /><br />Sikkerhetskopier endrer ikke noen filer under dine bibliotekmapper. Hvis du har aktivert tjenerinstillingen for å lagre omslagsbilder og metadata i bibliotekmapper så vil ikke de filene bli tatt sikkerhetskopi eller overskrevet.<br /><br />Alle klientene som bruker din tjener vil bli fornyet automatisk.",
"MessageSearchResultsFor": "Søk resultat for",
"MessageServerCouldNotBeReached": "Tjener kunne ikke bli nådd",
"MessageSetChaptersFromTracksDescription": "Sett kapitler ved å bruke hver lydfil som kapittel og kapitteltittel som lydfilnavnet",
"MessageStartPlaybackAtTime": "Start avspilling av \"{0}\" ved {1}?",
"MessageThinking": "Tenker...",
"MessageUploaderItemFailed": "Opplastning mislykkes",
"MessageUploaderItemSuccess": "Opplastning fullført!",
"MessageUploading": "Laster opp...",
"MessageValidCronExpression": "Gjyldig cron uttrykk",
"MessageWatcherIsDisabledGlobally": "Overvåer er deaktivert globalt i tjenerinstillingene",
"MessageXLibraryIsEmpty": "{0} Bibliotek er tumt!",
"MessageYourAudiobookDurationIsLonger": "Lydboklengden er lengre enn lengde som var funnet",
"MessageYourAudiobookDurationIsShorter": "Lydboklengden er kortere enn lengde som var funnet",
"NoteChangeRootPassword": "Root-bruker er eneste bruker som kan ha tumt passord",
"NoteChapterEditorTimes": "Notis: Første kapittel start tid må være 0:00 og siste kapittel start tid kan ikke overskride denne lydbokens lengde.",
"NoteFolderPicker": "Notis: allerede funnet mapper vil ikke bli vist",
"NoteFolderPickerDebian": "Notis: Mappevelger for debian er ikke fullstendig implementert. Du burde skrive inn stien til biblioteket direkte.",
"NoteRSSFeedPodcastAppsHttps": "Advarsel! De fleste podcast applikasjoner trenger RSS feed URL som bruker HTTPS",
"NoteRSSFeedPodcastAppsPubDate": "Advarsel! 1 eller flere av episodene har ikke publikasjonsdato. Noen podcast applikasjoner trenger dette.",
"NoteUploaderFoldersWithMediaFiles": "Mapper med mediefiler vil bli behandlet som separate bibliotekgjenstander.",
"NoteUploaderOnlyAudioFiles": "Om man laster opp kun lydfiler så vil hver lydfil bli behandlet som en separat lydbok.",
"NoteUploaderUnsupportedFiles": "Filer som ikke er støttet vil bli ignorert. Når man velger eller slipper en mappe, filer som ikke er en mappe vil bli ignorert.",
"PlaceholderNewCollection": "Ny samlingsnavn",
"PlaceholderNewFolderPath": "Ny mappesti",
"PlaceholderNewPlaylist": "Ny spillelistenavn",
"PlaceholderSearch": "Søk..",
"PlaceholderSearchEpisode": "Søk episode..",
"ToastAccountUpdateFailed": "Mislykkes å oppdatere konto",
"ToastAccountUpdateSuccess": "Konto oppdatert",
"ToastAuthorImageRemoveFailed": "Mislykkes å fjerne bilde",
"ToastAuthorImageRemoveSuccess": "Forfatter bilde fjernet",
"ToastAuthorUpdateFailed": "Mislykkes å oppdatere forfatter",
"ToastAuthorUpdateMerged": "Forfatter slått sammen",
"ToastAuthorUpdateSuccess": "Forfatter oppdatert",
"ToastAuthorUpdateSuccessNoImageFound": "Forfatter oppdater (ingen bilde funnet)",
"ToastBackupCreateFailed": "Mislykkes å lage sikkerhetskopi",
"ToastBackupCreateSuccess": "Sikkerhetskopi opprettet",
"ToastBackupDeleteFailed": "Mislykkes å slette sikkerhetskopi",
"ToastBackupDeleteSuccess": "Sikkerhetskopi slettet",
"ToastBackupRestoreFailed": "Misslykkes å gjenopprette sikkerhetskopi",
"ToastBackupUploadFailed": "Misslykkes å laste opp sikkerhetskopi",
"ToastBackupUploadSuccess": "Sikkerhetskopi lastet opp",
"ToastBatchUpdateFailed": "Bulk oppdatering mislykket",
"ToastBatchUpdateSuccess": "Bulk oppdatering fullført",
"ToastBookmarkCreateFailed": "Misslykkes å opprette bokmerke",
"ToastBookmarkCreateSuccess": "Bokmerke lagt til",
"ToastBookmarkRemoveFailed": "Misslykkes å fjerne bokmerke",
"ToastBookmarkRemoveSuccess": "Bokmerke fjernet",
"ToastBookmarkUpdateFailed": "Misslykkes å oppdatere bokmerke",
"ToastBookmarkUpdateSuccess": "Bokmerke oppdatert",
"ToastChaptersHaveErrors": "Kapittel har feil",
"ToastChaptersMustHaveTitles": "Kapittel må ha titler",
"ToastCollectionItemsRemoveFailed": "Misslykkes å fjerne gjenstand(er) fra samling",
"ToastCollectionItemsRemoveSuccess": "Gjenstand(er) fjernet fra samling",
"ToastCollectionRemoveFailed": "Misslykkes å fjerne samling",
"ToastCollectionRemoveSuccess": "Samling fjernet",
"ToastCollectionUpdateFailed": "Misslykkes å oppdatere samling",
"ToastCollectionUpdateSuccess": "samlingupdated",
"ToastItemCoverUpdateFailed": "Misslykkes å oppdatere omslag",
"ToastItemCoverUpdateSuccess": "Omslag oppdatert",
"ToastItemDetailsUpdateFailed": "Misslykkes å oppdatere detaljer",
"ToastItemDetailsUpdateSuccess": "Detaljer oppdatert",
"ToastItemDetailsUpdateUnneeded": "Ingen oppdateringer nødvendig for detaljer",
"ToastItemMarkedAsFinishedFailed": "Misslykkes å markere som Fullført",
"ToastItemMarkedAsFinishedSuccess": "Gjenstand marker som Fullført",
"ToastItemMarkedAsNotFinishedFailed": "Misslykkes å markere som Ikke Fullført",
"ToastItemMarkedAsNotFinishedSuccess": "Markert som Ikke Fullført",
"ToastLibraryCreateFailed": "Misslykkes å opprette bibliotek",
"ToastLibraryCreateSuccess": "Bibliotek \"{0}\" opprettet",
"ToastLibraryDeleteFailed": "Misslykkes å slette bibliotek",
"ToastLibraryDeleteSuccess": "Bibliotek slettet",
"ToastLibraryScanFailedToStart": "Misslykkes å starte skann",
"ToastLibraryScanStarted": "Bibliotek skann startet",
"ToastLibraryUpdateFailed": "Misslykkes å oppdatere bibiliotek",
"ToastLibraryUpdateSuccess": "Bibliotek \"{0}\" oppdatert",
"ToastPlaylistCreateFailed": "Misslykkes å opprette spilleliste",
"ToastPlaylistCreateSuccess": "Spilleliste opprettet",
"ToastPlaylistRemoveFailed": "Misslykkes å fjerne spilleliste",
"ToastPlaylistRemoveSuccess": "Spilleliste fjernet",
"ToastPlaylistUpdateFailed": "Misslykkes å oppdatere spilleliste",
"ToastPlaylistUpdateSuccess": "Spilleliste oppdatert",
"ToastPodcastCreateFailed": "Misslykkes å opprette podcast",
"ToastPodcastCreateSuccess": "Podcast opprettet",
"ToastRemoveItemFromCollectionFailed": "Misslykkes å fjerne gjenstsand fra samling",
"ToastRemoveItemFromCollectionSuccess": "Gjenstand fjernet fra samling",
"ToastRSSFeedCloseFailed": "Misslykkes å lukke RSS feed",
"ToastRSSFeedCloseSuccess": "RSS feed lukket",
"ToastSendEbookToDeviceFailed": "Misslykkes å sende ebok",
"ToastSendEbookToDeviceSuccess": "Ebok sendt til \"{0}\"",
"ToastSeriesUpdateFailed": "Misslykkes å oppdatere serie",
"ToastSeriesUpdateSuccess": "Serie oppdatert",
"ToastSessionDeleteFailed": "Misslykkes å slette sesjon",
"ToastSessionDeleteSuccess": "Sesjon slettet",
"ToastSocketConnected": "Socket koblet til",
"ToastSocketDisconnected": "Socket koblet fra",
"ToastSocketFailedToConnect": "Misslykkes å koble til Socket",
"ToastUserDeleteFailed": "Misslykkes å slette bruker",
"ToastUserDeleteSuccess": "Bruker slettet"
}
+33 -2
View File
@@ -102,7 +102,8 @@
"HeaderEmail": "Email",
"HeaderEmailSettings": "Email Settings",
"HeaderEpisodes": "Rozdziały",
"HeaderEReaderDevices": "E-Reader Devices",
"HeaderEreaderDevices": "Ereader Devices",
"HeaderEreaderSettings": "Ereader Settings",
"HeaderFiles": "Pliki",
"HeaderFindChapters": "Wyszukaj rozdziały",
"HeaderIgnoredFiles": "Zignoruj pliki",
@@ -137,6 +138,7 @@
"HeaderRemoveEpisodes": "Usuń {0} odcinków",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "Kanał RSS jest otwarty",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderSavedMediaProgress": "Zapisany postęp",
"HeaderSchedule": "Harmonogram",
"HeaderScheduleLibraryScans": "Zaplanuj automatyczne skanowanie biblioteki",
@@ -154,6 +156,7 @@
"HeaderStatsRecentSessions": "Ostatnie sesje",
"HeaderStatsTop10Authors": "Top 10 Autorów",
"HeaderStatsTop5Genres": "Top 5 Gatunków",
"HeaderTableOfContents": "Table of Contents",
"HeaderTools": "Narzędzia",
"HeaderUpdateAccount": "Zaktualizuj konto",
"HeaderUpdateAuthor": "Zaktualizuj autorów",
@@ -183,6 +186,7 @@
"LabelAuthors": "Autorzy",
"LabelAutoDownloadEpisodes": "Automatyczne pobieranie odcinków",
"LabelBackToUser": "Powrót",
"LabelBackupLocation": "Backup Location",
"LabelBackupsEnableAutomaticBackups": "Włącz automatyczne kopie zapasowe",
"LabelBackupsEnableAutomaticBackupsHelp": "Kopie zapasowe są zapisywane w folderze /metadata/backups",
"LabelBackupsMaxBackupSize": "Maksymalny łączny rozmiar backupów (w GB)",
@@ -199,6 +203,7 @@
"LabelClosePlayer": "Zamknij odtwarzacz",
"LabelCodec": "Codec",
"LabelCollapseSeries": "Podsumuj serię",
"LabelCollection": "Collection",
"LabelCollections": "Kolekcje",
"LabelComplete": "Ukończone",
"LabelConfirmPassword": "Potwierdź hasło",
@@ -220,7 +225,9 @@
"LabelDirectory": "Katalog",
"LabelDiscFromFilename": "Oznaczenie dysku z nazwy pliku",
"LabelDiscFromMetadata": "Oznaczenie dysku z metadanych",
"LabelDiscover": "Discover",
"LabelDownload": "Pobierz",
"LabelDownloadNEpisodes": "Download {0} episodes",
"LabelDuration": "Czas trwania",
"LabelDurationFound": "Znaleziona długość:",
"LabelEbook": "Ebook",
@@ -230,6 +237,7 @@
"LabelEmailSettingsFromAddress": "From Address",
"LabelEmailSettingsSecure": "Secure",
"LabelEmailSettingsSecureHelp": "If true the connection will use TLS when connecting to server. If false then TLS is used if server supports the STARTTLS extension. In most cases set this value to true if you are connecting to port 465. For port 587 or 25 keep it false. (from nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Test Address",
"LabelEmbeddedCover": "Embedded Cover",
"LabelEnable": "Włącz",
"LabelEnd": "Zakończ",
@@ -248,6 +256,7 @@
"LabelFinished": "Zakończone",
"LabelFolder": "Folder",
"LabelFolders": "Foldery",
"LabelFontScale": "Font scale",
"LabelFormat": "Format",
"LabelGenre": "Gatunek",
"LabelGenres": "Gatunki",
@@ -279,12 +288,16 @@
"LabelLastSeen": "Ostatnio widziany",
"LabelLastTime": "Ostatni czas",
"LabelLastUpdate": "Ostatnia aktualizacja",
"LabelLayout": "Layout",
"LabelLayoutSinglePage": "Single page",
"LabelLayoutSplitPage": "Split page",
"LabelLess": "Mniej",
"LabelLibrariesAccessibleToUser": "Biblioteki dostępne dla użytkownika",
"LabelLibrary": "Biblioteka",
"LabelLibraryItem": "Element biblioteki",
"LabelLibraryName": "Nazwa biblioteki",
"LabelLimit": "Limit",
"LabelLineSpacing": "Line spacing",
"LabelListenAgain": "Słuchaj ponownie",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Informacja",
@@ -309,6 +322,7 @@
"LabelNewPassword": "Nowe hasło",
"LabelNextBackupDate": "Next backup date",
"LabelNextScheduledRun": "Next scheduled run",
"LabelNoEpisodesSelected": "No episodes selected",
"LabelNotes": "Uwagi",
"LabelNotFinished": "Nieukończone",
"LabelNotificationAppriseURL": "URLe Apprise",
@@ -368,6 +382,8 @@
"LabelSearchTitle": "Wyszukaj tytuł",
"LabelSearchTitleOrASIN": "Szukaj tytuł lub ASIN",
"LabelSeason": "Sezon",
"LabelSelectAllEpisodes": "Select all episodes",
"LabelSelectEpisodesShowing": "Select {0} episodes showing",
"LabelSendEbookToDevice": "Send Ebook to...",
"LabelSequence": "Kolejność",
"LabelSeries": "Serie",
@@ -383,10 +399,15 @@
"LabelSettingsDisableWatcher": "Wyłącz monitorowanie",
"LabelSettingsDisableWatcherForLibrary": "Wyłącz monitorowanie folderów dla biblioteki",
"LabelSettingsDisableWatcherHelp": "Wyłącz automatyczne dodawanie/aktualizowanie elementów po wykryciu zmian w plikach. *Wymaga restartu serwera",
"LabelSettingsEnableWatcher": "Enable Watcher",
"LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
"LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
"LabelSettingsExperimentalFeatures": "Funkcje eksperymentalne",
"LabelSettingsExperimentalFeaturesHelp": "Funkcje w trakcie rozwoju, które mogą zyskanć na Twojej opinii i pomocy w testowaniu. Kliknij, aby otworzyć dyskusję na githubie.",
"LabelSettingsFindCovers": "Szukanie okładek",
"LabelSettingsFindCoversHelp": "Jeśli audiobook nie posiada zintegrowanej okładki albo w folderze nie zostanie znaleziony plik okładki, skaner podejmie próbę pobrania okładki z sieci. <br>Uwaga: może to wydłuzyć proces skanowania",
"LabelSettingsHideSingleBookSeries": "Hide single book series",
"LabelSettingsHideSingleBookSeriesHelp": "Series that have a single book will be hidden from the series page and home page shelves.",
"LabelSettingsHomePageBookshelfView": "Widok półki z książkami na stronie głównej",
"LabelSettingsLibraryBookshelfView": "Widok półki z książkami na stronie biblioteki",
"LabelSettingsOverdriveMediaMarkers": "Użyj markerów Overdrive Media Markers dla rozdziałów",
@@ -413,6 +434,7 @@
"LabelShowAll": "Pokaż wszystko",
"LabelSize": "Rozmiar",
"LabelSleepTimer": "Wyłącznik czasowy",
"LabelSlug": "Slug",
"LabelStart": "Rozpocznij",
"LabelStarted": "Rozpoczęty",
"LabelStartedAt": "Rozpoczęto",
@@ -439,6 +461,9 @@
"LabelTagsAccessibleToUser": "Tagi dostępne dla użytkownika",
"LabelTagsNotAccessibleToUser": "Tags not Accessible to User",
"LabelTasks": "Tasks Running",
"LabelTheme": "Theme",
"LabelThemeDark": "Dark",
"LabelThemeLight": "Light",
"LabelTimeBase": "Time Base",
"LabelTimeListened": "Czas odtwarzania",
"LabelTimeListenedToday": "Czas odtwarzania dzisiaj",
@@ -457,6 +482,7 @@
"LabelTrackFromMetadata": "Ścieżka z metadanych",
"LabelTracks": "Tracks",
"LabelTracksMultiTrack": "Multi-track",
"LabelTracksNone": "No tracks",
"LabelTracksSingleTrack": "Single-track",
"LabelType": "Typ",
"LabelUnabridged": "Unabridged",
@@ -497,14 +523,18 @@
"MessageChapterErrorStartLtPrev": "Invalid start time must be greater than or equal to previous chapter start time",
"MessageChapterStartIsAfter": "Początek rozdziału następuje po zakończeniu audiobooka",
"MessageCheckingCron": "Sprawdzanie cron...",
"MessageConfirmCloseFeed": "Are you sure you want to close this feed?",
"MessageConfirmDeleteBackup": "Czy na pewno chcesz usunąć kopię zapasową dla {0}?",
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
"MessageConfirmDeleteLibrary": "Czy na pewno chcesz trwale usunąć bibliotekę \"{0}\"?",
"MessageConfirmDeleteSession": "Czy na pewno chcesz usunąć tę sesję?",
"MessageConfirmForceReScan": "Czy na pewno chcesz wymusić ponowne skanowanie?",
"MessageConfirmMarkAllEpisodesFinished": "Are you sure you want to mark all episodes as finished?",
"MessageConfirmMarkAllEpisodesNotFinished": "Are you sure you want to mark all episodes as not finished?",
"MessageConfirmMarkSeriesFinished": "Are you sure you want to mark all books in this series as finished?",
"MessageConfirmMarkSeriesNotFinished": "Are you sure you want to mark all books in this series as not finished?",
"MessageConfirmRemoveAllChapters": "Are you sure you want to remove all chapters?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Czy na pewno chcesz usunąć kolekcję \"{0}\"?",
"MessageConfirmRemoveEpisode": "Czy na pewno chcesz usunąć odcinek \"{0}\"?",
"MessageConfirmRemoveEpisodes": "Czy na pewno chcesz usunąć {0} odcinki?",
@@ -535,6 +565,8 @@
"MessageM4BFailed": "Tworzenie pliku M4B nie powiodło się",
"MessageM4BFinished": "Tworzenie pliku M4B zakończyło się!",
"MessageMapChapterTitles": "Mapowanie tytułów rozdziałów do istniejących rozdziałów audiobooka bez dostosowywania znaczników czasu",
"MessageMarkAllEpisodesFinished": "Mark all episodes finished",
"MessageMarkAllEpisodesNotFinished": "Mark all episodes not finished",
"MessageMarkAsFinished": "Oznacz jako ukończone",
"MessageMarkAsNotFinished": "Oznacz jako nieukończone",
"MessageMatchBooksDescription": "spróbuje dopasować książki w bibliotece bez plików audio, korzystając z wybranego dostawcy wyszukiwania i wypełnić puste szczegóły i okładki. Nie nadpisuje informacji.",
@@ -575,7 +607,6 @@
"MessagePlaylistCreateFromCollection": "Create playlist from collection",
"MessagePodcastHasNoRSSFeedForMatching": "Podcast nie ma adresu url kanału RSS, który mógłby zostać użyty do dopasowania",
"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'.",
"MessageRemoveAllItemsWarning": "UWAGA! Ta akcja usunie wszystkie elementy biblioteki z bazy danych, w tym wszystkie aktualizacje lub dopasowania, które zostały wykonane. Pliki pozostaną niezmienione. Czy jesteś pewien?",
"MessageRemoveChapter": "Usuń rozdział",
"MessageRemoveEpisodes": "Usuń {0} odcinków",
"MessageRemoveFromPlayerQueue": "Remove from player queue",
+78 -47
View File
@@ -55,7 +55,7 @@
"ButtonRemoveAll": "Удалить всё",
"ButtonRemoveAllLibraryItems": "Удалить все элементы библиотеки",
"ButtonRemoveFromContinueListening": "Удалить из Продолжить слушать",
"ButtonRemoveFromContinueReading": "Remove from Continue Reading",
"ButtonRemoveFromContinueReading": "Удалить из Продолжить читать",
"ButtonRemoveSeriesFromContinueSeries": "Удалить серию из Продолжить серию",
"ButtonReScan": "Пересканировать",
"ButtonReset": "Сбросить",
@@ -98,11 +98,12 @@
"HeaderCurrentDownloads": "Текущие закачки",
"HeaderDetails": "Подробности",
"HeaderDownloadQueue": "Очередь скачивания",
"HeaderEbookFiles": "Ebook Files",
"HeaderEbookFiles": "Файлы e-книг",
"HeaderEmail": "Email",
"HeaderEmailSettings": "Email Settings",
"HeaderEmailSettings": "Настройки Email",
"HeaderEpisodes": "Эпизоды",
"HeaderEReaderDevices": "E-Reader Devices",
"HeaderEreaderDevices": "Устройства E-книга",
"HeaderEreaderSettings": "Настройки E-ридера",
"HeaderFiles": "Файлы",
"HeaderFindChapters": "Найти главы",
"HeaderIgnoredFiles": "Игнорируемые Файлы",
@@ -137,6 +138,7 @@
"HeaderRemoveEpisodes": "Удалить {0} эпизодов",
"HeaderRSSFeedGeneral": "Сведения о RSS",
"HeaderRSSFeedIsOpen": "RSS-канал открыт",
"HeaderRSSFeeds": "RSS-каналы",
"HeaderSavedMediaProgress": "Прогресс медиа сохранен",
"HeaderSchedule": "Планировщик",
"HeaderScheduleLibraryScans": "Планировщик автоматического сканирования библиотеки",
@@ -154,6 +156,7 @@
"HeaderStatsRecentSessions": "Последние сеансы",
"HeaderStatsTop10Authors": "Топ 10 авторов",
"HeaderStatsTop5Genres": "Топ 5 жанров",
"HeaderTableOfContents": "Содержание",
"HeaderTools": "Инструменты",
"HeaderUpdateAccount": "Обновить учетную запись",
"HeaderUpdateAuthor": "Обновить автора",
@@ -167,7 +170,7 @@
"LabelAccountTypeGuest": "Гость",
"LabelAccountTypeUser": "Пользователь",
"LabelActivity": "Активность",
"LabelAdded": "Added",
"LabelAdded": "Добавили",
"LabelAddedAt": "Дата добавления",
"LabelAddToCollection": "Добавить в коллекцию",
"LabelAddToCollectionBatch": "Добавить {0} книг в коллекцию",
@@ -183,27 +186,29 @@
"LabelAuthors": "Авторы",
"LabelAutoDownloadEpisodes": "Скачивать эпизоды автоматически",
"LabelBackToUser": "Назад к пользователю",
"LabelBackupLocation": "Backup Location",
"LabelBackupsEnableAutomaticBackups": "Включить автоматическое бэкапирование",
"LabelBackupsEnableAutomaticBackupsHelp": "Бэкапы сохраняются в /metadata/backups",
"LabelBackupsMaxBackupSize": "Максимальный размер бэкапа (в GB)",
"LabelBackupsMaxBackupSizeHelp": "В качестве защиты процесс бэкапирования будет завершаться ошибкой, если будет превышен настроенный размер.",
"LabelBackupsNumberToKeep": "Сохранять бэкапов",
"LabelBackupsNumberToKeepHelp": "За один раз только 1 бэкап будет удален, так что если у вас будет больше бэкапов, то их нужно удалить вручную.",
"LabelBitrate": "Bitrate",
"LabelBitrate": "Битрейт",
"LabelBooks": "Книги",
"LabelChangePassword": "Изменить пароль",
"LabelChannels": "Channels",
"LabelChapters": "Chapters",
"LabelChannels": "Каналы",
"LabelChapters": "Главы",
"LabelChaptersFound": "глав найдено",
"LabelChapterTitle": "Название главы",
"LabelClosePlayer": "Закрыть проигрыватель",
"LabelCodec": "Codec",
"LabelCodec": "Кодек",
"LabelCollapseSeries": "Свернуть серии",
"LabelCollection": "Коллекция",
"LabelCollections": "Коллекции",
"LabelComplete": "Завершить",
"LabelConfirmPassword": "Подтвердить пароль",
"LabelContinueListening": "Продолжить слушать",
"LabelContinueReading": "Continue Reading",
"LabelContinueReading": "Продолжить читать",
"LabelContinueSeries": "Продолжить серию",
"LabelCover": "Обложка",
"LabelCoverImageURL": "URL изображения обложки",
@@ -220,17 +225,20 @@
"LabelDirectory": "Каталог",
"LabelDiscFromFilename": "Диск из Имени файла",
"LabelDiscFromMetadata": "Диск из Метаданных",
"LabelDiscover": "Не начато",
"LabelDownload": "Скачать",
"LabelDownloadNEpisodes": "Скачать {0} эпизодов",
"LabelDuration": "Длина",
"LabelDurationFound": "Найденная длина:",
"LabelEbook": "Ebook",
"LabelEbooks": "Ebooks",
"LabelEbook": "E-книга",
"LabelEbooks": "E-книги",
"LabelEdit": "Редактировать",
"LabelEmail": "Email",
"LabelEmailSettingsFromAddress": "From Address",
"LabelEmailSettingsSecure": "Secure",
"LabelEmailSettingsSecureHelp": "If true the connection will use TLS when connecting to server. If false then TLS is used if server supports the STARTTLS extension. In most cases set this value to true if you are connecting to port 465. For port 587 or 25 keep it false. (from nodemailer.com/smtp/#authentication)",
"LabelEmbeddedCover": "Embedded Cover",
"LabelEmailSettingsFromAddress": "Адрес От",
"LabelEmailSettingsSecure": "Безопасность",
"LabelEmailSettingsSecureHelp": "Если значение истинно, то соединение будет использовать TLS при подключении к серверу. Если значение ложно, то TLS будет использован, если сервер поддерживает расширение STARTTLS. В большинстве случаев установите это значение в истину, если вы подключаетесь к порту 465. Для порта 587 или 25 оставьте значение ложным. (из nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Тестовый адрес",
"LabelEmbeddedCover": "Встроенная обложка",
"LabelEnable": "Включить",
"LabelEnd": "Конец",
"LabelEpisode": "Эпизод",
@@ -248,13 +256,14 @@
"LabelFinished": "Закончен",
"LabelFolder": "Папка",
"LabelFolders": "Папки",
"LabelFormat": "Format",
"LabelFontScale": "Масштаб шрифта",
"LabelFormat": "Формат",
"LabelGenre": "Жанр",
"LabelGenres": "Жанры",
"LabelHardDeleteFile": "Жесткое удаление файла",
"LabelHasEbook": "Has ebook",
"LabelHasSupplementaryEbook": "Has supplementary ebook",
"LabelHost": "Host",
"LabelHasEbook": "Есть e-книга",
"LabelHasSupplementaryEbook": "Есть дополнительная e-книга",
"LabelHost": "Хост",
"LabelHour": "Часы",
"LabelIcon": "Иконка",
"LabelIncludeInTracklist": "Включать в список воспроизведения",
@@ -270,21 +279,25 @@
"LabelIntervalEveryDay": "Каждый день",
"LabelIntervalEveryHour": "Каждый час",
"LabelInvalidParts": "Неверные части",
"LabelInvert": "Invert",
"LabelInvert": "Инвертировать",
"LabelItem": "Элемент",
"LabelLanguage": "Язык",
"LabelLanguageDefaultServer": "Язык сервера по умолчанию",
"LabelLastBookAdded": "Last Book Added",
"LabelLastBookUpdated": "Last Book Updated",
"LabelLastBookAdded": "Последняя книга добавлена",
"LabelLastBookUpdated": "Последняя книга обновлена",
"LabelLastSeen": "Последнее сканирование",
"LabelLastTime": "Последний по времени",
"LabelLastUpdate": "Последний обновленный",
"LabelLayout": "Макет",
"LabelLayoutSinglePage": "Одна страница",
"LabelLayoutSplitPage": "Разделенная страница",
"LabelLess": "Менее",
"LabelLibrariesAccessibleToUser": "Библиотеки доступные для пользователя",
"LabelLibrary": "Библиотека",
"LabelLibraryItem": "Элемент библиотеки",
"LabelLibraryName": "Имя библиотеки",
"LabelLimit": "Лимит",
"LabelLineSpacing": "Межстрочный интервал",
"LabelListenAgain": "Послушать снова",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Info",
@@ -294,12 +307,12 @@
"LabelMediaType": "Тип медиа",
"LabelMetadataProvider": "Провайдер",
"LabelMetaTag": "Мета тег",
"LabelMetaTags": "Meta Tags",
"LabelMetaTags": "Мета теги",
"LabelMinute": "Минуты",
"LabelMissing": "Потеряно",
"LabelMissingParts": "Потерянные части",
"LabelMore": "Еще",
"LabelMoreInfo": "More Info",
"LabelMoreInfo": "Больше информации",
"LabelName": "Имя",
"LabelNarrator": "Читает",
"LabelNarrators": "Чтецы",
@@ -309,6 +322,7 @@
"LabelNewPassword": "Новый пароль",
"LabelNextBackupDate": "Следующая дата бэкапирования",
"LabelNextScheduledRun": "Следущий запланированный запуск",
"LabelNoEpisodesSelected": "Эпизоды не выбраны",
"LabelNotes": "Заметки",
"LabelNotFinished": "Не завершено",
"LabelNotificationAppriseURL": "URL(ы) для извещений",
@@ -340,18 +354,18 @@
"LabelPodcast": "Подкаст",
"LabelPodcasts": "Подкасты",
"LabelPodcastType": "Тип подкаста",
"LabelPort": "Port",
"LabelPort": "Порт",
"LabelPrefixesToIgnore": "Игнорируемые префиксы (без учета регистра)",
"LabelPreventIndexing": "Запретить индексацию фида каталогами подкастов iTunes и Google",
"LabelPrimaryEbook": "Primary ebook",
"LabelPrimaryEbook": "Основная e-книга",
"LabelProgress": "Прогресс",
"LabelProvider": "Провайдер",
"LabelPubDate": "Дата публикации",
"LabelPublisher": "Издатель",
"LabelPublishYear": "Год публикации",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRead": "Читать",
"LabelReadAgain": "Читать снова",
"LabelReadEbookWithoutProgress": "Читать e-книгу без сохранения прогресса",
"LabelRecentlyAdded": "Недавно добавленные",
"LabelRecentSeries": "Последние серии",
"LabelRecommended": "Рекомендованное",
@@ -368,25 +382,32 @@
"LabelSearchTitle": "Поиск по названию",
"LabelSearchTitleOrASIN": "Поиск по названию или ASIN",
"LabelSeason": "Сезон",
"LabelSendEbookToDevice": "Send Ebook to...",
"LabelSelectAllEpisodes": "Выбрать все эпизоды",
"LabelSelectEpisodesShowing": "Выберите {0} эпизодов для показа",
"LabelSendEbookToDevice": "Отправить e-книгу в...",
"LabelSequence": "Последовательность",
"LabelSeries": "Серия",
"LabelSeriesName": "Имя серии",
"LabelSeriesProgress": "Прогресс серии",
"LabelSetEbookAsPrimary": "Set as primary",
"LabelSetEbookAsSupplementary": "Set as supplementary",
"LabelSettingsAudiobooksOnly": "Audiobooks only",
"LabelSettingsAudiobooksOnlyHelp": "Enabling this setting will ignore ebook files unless they are inside an audiobook folder in which case they will be set as supplementary ebooks",
"LabelSetEbookAsPrimary": "Установить как основную",
"LabelSetEbookAsSupplementary": "Установить как дополнительную",
"LabelSettingsAudiobooksOnly": "Только аудиокниги",
"LabelSettingsAudiobooksOnlyHelp": "Если включить эту настройку, файлы электронных книг будут игнорироваться, за исключением случаев, когда они находятся в папке с аудиокнигами, в этом случае они будут рассматриваться как дополнительные электронные книги.",
"LabelSettingsBookshelfViewHelp": "Конструкция с деревянными полками",
"LabelSettingsChromecastSupport": "Поддержка Chromecast",
"LabelSettingsDateFormat": "Формат даты",
"LabelSettingsDisableWatcher": "Отключить отслеживание",
"LabelSettingsDisableWatcherForLibrary": "Отключить отслеживание для библиотеки",
"LabelSettingsDisableWatcherHelp": "Отключает автоматическое добавление/обновление элементов, когда обнаружено изменение файлов. *Требуется перезапуск сервера",
"LabelSettingsEnableWatcher": "Включить отслеживание",
"LabelSettingsEnableWatcherForLibrary": "Включить отслеживание за папками библиотеки",
"LabelSettingsEnableWatcherHelp": "Включает автоматическое добавление/обновление элементов при обнаружении изменений файлов. *Требуется перезапуск сервера",
"LabelSettingsExperimentalFeatures": "Экспериментальные функции",
"LabelSettingsExperimentalFeaturesHelp": "Функционал в разработке на который Вы могли бы дать отзыв или помочь в тестировании. Нажмите для открытия обсуждения на github.",
"LabelSettingsFindCovers": "Найти обложки",
"LabelSettingsFindCoversHelp": "Если у Ваших аудиокниг нет встроенной обложки или файла обложки в папке книги, то сканер попробует найти обложку.<br>Примечание: Это увеличит время сканирования",
"LabelSettingsHideSingleBookSeries": "Скрыть серии с одной книгой",
"LabelSettingsHideSingleBookSeriesHelp": "Серии, в которых всего одна книга, будут скрыты со страницы серий и полок домашней страницы.",
"LabelSettingsHomePageBookshelfView": "Вид книжной полки на Домашней странице",
"LabelSettingsLibraryBookshelfView": "Вид книжной полки в Библиотеке",
"LabelSettingsOverdriveMediaMarkers": "Overdrive Media Markers для глав",
@@ -413,6 +434,7 @@
"LabelShowAll": "Показать все",
"LabelSize": "Размер",
"LabelSleepTimer": "Таймер сна",
"LabelSlug": "Слизень",
"LabelStart": "Начало",
"LabelStarted": "Начат",
"LabelStartedAt": "Начато В",
@@ -431,15 +453,18 @@
"LabelStatsMinutesListening": "Минут прослушано",
"LabelStatsOverallDays": "Всего дней",
"LabelStatsOverallHours": "Всего часов",
"LabelStatsWeekListening": "Недель прослушано",
"LabelStatsWeekListening": "Прослушано за неделю",
"LabelSubtitle": "Подзаголовок",
"LabelSupportedFileTypes": "Поддерживаемые типы файлов",
"LabelTag": "Тег",
"LabelTags": "Теги",
"LabelTagsAccessibleToUser": "Теги доступные для пользователя",
"LabelTagsNotAccessibleToUser": "Tags not Accessible to User",
"LabelTagsNotAccessibleToUser": "Теги не доступные для пользователя",
"LabelTasks": "Запущенные задачи",
"LabelTimeBase": "Time Base",
"LabelTheme": "Тема",
"LabelThemeDark": "Темная",
"LabelThemeLight": "Светлая",
"LabelTimeBase": "Временная база",
"LabelTimeListened": "Время прослушивания",
"LabelTimeListenedToday": "Время прослушивания сегодня",
"LabelTimeRemaining": "{0} осталось",
@@ -457,6 +482,7 @@
"LabelTrackFromMetadata": "Трек из Метаданных",
"LabelTracks": "Треков",
"LabelTracksMultiTrack": "Мультитрек",
"LabelTracksNone": "Нет треков",
"LabelTracksSingleTrack": "Один трек",
"LabelType": "Тип",
"LabelUnabridged": "Полное издание",
@@ -497,18 +523,22 @@
"MessageChapterErrorStartLtPrev": "Неверное время начала, должно быть больше или равно времени начала предыдущей главы",
"MessageChapterStartIsAfter": "Глава начинается после окончания аудиокниги",
"MessageCheckingCron": "Проверка cron...",
"MessageConfirmCloseFeed": "Вы уверены, что хотите закрыть этот канал?",
"MessageConfirmDeleteBackup": "Вы уверены, что хотите удалить бэкап для {0}?",
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
"MessageConfirmDeleteFile": "Это удалит файл из Вашей файловой системы. Вы уверены?",
"MessageConfirmDeleteLibrary": "Вы уверены, что хотите навсегда удалить библиотеку \"{0}\"?",
"MessageConfirmDeleteSession": "Вы уверены, что хотите удалить этот сеанс?",
"MessageConfirmForceReScan": "Вы уверены, что хотите принудительно выполнить повторное сканирование?",
"MessageConfirmMarkSeriesFinished": "Вы уверены, что хотите отметить все книги этой серии как законченные?",
"MessageConfirmMarkSeriesNotFinished": "Вы уверены, что хотите отметить все книги этой серии как незаконченные?",
"MessageConfirmRemoveAllChapters": "Are you sure you want to remove all chapters?",
"MessageConfirmMarkAllEpisodesFinished": "Вы уверены, что хотите отметить все эпизоды как завершенные?",
"MessageConfirmMarkAllEpisodesNotFinished": "Вы уверены, что хотите отметить все эпизоды как не завершенные?",
"MessageConfirmMarkSeriesFinished": "Вы уверены, что хотите отметить все книги этой серии как завершенные?",
"MessageConfirmMarkSeriesNotFinished": "Вы уверены, что хотите отметить все книги этой серии как не завершенные?",
"MessageConfirmRemoveAllChapters": "Вы уверены, что хотите удалить все главы?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Вы уверены, что хотите удалить коллекцию \"{0}\"?",
"MessageConfirmRemoveEpisode": "Вы уверены, что хотите удалить эпизод \"{0}\"?",
"MessageConfirmRemoveEpisodes": "Вы уверены, что хотите удалить {0} эпизодов?",
"MessageConfirmRemoveNarrator": "Are you sure you want to remove narrator \"{0}\"?",
"MessageConfirmRemoveNarrator": "Вы уверены, что хотите удалить чтеца \"{0}\"?",
"MessageConfirmRemovePlaylist": "Вы уверены, что хотите удалить плейлист \"{0}\"?",
"MessageConfirmRenameGenre": "Вы уверены, что хотите переименовать жанр \"{0}\" в \"{1}\" для всех элементов?",
"MessageConfirmRenameGenreMergeNote": "Примечание: Этот жанр уже существует, поэтому они будут объединены.",
@@ -516,7 +546,7 @@
"MessageConfirmRenameTag": "Вы уверены, что хотите переименовать тег \"{0}\" в \"{1}\" для всех элементов?",
"MessageConfirmRenameTagMergeNote": "Примечание: Этот тег уже существует, поэтому они будут объединены.",
"MessageConfirmRenameTagWarning": "Предупреждение! Похожий тег с другими начальными буквами уже существует \"{0}\".",
"MessageConfirmSendEbookToDevice": "Are you sure you want to send {0} ebook \"{1}\" to device \"{2}\"?",
"MessageConfirmSendEbookToDevice": "Вы уверены, что хотите отправить {0} e-книгу \"{1}\" на устройство \"{2}\"?",
"MessageDownloadingEpisode": "Эпизод скачивается",
"MessageDragFilesIntoTrackOrder": "Перетащите файлы для исправления порядка треков",
"MessageEmbedFinished": "Встраивание завершено!",
@@ -535,6 +565,8 @@
"MessageM4BFailed": "M4B Ошибка!",
"MessageM4BFinished": "M4B Завершено!",
"MessageMapChapterTitles": "Сопоставление названий глав с существующими главами аудиокниги без корректировки временных меток",
"MessageMarkAllEpisodesFinished": "Отметить все эпизоды как завершенные",
"MessageMarkAllEpisodesNotFinished": "Отметить все эпизоды как не завершенные",
"MessageMarkAsFinished": "Отметить, как завершенную",
"MessageMarkAsNotFinished": "Отметить, как не завершенную",
"MessageMatchBooksDescription": "попытается сопоставить книги в библиотеке с книгой из выбранного поставщика поиска и заполнить пустые детали и обложку. Не перезаписывает сведения.",
@@ -575,7 +607,6 @@
"MessagePlaylistCreateFromCollection": "Создать плейлист из коллекции",
"MessagePodcastHasNoRSSFeedForMatching": "Подкаст не имеет URL-адреса RSS-канала, который можно использовать для поиска",
"MessageQuickMatchDescription": "Заполняет пустые детали элемента и обложку первым результатом поиска из «{0}». Не перезаписывает сведения, если не включен параметр сервера 'Предпочитать метаданные поиска'.",
"MessageRemoveAllItemsWarning": "ПРЕДУПРЕЖДЕНИЕ! Это действие удалит все элементы библиотеки из базы данных, включая все сделанные обновления или совпадения. Ничего не произойдет с вашими фактическими файлами. Уверены?",
"MessageRemoveChapter": "Удалить главу",
"MessageRemoveEpisodes": "Удалить {0} эпизод(ов)",
"MessageRemoveFromPlayerQueue": "Удалить из очереди воспроизведения",
@@ -671,8 +702,8 @@
"ToastRemoveItemFromCollectionSuccess": "Элемент удален из коллекции",
"ToastRSSFeedCloseFailed": "Не удалось закрыть RSS-канал",
"ToastRSSFeedCloseSuccess": "RSS-канал закрыт",
"ToastSendEbookToDeviceFailed": "Failed to Send Ebook to device",
"ToastSendEbookToDeviceSuccess": "Ebook sent to device \"{0}\"",
"ToastSendEbookToDeviceFailed": "Не удалось отправить e-книгу на устройство",
"ToastSendEbookToDeviceSuccess": "E-книга отправлена на устройство \"{0}\"",
"ToastSeriesUpdateFailed": "Не удалось обновить серию",
"ToastSeriesUpdateSuccess": "Успешное обновление серии",
"ToastSessionDeleteFailed": "Не удалось удалить сеанс",
+63 -32
View File
@@ -55,7 +55,7 @@
"ButtonRemoveAll": "移除所有",
"ButtonRemoveAllLibraryItems": "移除所有媒体库项目",
"ButtonRemoveFromContinueListening": "从继续收听中删除",
"ButtonRemoveFromContinueReading": "Remove from Continue Reading",
"ButtonRemoveFromContinueReading": "从继续阅读中删除",
"ButtonRemoveSeriesFromContinueSeries": "从继续收听系列中删除",
"ButtonReScan": "重新扫描",
"ButtonReset": "重置",
@@ -74,7 +74,7 @@
"ButtonStartM4BEncode": "开始 M4B 编码",
"ButtonStartMetadataEmbed": "开始嵌入元数据",
"ButtonSubmit": "提交",
"ButtonTest": "Test",
"ButtonTest": "测试",
"ButtonUpload": "上传",
"ButtonUploadBackup": "上传备份",
"ButtonUploadCover": "上传封面",
@@ -98,11 +98,12 @@
"HeaderCurrentDownloads": "当前下载",
"HeaderDetails": "详情",
"HeaderDownloadQueue": "下载队列",
"HeaderEbookFiles": "Ebook Files",
"HeaderEmail": "Email",
"HeaderEmailSettings": "Email Settings",
"HeaderEbookFiles": "电子书文件",
"HeaderEmail": "邮箱",
"HeaderEmailSettings": "邮箱设置",
"HeaderEpisodes": "剧集",
"HeaderEReaderDevices": "E-Reader Devices",
"HeaderEreaderDevices": "Ereader 设备",
"HeaderEreaderSettings": "Ereader 设置",
"HeaderFiles": "文件",
"HeaderFindChapters": "查找章节",
"HeaderIgnoredFiles": "忽略的文件",
@@ -137,6 +138,7 @@
"HeaderRemoveEpisodes": "移除 {0} 剧集",
"HeaderRSSFeedGeneral": "RSS 详细信息",
"HeaderRSSFeedIsOpen": "RSS 源已打开",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderSavedMediaProgress": "保存媒体进度",
"HeaderSchedule": "计划任务",
"HeaderScheduleLibraryScans": "自动扫描媒体库",
@@ -154,6 +156,7 @@
"HeaderStatsRecentSessions": "历史会话",
"HeaderStatsTop10Authors": "前 10 位作者",
"HeaderStatsTop5Genres": "前 5 种流派",
"HeaderTableOfContents": "目录",
"HeaderTools": "工具",
"HeaderUpdateAccount": "更新帐户",
"HeaderUpdateAuthor": "更新作者",
@@ -183,6 +186,7 @@
"LabelAuthors": "作者",
"LabelAutoDownloadEpisodes": "自动下载剧集",
"LabelBackToUser": "返回到用户",
"LabelBackupLocation": "Backup Location",
"LabelBackupsEnableAutomaticBackups": "启用自动备份",
"LabelBackupsEnableAutomaticBackupsHelp": "备份保存到 /metadata/backups",
"LabelBackupsMaxBackupSize": "最大备份大小 (GB)",
@@ -199,11 +203,12 @@
"LabelClosePlayer": "关闭播放器",
"LabelCodec": "编解码",
"LabelCollapseSeries": "折叠系列",
"LabelCollection": "Collection",
"LabelCollections": "收藏",
"LabelComplete": "已完成",
"LabelConfirmPassword": "确认密码",
"LabelContinueListening": "继续收听",
"LabelContinueReading": "Continue Reading",
"LabelContinueReading": "继续阅读",
"LabelContinueSeries": "继续收听系列",
"LabelCover": "封面",
"LabelCoverImageURL": "封面图像 URL",
@@ -220,16 +225,19 @@
"LabelDirectory": "目录",
"LabelDiscFromFilename": "从文件名获取光盘",
"LabelDiscFromMetadata": "从元数据获取光盘",
"LabelDiscover": "Discover",
"LabelDownload": "下载",
"LabelDownloadNEpisodes": "Download {0} episodes",
"LabelDuration": "持续时间",
"LabelDurationFound": "找到持续时间:",
"LabelEbook": "Ebook",
"LabelEbooks": "Ebooks",
"LabelEbook": "电子书",
"LabelEbooks": "电子书",
"LabelEdit": "编辑",
"LabelEmail": "Email",
"LabelEmailSettingsFromAddress": "From Address",
"LabelEmailSettingsSecure": "Secure",
"LabelEmailSettingsSecureHelp": "If true the connection will use TLS when connecting to server. If false then TLS is used if server supports the STARTTLS extension. In most cases set this value to true if you are connecting to port 465. For port 587 or 25 keep it false. (from nodemailer.com/smtp/#authentication)",
"LabelEmail": "邮箱",
"LabelEmailSettingsFromAddress": "发件人地址",
"LabelEmailSettingsSecure": "安全",
"LabelEmailSettingsSecureHelp": "如果选是, 则连接将在连接到服务器时使用TLS. 如果选否, 则若服务器支持STARTTLS扩展, 则使用TLS. 在大多数情况下, 如果连接到端口465, 请将该值设置为是. 对于端口587或25, 请保持为否. (来自nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "测试地址",
"LabelEmbeddedCover": "嵌入封面",
"LabelEnable": "启用",
"LabelEnd": "结束",
@@ -248,13 +256,14 @@
"LabelFinished": "已听完",
"LabelFolder": "文件夹",
"LabelFolders": "文件夹",
"LabelFontScale": "字体比例",
"LabelFormat": "编码格式",
"LabelGenre": "流派",
"LabelGenres": "流派",
"LabelHardDeleteFile": "完全删除文件",
"LabelHasEbook": "Has ebook",
"LabelHasSupplementaryEbook": "Has supplementary ebook",
"LabelHost": "Host",
"LabelHasEbook": "有电子书",
"LabelHasSupplementaryEbook": "有补充电子书",
"LabelHost": "主机",
"LabelHour": "小时",
"LabelIcon": "图标",
"LabelIncludeInTracklist": "包含在音轨列表中",
@@ -279,12 +288,16 @@
"LabelLastSeen": "上次查看时间",
"LabelLastTime": "最近一次",
"LabelLastUpdate": "最近更新",
"LabelLayout": "布局",
"LabelLayoutSinglePage": "单页",
"LabelLayoutSplitPage": "分页",
"LabelLess": "较少",
"LabelLibrariesAccessibleToUser": "用户可访问的媒体库",
"LabelLibrary": "媒体库",
"LabelLibraryItem": "媒体库项目",
"LabelLibraryName": "媒体库名称",
"LabelLimit": "限制",
"LabelLineSpacing": "行间距",
"LabelListenAgain": "再次收听",
"LabelLogLevelDebug": "调试",
"LabelLogLevelInfo": "信息",
@@ -309,6 +322,7 @@
"LabelNewPassword": "新密码",
"LabelNextBackupDate": "下次备份日期",
"LabelNextScheduledRun": "下次任务运行",
"LabelNoEpisodesSelected": "No episodes selected",
"LabelNotes": "注释",
"LabelNotFinished": "未听完",
"LabelNotificationAppriseURL": "通知 URL(s)",
@@ -340,18 +354,18 @@
"LabelPodcast": "播客",
"LabelPodcasts": "播客",
"LabelPodcastType": "播客类型",
"LabelPort": "Port",
"LabelPort": "端口",
"LabelPrefixesToIgnore": "忽略的前缀 (不区分大小写)",
"LabelPreventIndexing": "防止 iTunes 和 Google 播客目录对你的源进行索引",
"LabelPrimaryEbook": "Primary ebook",
"LabelPrimaryEbook": "主电子书",
"LabelProgress": "进度",
"LabelProvider": "供应商",
"LabelPubDate": "出版日期",
"LabelPublisher": "出版商",
"LabelPublishYear": "发布年份",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRead": "阅读",
"LabelReadAgain": "再次阅读",
"LabelReadEbookWithoutProgress": "阅读电子书而不保存进度",
"LabelRecentlyAdded": "最近添加",
"LabelRecentSeries": "最近添加系列",
"LabelRecommended": "推荐内容",
@@ -368,25 +382,32 @@
"LabelSearchTitle": "搜索标题",
"LabelSearchTitleOrASIN": "搜索标题或 ASIN",
"LabelSeason": "季",
"LabelSendEbookToDevice": "Send Ebook to...",
"LabelSelectAllEpisodes": "Select all episodes",
"LabelSelectEpisodesShowing": "Select {0} episodes showing",
"LabelSendEbookToDevice": "发送电子书到...",
"LabelSequence": "序列",
"LabelSeries": "系列",
"LabelSeriesName": "系列名称",
"LabelSeriesProgress": "系列进度",
"LabelSetEbookAsPrimary": "Set as primary",
"LabelSetEbookAsSupplementary": "Set as supplementary",
"LabelSettingsAudiobooksOnly": "Audiobooks only",
"LabelSettingsAudiobooksOnlyHelp": "Enabling this setting will ignore ebook files unless they are inside an audiobook folder in which case they will be set as supplementary ebooks",
"LabelSetEbookAsPrimary": "设置为主",
"LabelSetEbookAsSupplementary": "设置为补充",
"LabelSettingsAudiobooksOnly": "只有有声读物",
"LabelSettingsAudiobooksOnlyHelp": "启用此设置将忽略电子书文件, 除非它们位于有声读物文件夹中, 在这种情况下, 它们将被设置为补充电子书",
"LabelSettingsBookshelfViewHelp": "带有木架子的拟物化设计",
"LabelSettingsChromecastSupport": "Chromecast 支持",
"LabelSettingsDateFormat": "日期格式",
"LabelSettingsDisableWatcher": "禁用监视程序",
"LabelSettingsDisableWatcherForLibrary": "禁用媒体库的文件夹监视程序",
"LabelSettingsDisableWatcherHelp": "检测到文件更改时禁用自动添加和更新项目. *需要重启服务器",
"LabelSettingsEnableWatcher": "Enable Watcher",
"LabelSettingsEnableWatcherForLibrary": "Enable folder watcher for library",
"LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
"LabelSettingsExperimentalFeatures": "实验功能",
"LabelSettingsExperimentalFeaturesHelp": "开发中的功能需要你的反馈并帮助测试. 点击打开 github 讨论.",
"LabelSettingsFindCovers": "查找封面",
"LabelSettingsFindCoversHelp": "如果你的有声读物在文件夹中没有嵌入封面或封面图像, 扫描将尝试查找封面.<br>注意: 这将延长扫描时间",
"LabelSettingsHideSingleBookSeries": "Hide single book series",
"LabelSettingsHideSingleBookSeriesHelp": "Series that have a single book will be hidden from the series page and home page shelves.",
"LabelSettingsHomePageBookshelfView": "首页使用书架视图",
"LabelSettingsLibraryBookshelfView": "媒体库使用书架视图",
"LabelSettingsOverdriveMediaMarkers": "对章节使用 Overdrive 媒体标记",
@@ -413,6 +434,7 @@
"LabelShowAll": "全部显示",
"LabelSize": "文件大小",
"LabelSleepTimer": "睡眠定时",
"LabelSlug": "Slug",
"LabelStart": "开始",
"LabelStarted": "开始于",
"LabelStartedAt": "从这开始",
@@ -439,6 +461,9 @@
"LabelTagsAccessibleToUser": "用户可访问的标签",
"LabelTagsNotAccessibleToUser": "用户无法访问标签",
"LabelTasks": "正在运行的任务",
"LabelTheme": "主题",
"LabelThemeDark": "黑暗",
"LabelThemeLight": "明亮",
"LabelTimeBase": "时间基准",
"LabelTimeListened": "收听时间",
"LabelTimeListenedToday": "今日收听的时间",
@@ -457,6 +482,7 @@
"LabelTrackFromMetadata": "从源数据获取音轨",
"LabelTracks": "音轨",
"LabelTracksMultiTrack": "多轨",
"LabelTracksNone": "No tracks",
"LabelTracksSingleTrack": "单轨",
"LabelType": "类型",
"LabelUnabridged": "未删节",
@@ -497,18 +523,22 @@
"MessageChapterErrorStartLtPrev": "无效的开始时间, 必须大于或等于上一章节的开始时间",
"MessageChapterStartIsAfter": "章节开始是在有声读物结束之后",
"MessageCheckingCron": "检查计划任务...",
"MessageConfirmCloseFeed": "Are you sure you want to close this feed?",
"MessageConfirmDeleteBackup": "你确定要删除备份 {0}?",
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
"MessageConfirmDeleteFile": "这将从文件系统中删除该文件. 你确定吗?",
"MessageConfirmDeleteLibrary": "你确定要永久删除媒体库 \"{0}\"?",
"MessageConfirmDeleteSession": "你确定要删除此会话吗?",
"MessageConfirmForceReScan": "你确定要强制重新扫描吗?",
"MessageConfirmMarkAllEpisodesFinished": "Are you sure you want to mark all episodes as finished?",
"MessageConfirmMarkAllEpisodesNotFinished": "Are you sure you want to mark all episodes as not finished?",
"MessageConfirmMarkSeriesFinished": "你确定要将此系列中的所有书籍都标记为已听完吗?",
"MessageConfirmMarkSeriesNotFinished": "你确定要将此系列中的所有书籍都标记为未听完吗?",
"MessageConfirmRemoveAllChapters": "你确定要移除所有章节吗?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "您确定要移除收藏 \"{0}\"?",
"MessageConfirmRemoveEpisode": "您确定要移除剧集 \"{0}\"?",
"MessageConfirmRemoveEpisodes": "你确定要移除 {0} 剧集?",
"MessageConfirmRemoveNarrator": "Are you sure you want to remove narrator \"{0}\"?",
"MessageConfirmRemoveNarrator": "你确定要删除演播者 \"{0}\"?",
"MessageConfirmRemovePlaylist": "你确定要移除播放列表 \"{0}\"?",
"MessageConfirmRenameGenre": "你确定要将所有项目流派 \"{0}\" 重命名到 \"{1}\"?",
"MessageConfirmRenameGenreMergeNote": "注意: 该流派已经存在, 因此它们将被合并.",
@@ -516,7 +546,7 @@
"MessageConfirmRenameTag": "你确定要将所有项目标签 \"{0}\" 重命名到 \"{1}\"?",
"MessageConfirmRenameTagMergeNote": "注意: 该标签已经存在, 因此它们将被合并.",
"MessageConfirmRenameTagWarning": "警告! 已经存在有大小写不同的类似标签 \"{0}\".",
"MessageConfirmSendEbookToDevice": "Are you sure you want to send {0} ebook \"{1}\" to device \"{2}\"?",
"MessageConfirmSendEbookToDevice": "你确定要发送 {0} 电子书 \"{1}\" 到设备 \"{2}\"?",
"MessageDownloadingEpisode": "正在下载剧集",
"MessageDragFilesIntoTrackOrder": "将文件拖动到正确的音轨顺序",
"MessageEmbedFinished": "嵌入完成!",
@@ -535,6 +565,8 @@
"MessageM4BFailed": "M4B 失败!",
"MessageM4BFinished": "M4B 完成!",
"MessageMapChapterTitles": "将章节标题映射到现有的有声读物章节, 无需调整时间戳",
"MessageMarkAllEpisodesFinished": "Mark all episodes finished",
"MessageMarkAllEpisodesNotFinished": "Mark all episodes not finished",
"MessageMarkAsFinished": "标记为已听完",
"MessageMarkAsNotFinished": "标记为未听完",
"MessageMatchBooksDescription": "尝试将媒体库中的图书与所选搜索提供商的图书进行匹配, 并填写空白的详细信息和封面. 不覆盖详细信息.",
@@ -575,7 +607,6 @@
"MessagePlaylistCreateFromCollection": "从收藏中创建播放列表",
"MessagePodcastHasNoRSSFeedForMatching": "播客没有可用于匹配 RSS 源的 url",
"MessageQuickMatchDescription": "使用来自 '{0}' 的第一个匹配结果填充空白详细信息和封面. 除非启用 '首选匹配元数据' 服务器设置, 否则不会覆盖详细信息.",
"MessageRemoveAllItemsWarning": "警告! 此操作将从数据库中删除所有的媒体库项, 包括您所做的任何更新或匹配. 这不会对实际文件产生任何影响. 你确定吗?",
"MessageRemoveChapter": "移除章节",
"MessageRemoveEpisodes": "移除 {0} 剧集",
"MessageRemoveFromPlayerQueue": "从播放队列中移除",
@@ -671,8 +702,8 @@
"ToastRemoveItemFromCollectionSuccess": "项目已从收藏中删除",
"ToastRSSFeedCloseFailed": "关闭 RSS 源失败",
"ToastRSSFeedCloseSuccess": "RSS 源已关闭",
"ToastSendEbookToDeviceFailed": "Failed to send Ebook to device",
"ToastSendEbookToDeviceSuccess": "Ebook sent to device \"{0}\"",
"ToastSendEbookToDeviceFailed": "发送电子书到设备失败",
"ToastSendEbookToDeviceSuccess": "电子书已经发送到设备 \"{0}\"",
"ToastSeriesUpdateFailed": "更新系列失败",
"ToastSeriesUpdateSuccess": "系列已更新",
"ToastSessionDeleteFailed": "删除会话失败",

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