Compare commits

...
Author SHA1 Message Date
advplyr 4fb9f6b92d Version bump 0.12.0-beta 2026-02-09 17:28:57 -06:00
advplyrandGitHub fabd579247 Merge pull request #1797 from weblate/weblate-audiobookshelf-abs-mobile-app
Translations update from Hosted Weblate
2026-02-09 17:14:58 -06:00
Yusuke SakaiandHosted Weblate b4ee3b80a8 Translated using Weblate (Japanese)
Currently translated at 54.8% (205 of 374 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/ja/
2026-02-10 00:14:41 +01:00
Bjorn JorgensenandHosted Weblate a75bdce9b4 Translated using Weblate (Danish)
Currently translated at 97.0% (363 of 374 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/da/
2026-02-10 00:14:41 +01:00
Luis LandeiroandHosted Weblate d48ac952a5 Translated using Weblate (Portuguese (Brazil))
Currently translated at 98.1% (367 of 374 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/pt_BR/
2026-02-10 00:14:40 +01:00
advplyrandGitHub d83b2e032b Merge pull request #1749 from danyhoron/master
feat: implement download queue on iOS
2026-02-09 17:14:30 -06:00
advplyr 46c9c3f006 Fix downloading page filename overflow 2026-02-08 17:06:23 -06:00
advplyrandGitHub 4199add608 Merge pull request #1738 from eagleeyetom/chromecast-volume-fix-updated
Android cast: stabilize MediaSession volume handling; simplify Google…
2026-02-08 16:37:15 -06:00
advplyrandGitHub 8311643e73 Merge pull request #1774 from FreedomBen/dont-queue-background-display-events
Significantly improve Android UI performance when resuming from background
2026-02-08 16:08:49 -06:00
advplyrandGitHub 7775d5216f Merge pull request #1758 from weblate/weblate-audiobookshelf-abs-mobile-app
Translations update from Hosted Weblate
2026-02-03 17:27:10 -06:00
Lluís FornsandHosted Weblate 6f2fc6b5c1 Translated using Weblate (Catalan)
Currently translated at 79.6% (298 of 374 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/ca/
2026-02-03 20:10:04 +01:00
NapitaukiandHosted Weblate 235cac7ab4 Translated using Weblate (Finnish)
Currently translated at 100.0% (374 of 374 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/fi/
2026-02-03 20:10:04 +01:00
dapitch666andHosted Weblate 93b4acfe13 Translated using Weblate (French)
Currently translated at 100.0% (374 of 374 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/fr/
2026-02-02 20:02:04 +00:00
Jan-Eric MyhrgrenandHosted Weblate bd7c73c48d Translated using Weblate (Swedish)
Currently translated at 100.0% (374 of 374 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2026-02-02 20:02:02 +00:00
Dawid KuźnickiandHosted Weblate 45ecca7ce4 Translated using Weblate (Polish)
Currently translated at 96.7% (362 of 374 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/pl/
2026-02-02 20:02:00 +00:00
FiendFEARingandHosted Weblate 0a8c67cf13 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (374 of 374 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/zh_Hans/
2026-02-02 20:01:59 +00:00
ugyesandHosted Weblate 316d3d8324 Translated using Weblate (Hungarian)
Currently translated at 100.0% (374 of 374 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/hu/
2026-02-02 20:01:57 +00:00
enoshandHosted Weblate 182d45b07c Translated using Weblate (Hebrew)
Currently translated at 94.9% (355 of 374 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/he/
2026-02-02 20:01:55 +00:00
Delta UmhöferandHosted Weblate 58d8afca38 Translated using Weblate (German)
Currently translated at 100.0% (374 of 374 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/de/
2026-02-01 00:26:04 +01:00
dv4yGY2UandHosted Weblate 136709d7ae Translated using Weblate (Turkish)
Currently translated at 98.8% (359 of 363 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/tr/
2026-02-01 00:26:04 +01:00
bittin1ddc447d824349b2andHosted Weblate b0d02aa769 Translated using Weblate (Swedish)
Currently translated at 100.0% (363 of 363 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2026-02-01 00:26:03 +01:00
Samuel GuerreroandHosted Weblate ca66a45ba4 Translated using Weblate (Spanish)
Currently translated at 99.1% (360 of 363 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/es/
2026-02-01 00:26:02 +01:00
FiendFEARingandHosted Weblate d7d4114ee6 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (363 of 363 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/zh_Hans/
2026-02-01 00:26:02 +01:00
MantasandHosted Weblate e589c0a7ea Translated using Weblate (Lithuanian)
Currently translated at 52.3% (189 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/lt/
2026-02-01 00:26:01 +01:00
Kabika82andHosted Weblate eb2625a2df Translated using Weblate (Hungarian)
Currently translated at 100.0% (361 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/hu/
2026-02-01 00:26:01 +01:00
N VisiandHosted Weblate aacbacf557 Translated using Weblate (Japanese)
Currently translated at 55.9% (202 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/ja/
2026-02-01 00:26:00 +01:00
Henrik LyngeandHosted Weblate 0a7b129db2 Translated using Weblate (Danish)
Currently translated at 100.0% (361 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/da/
2026-02-01 00:25:59 +01:00
herny ucetandHosted Weblate c927264b62 Translated using Weblate (Slovak)
Currently translated at 100.0% (361 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sk/
2026-02-01 00:25:59 +01:00
xxzp3andHosted Weblate 808225351e Translated using Weblate (Danish)
Currently translated at 99.1% (358 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/da/
2026-02-01 00:25:58 +01:00
J. LavoieandHosted Weblate 40ee8d5221 Translated using Weblate (Italian)
Currently translated at 100.0% (361 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/it/
2026-02-01 00:25:58 +01:00
J. LavoieandHosted Weblate 8cc80e8378 Translated using Weblate (French)
Currently translated at 100.0% (361 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/fr/
2026-02-01 00:25:57 +01:00
MarcinandHosted Weblate db5f249c14 Translated using Weblate (Polish)
Currently translated at 99.7% (360 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/pl/
2026-02-01 00:25:56 +01:00
MarioandHosted Weblate e86028e577 Translated using Weblate (German)
Currently translated at 100.0% (361 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/de/
2026-02-01 00:25:56 +01:00
Jan-Eric MyhrgrenandHosted Weblate 54bed2bee1 Translated using Weblate (Swedish)
Currently translated at 100.0% (361 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2026-02-01 00:25:55 +01:00
Petri HämäläinenandHosted Weblate 1de78165d0 Translated using Weblate (Finnish)
Currently translated at 100.0% (361 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/fi/
2026-02-01 00:25:55 +01:00
Ivan SmoliakovandHosted Weblate 4c9ed5e2bf Translated using Weblate (Russian)
Currently translated at 100.0% (361 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/ru/
2026-02-01 00:25:54 +01:00
lambolightingandHosted Weblate a036a8bda6 Translated using Weblate (Greek)
Currently translated at 60.6% (219 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/el/
2026-02-01 00:25:53 +01:00
biuklijaandHosted Weblate 5a482e603e Translated using Weblate (Croatian)
Currently translated at 100.0% (361 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/hr/
2026-02-01 00:25:53 +01:00
FiendFEARingandHosted Weblate d5eb8a341e Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (361 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/zh_Hans/
2026-02-01 00:25:52 +01:00
Максим ГорпинічandHosted Weblate 9c74c47448 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (361 of 361 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/uk/
2026-02-01 00:25:51 +01:00
AhetekandHosted Weblate 8584bebe6c Translated using Weblate (Polish)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/pl/
2026-02-01 00:25:50 +01:00
advplyrandGitHub 39cd6c65f2 Merge pull request #1763 from randomdude583/fix/android-aac-seek-issue
Enable constant bitrate seeking to fix AAC seek reset in ExoPlayer
2026-01-31 17:25:39 -06:00
advplyrandGitHub 1056541dd2 Merge pull request #1772 from KiwiHour/sort-by-progress
added 'sort by progress' entries
2026-01-30 17:31:26 -06:00
advplyrandGitHub f9a3a4a218 Merge pull request #1775 from anstosa/ansel/playnextepisodesort
Play Next Episode correctly for serial podcasts
2026-01-30 17:11:54 -06:00
advplyrandGitHub 80bafd9281 Merge pull request #1755 from sir-wilhelm/localize
Localized various strings.
2026-01-30 16:59:16 -06:00
advplyr c06c17d3ae Update HeaderWelcome to include username 2026-01-30 16:50:40 -06:00
advplyr 2a7969fe68 Fix backButton dialog i18n strings 2026-01-30 16:47:51 -06:00
advplyr decda748ba Fix unnecessary $ in getString call 2026-01-30 16:22:57 -06:00
advplyrandGitHub 427f858be5 Merge pull request #1767 from FreedomBen/add-more-backwards-forward-options
Expand time interval options for jump controls
2026-01-29 17:38:42 -06:00
advplyr 1043fb3f3e fix i18n string order 2026-01-29 17:33:58 -06:00
advplyr 7c5e8cb046 Revert audio player playerControls padding 2026-01-29 17:32:34 -06:00
advplyr 5fb8baa186 Remove icons from jump options, remove unused computed properties 2026-01-29 17:17:29 -06:00
advplyr f63b04451b Update jump label to only show on fullscreen audio player 2026-01-29 17:08:12 -06:00
advplyr a80722ff79 Fix auth re-login error updating vuex state 2026-01-29 16:41:16 -06:00
Daniel HoronandGitHub 9d5cbd37c8 Merge branch 'advplyr:master' into master 2026-01-29 17:35:37 +02:00
KiwiHour fada8fccb1 made order-by menu scrollable 2026-01-12 00:07:34 +00:00
Ansel Santosa 9d650019cd Play Next Episode correctly for serial podcasts
The default episode sort correctly takes podcast type into account (oldest to newest for serial, newest to oldest for episodic). However the Play Next Episode button uses episodic sorting for all podcast types. This minimal change fixes that.
2026-01-07 22:19:27 -08:00
KiwiHourandGitHub 915f3c88bc Removed whitespaces around LabelLibrarySortByProgress 2026-01-06 01:48:36 +00:00
Benjamin Porter 140bc7fbc5 Skip progress updates when backgrounded
When we are backgrounded, these queue events build up and can cause
performance issues as the queue is processed.  We don't need to process
these when backgrounded, so skip them.

Also add small delay when resuming for webview to load before sending it
update events
2026-01-05 16:58:10 -07:00
KiwiHour 2a12c1e811 added 'sort by progress' entries, strings added for en-us 2026-01-05 23:50:15 +00:00
Benjamin Porter 5250adb36e Don't queue display events while backgrounded
When we are backgrounded, don't queue display events.  This prevents
a hang and sluggish replay of display events once we are re-foregrounded
later
2026-01-04 10:03:50 -07:00
Benjamin Porter f548163689 Make jump labels compatible with i18n/translation 2025-12-29 17:08:37 -07:00
Benjamin Porter 589ffcecca Move jump back/forward labels below the icon
Move jump back/forward labels below the icon.  Previously they
were on the side which looked a little awkward
2025-12-29 14:09:01 -07:00
Benjamin Porter d9c591b0ea Expand time interval options for Make jump controls
Fixes #1445

- Added additional options for customizing jump forward/backward.  Instead of just 5,
  10, and 30 seconds, we now have 5s, 10s, 15s, 30s, 60s, 2m, and 5m.
- Switched the jump interval to a list in the settings menu for better UX
- Reordered "Disable auto rewind time" for aesthetics in settings menu (it looked
  out of place after backwards time and forwards time were turned to dropdowns

The only downside of this (afaict), and what created the biggest challenge,
is the lack of numeric glyphs in the Material Symbols font.  They only have 5, 10,
and 30, which we were previously using.  Given that they don't have others, that means
we had to change strategies for displaying.  I switched all to generic backward and
forward icons and added the time interval as a label next to it so the user can still
tell at a glance what the setting is.  For consistency we don't use the numbered
glyphs anymore.  For more info on the Material Symbols font, see:
https://fonts.google.com/icons?icon.query=forward

However this does feel like two steps forward, one step back, though I can't think
of good options.  Other possibility would be to create SVGs, though I'm not skilled
enough to do that.  Personally this feels like a good compromise, but others will
probably differ. I considered using the numbered glyphs when the selected value was
5, 10, or 30, but when testing I found the inconsistency jarring and kind of janky.
2025-12-29 12:55:18 -07:00
sir-wilhelm 462021225f Localized various strings.
Confirm title, corresponding messages, welcome, and media type dropdown.
2025-12-28 10:36:17 -06:00
Alex 3f0bc74c21 Enable constant bitrate seeking to fix AAC seek reset in ExoPlayer 2025-12-24 13:03:27 -06:00
advplyr b2c2b625e3 Cleanup ItemSearchCard remove unused match properties, add LabelByAuthor string 2025-12-16 17:44:34 -06:00
advplyrandGitHub d3bd3427e3 Merge pull request #1733 from weblate/weblate-audiobookshelf-abs-mobile-app
Translations update from Hosted Weblate
2025-12-14 16:35:05 -06:00
lambolightingandHosted Weblate a040a73174 Translated using Weblate (Greek)
Currently translated at 24.4% (88 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/el/
2025-12-14 22:00:20 +00:00
lambolightingandHosted Weblate 332d9f203e Translated using Weblate (Greek)
Currently translated at 8.3% (30 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/el/
2025-12-12 23:13:10 +00:00
Lucas JaksysandHosted Weblate 2d97329836 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/pt_BR/
2025-12-12 23:13:10 +00:00
kfctatertotandHosted Weblate 730d030623 Translated using Weblate (Arabic)
Currently translated at 99.7% (359 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/ar/
2025-12-12 23:13:09 +00:00
kfctatertotandHosted Weblate 2e29daab1d Translated using Weblate (Spanish)
Currently translated at 99.7% (359 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/es/
2025-12-12 23:13:08 +00:00
zard KimandHosted Weblate d7b48b4f61 Translated using Weblate (Korean)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/ko/
2025-12-12 23:13:08 +00:00
advplyrandHosted Weblate 24b98f10e3 Added translation using Weblate (Greek) 2025-12-12 23:13:07 +00:00
Igor DobračaandHosted Weblate 5fd6f5e4cc Translated using Weblate (Croatian)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/hr/
2025-12-12 23:13:06 +00:00
thehijackerandHosted Weblate c21af649c3 Translated using Weblate (Slovenian)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sl/
2025-12-12 23:13:06 +00:00
Alessandro BurzioandHosted Weblate 1d8a23922e Translated using Weblate (Italian)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/it/
2025-12-12 23:13:05 +00:00
J. LavoieandHosted Weblate 68893ab1f4 Translated using Weblate (German)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/de/
2025-12-12 23:13:04 +00:00
Petri HämäläinenandHosted Weblate dcf172bd98 Translated using Weblate (Finnish)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/fi/
2025-12-12 23:13:04 +00:00
J. LavoieandHosted Weblate 6dd466a9ce Translated using Weblate (French)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/fr/
2025-12-12 23:13:03 +00:00
advplyrandHosted Weblate ca222d4110 Added translation using Weblate (Icelandic) 2025-12-12 23:13:02 +00:00
Ivan SmoliakovandHosted Weblate c9af9582e3 Translated using Weblate (Russian)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/ru/
2025-12-12 23:13:01 +00:00
zard KimandHosted Weblate a3028127ce Translated using Weblate (Korean)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/ko/
2025-12-12 23:13:01 +00:00
PlazecandHosted Weblate 23133194b2 Translated using Weblate (Czech)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/cs/
2025-12-12 23:13:00 +00:00
Renaldas RepečkaandHosted Weblate b84555db6c Translated using Weblate (Lithuanian)
Currently translated at 51.9% (187 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/lt/
2025-12-12 23:12:59 +00:00
ArturandHosted Weblate 229298df1b Translated using Weblate (Polish)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/pl/
2025-12-12 23:12:59 +00:00
Cèlia GarrigaandHosted Weblate fb270cb50b Translated using Weblate (Catalan)
Currently translated at 78.0% (281 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/ca/
2025-12-12 23:12:58 +00:00
B0raxandHosted Weblate a861c880ba Translated using Weblate (German)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/de/
2025-12-12 23:12:57 +00:00
Jan-Eric MyhrgrenandHosted Weblate 9712d3f527 Translated using Weblate (Swedish)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-12-12 23:12:57 +00:00
ugyesandHosted Weblate 51a7ce41de Translated using Weblate (Hungarian)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/hu/
2025-12-12 23:12:56 +00:00
Максим ГорпинічandHosted Weblate 4c657c66d0 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/uk/
2025-12-12 23:12:55 +00:00
FiendFEARingandHosted Weblate 61c3fafd94 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (360 of 360 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/zh_Hans/
2025-12-12 23:12:54 +00:00
advplyr bab95530c8 Update WrappingMarquee to use textContent 2025-12-12 17:12:39 -06:00
Dani Horon 68afba45bc feat: implement download queue on iOS 2025-12-10 17:55:43 +02:00
eagleeyetom 1a52f19b32 Android cast: stabilize MediaSession volume handling; simplify Google Cast volume 2025-11-27 00:32:33 +01:00
advplyr aaef0a7e8d Update github issue templates with 0.11.0 2025-11-25 17:28:10 -06:00
advplyr 02d9023f9d Merge branch 'master' of https://github.com/advplyr/audiobookshelf-app 2025-11-24 14:52:04 -06:00
advplyr 59a27cdd4d Add Turkish language option #1734 2025-11-24 14:51:59 -06:00
60 changed files with 1225 additions and 273 deletions
+2 -2
View File
@@ -72,10 +72,10 @@ body:
description: Please ensure your app is up to date. *If you are using a 3rd-party app, please reach out to them directly.*
multiple: true
options:
- 'Android App - 0.11.0'
- 'iOS App - 0.11.0'
- 'Android App - 0.10.1'
- 'iOS App - 0.10.1'
- 'Android App - 0.10.0'
- 'iOS App - 0.10.0'
validations:
required: true
- type: dropdown
+2 -2
View File
@@ -43,10 +43,10 @@ body:
description: Please ensure your app is up to date. *If you are using a 3rd-party app, please reach out to them directly.*
multiple: true
options:
- 'Android App - 0.11.0'
- 'iOS App - 0.11.0'
- 'Android App - 0.10.1'
- 'iOS App - 0.10.1'
- 'Android App - 0.10.0'
- 'iOS App - 0.10.0'
validations:
required: true
- type: textarea
+2 -2
View File
@@ -36,8 +36,8 @@ android {
applicationId "com.audiobookshelf.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 115
versionName "0.11.0-beta"
versionCode 116
versionName "0.12.0-beta"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
manifestPlaceholders = [
"appAuthRedirectScheme": "com.audiobookshelf.app"
@@ -527,4 +527,18 @@ constructor(private val playerNotificationService: PlayerNotificationService) {
checkAutoSleepTimer()
}
/**
* Sends the current sleep timer state to the client.
* Called when app resumes from background to sync UI state.
*/
fun sendCurrentSleepTimerState() {
if (sleepTimerRunning) {
val timeRemaining = getSleepTimerTimeRemainingSeconds(getPlaybackSpeed())
playerNotificationService.clientEventEmitter?.onSleepTimerSet(timeRemaining, isAutoSleepTimer)
} else {
// No timer running - send 0 to clear any stale UI state
playerNotificationService.clientEventEmitter?.onSleepTimerSet(0, false)
}
}
}
@@ -3,6 +3,7 @@ package com.audiobookshelf.app.player
import android.annotation.SuppressLint
import android.os.Looper
import android.util.Log
import kotlin.math.roundToInt
import android.view.Surface
import android.view.SurfaceHolder
import android.view.SurfaceView
@@ -53,6 +54,10 @@ class CastPlayer(var castContext: CastContext) : BasePlayer() {
private var myCurrentTrackGroups: TrackGroupArray
private var myCurrentTrackSelections: TrackSelectionArray
// Cache for pending volume to handle async setVolume
private var pendingVolume: Int? = null
private var pendingVolumeSetAt: Long = 0L
var currentMediaItems:List<MediaItem> = mutableListOf()
var remoteMediaClient:RemoteMediaClient? = null
var sessionAvailabilityListener:SessionAvailabilityListener? = null
@@ -864,12 +869,24 @@ class CastPlayer(var castContext: CastContext) : BasePlayer() {
}
override fun getDeviceVolume(): Int {
// Short-lived cache without even-value quantization
val now = System.currentTimeMillis()
if (pendingVolume != null && (now - pendingVolumeSetAt) < 100) {
return pendingVolume!!
}
val session = castContext.sessionManager.currentCastSession
return if (session != null && !session.isMute) {
(session.volume * 100).toInt()
val vol = if (session != null && !session.isMute) {
(session.volume * 100).roundToInt().coerceIn(0, 100)
} else {
0
}
if (pendingVolume != null && vol == pendingVolume) {
pendingVolume = null
}
return vol
}
override fun isDeviceMuted(): Boolean {
@@ -881,22 +898,28 @@ class CastPlayer(var castContext: CastContext) : BasePlayer() {
val session = castContext.sessionManager.currentCastSession
try {
val clamped = volume.coerceIn(0, 100)
session?.volume = clamped / 100.0
val target = (clamped / 100.0).let { kotlin.math.round(it * 100.0) / 100.0 }
// Cache for 100ms to return in getDeviceVolume during async period
pendingVolume = clamped
pendingVolumeSetAt = System.currentTimeMillis()
session?.setVolume(target)
} catch (e: Exception) {
Log.e(tag, "Failed to set cast device volume", e)
}
}
override fun increaseDeviceVolume() {
val currentVolume = getDeviceVolume()
val newVolume = (currentVolume + 1).coerceAtMost(100)
setDeviceVolume(newVolume)
val current = getDeviceVolume()
val next = current + 1
setDeviceVolume(next.coerceAtMost(100))
}
override fun decreaseDeviceVolume() {
val currentVolume = getDeviceVolume()
val newVolume = (currentVolume - 1).coerceAtLeast(0)
setDeviceVolume(newVolume)
val current = getDeviceVolume()
val next = current - 1
setDeviceVolume(next.coerceAtLeast(0))
}
override fun setDeviceMuted(muted: Boolean) {
@@ -480,6 +480,8 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
val dataSourceFactory = DefaultDataSource.Factory(ctx)
val extractorsFactory = DefaultExtractorsFactory()
extractorsFactory.setConstantBitrateSeekingEnabled(true)
if (DeviceManager.deviceData.deviceSettings?.enableMp3IndexSeeking == true) {
// @see
// https://exoplayer.dev/troubleshooting.html#why-is-seeking-inaccurate-in-some-mp3-files
@@ -494,6 +496,8 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
val dataSourceFactory = DefaultHttpDataSource.Factory()
val extractorsFactory = DefaultExtractorsFactory()
extractorsFactory.setConstantBitrateSeekingEnabled(true)
if (DeviceManager.deviceData.deviceSettings?.enableMp3IndexSeeking == true) {
// @see
// https://exoplayer.dev/troubleshooting.html#why-is-seeking-inaccurate-in-some-mp3-files
@@ -732,32 +736,21 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
}
private fun setMediaSessionToCastVolume() {
val currentVol = try { castPlayer?.getDeviceVolume() ?: 0 } catch (e: Exception) { 0 }
val currentVol = try { castPlayer?.getDeviceVolume() ?: 0 } catch (_: Exception) { 0 }
val provider = object : VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, 100, currentVol) {
override fun onSetVolumeTo(volume: Int) {
// Clamp, update UI immediately, then send to device
val clamped = volume.coerceIn(0, 100)
try {
castPlayer?.setDeviceVolume(clamped)
val actual = castPlayer?.getDeviceVolume() ?: clamped
setCurrentVolume(actual)
} catch (_: Exception) {}
setCurrentVolume(clamped)
try { castPlayer?.setDeviceVolume(clamped) } catch (_: Exception) {}
}
override fun onAdjustVolume(direction: Int) {
val current = try { castPlayer?.getDeviceVolume() ?: currentVolume } catch (_: Exception) { currentVolume }
val step = if (direction > 0) 1 else if (direction < 0) -1 else 0
if (step == 0) return
var target = (current + step).coerceIn(0, 100)
try {
castPlayer?.setDeviceVolume(target)
var actual = castPlayer?.getDeviceVolume() ?: current
// If device ignored tiny step, try nudging up to 3 steps total.
if (actual == current) {
target = (current + step * 3).coerceIn(0, 100)
castPlayer?.setDeviceVolume(target)
actual = castPlayer?.getDeviceVolume() ?: current
}
setCurrentVolume(actual)
} catch (_: Exception) {}
// Use Android-provided step (1, 0, +1). Clamp, update UI immediately, then send.
val current = currentVolume
val target = (current + direction).coerceIn(0, 100)
setCurrentVolume(target)
try { castPlayer?.setDeviceVolume(target) } catch (_: Exception) {}
}
}
remoteVolumeProvider = provider
@@ -33,6 +33,9 @@ class AbsAudioPlayer : Plugin() {
private var isCastAvailable:Boolean = false
// Track foreground state to avoid flooding WebView with events while backgrounded
private var isInForeground: Boolean = true
override fun load() {
mainActivity = (activity as MainActivity)
apiHandler = ApiHandler(mainActivity)
@@ -60,6 +63,8 @@ class AbsAudioPlayer : Plugin() {
}
override fun onMetadata(metadata: PlaybackMetadata) {
// Skip frequent metadata updates when app is backgrounded to prevent event queue buildup
if (!isInForeground) return
notifyListeners("onMetadata", JSObject(jacksonMapper.writeValueAsString(metadata)))
}
@@ -68,6 +73,8 @@ class AbsAudioPlayer : Plugin() {
}
override fun onSleepTimerSet(sleepTimeRemaining: Int, isAutoSleepTimer:Boolean) {
// Skip sleep timer updates when app is backgrounded to prevent event queue buildup
if (!isInForeground) return
val ret = JSObject()
ret.put("value", sleepTimeRemaining)
ret.put("isAuto", isAutoSleepTimer)
@@ -75,6 +82,8 @@ class AbsAudioPlayer : Plugin() {
}
override fun onLocalMediaProgressUpdate(localMediaProgress: LocalMediaProgress) {
// Skip progress updates when app is backgrounded to prevent event queue buildup
if (!isInForeground) return
notifyListeners("onLocalMediaProgressUpdate", JSObject(jacksonMapper.writeValueAsString(localMediaProgress)))
}
@@ -118,6 +127,27 @@ class AbsAudioPlayer : Plugin() {
notifyListeners(evtName, ret)
}
override fun handleOnPause() {
super.handleOnPause()
isInForeground = false
}
override fun handleOnResume() {
super.handleOnResume()
isInForeground = true
// Send current state to UI after resume to sync up (with small delay to let WebView fully resume)
if (::playerNotificationService.isInitialized && playerNotificationService.currentPlaybackSession != null) {
Handler(Looper.getMainLooper()).postDelayed({
playerNotificationService.sendClientMetadata(PlayerState.READY)
playerNotificationService.sleepTimerManager.sendCurrentSleepTimerState()
playerNotificationService.mediaProgressSyncer.currentLocalMediaProgress?.let {
playerNotificationService.clientEventEmitter?.onLocalMediaProgressUpdate(it)
}
}, 100)
}
}
private fun initCastManager() {
val googleApi = GoogleApiAvailability.getInstance()
val statusCode = googleApi.isGooglePlayServicesAvailable(mainActivity)
+13 -11
View File
@@ -3,7 +3,7 @@ class WrappingMarquee {
#scrollSpeed = 30
/**
* @param {HTMLElement} el
* @param {HTMLElement} el
*/
constructor(el) {
this.el = el
@@ -21,8 +21,8 @@ class WrappingMarquee {
/**
* Transparent gradient mask shown when text is scrolling left and overflowing right
*
* @param {boolean} showLeft
*
* @param {boolean} showLeft
*/
setMask(showLeft) {
if (!this.el) return
@@ -39,11 +39,11 @@ class WrappingMarquee {
this.setMask(true)
let textScrollAmount = this.el.scrollWidth
this.pEl.innerHTML = this.innerText + '&nbsp;'.repeat(15)
this.pEl.textContent = this.innerText + '\u00A0'.repeat(15) // \u00A0 = non-breaking space
let totalScrollAmount = this.el.scrollWidth
let scrollDuration = totalScrollAmount * this.#scrollSpeed
this.pEl.innerHTML = this.pEl.innerHTML + this.innerText
this.pEl.textContent = this.pEl.textContent + this.innerText
let done = false
let start, previousTimeStamp
@@ -55,13 +55,14 @@ class WrappingMarquee {
const elapsed = timeStamp - start
if (this.isScrolling && previousTimeStamp !== timeStamp) {
const amountToMove = Math.min(elapsed / scrollDuration * totalScrollAmount, totalScrollAmount)
const amountToMove = Math.min((elapsed / scrollDuration) * totalScrollAmount, totalScrollAmount)
this.pEl.style.transform = `translateX(-${amountToMove}px)`
if (amountToMove === totalScrollAmount) done = true
if (amountToMove > textScrollAmount) this.setMask(false)
}
if (!this.isScrolling || done) { // canceled or done
if (!this.isScrolling || done) {
// canceled or done
this.isScrolling = false
this.pEl.style.transform = 'translateX(0px)'
this.pEl.innerText = this.innerText
@@ -69,7 +70,8 @@ class WrappingMarquee {
if (done) {
this.startTimer()
}
} else if (elapsed < scrollDuration) { // step
} else if (elapsed < scrollDuration) {
// step
previousTimeStamp = timeStamp
this.animationId = window.requestAnimationFrame(step)
}
@@ -94,8 +96,8 @@ class WrappingMarquee {
/**
* Initialize and start marquee if text overflows container
* resets the marquee if already active
*
* @param {string} innerText
*
* @param {string} innerText
*/
init(innerText) {
if (!this.el || !this.pEl) return
@@ -114,4 +116,4 @@ class WrappingMarquee {
}
}
}
export default WrappingMarquee
export default WrappingMarquee
+17 -6
View File
@@ -70,14 +70,20 @@
<div id="playerControls" class="absolute right-0 bottom-0 mx-auto" style="max-width: 414px">
<div class="flex items-center max-w-full" :class="playerSettings.lockUi ? 'justify-center' : 'justify-between'">
<span v-show="showFullscreen && !playerSettings.lockUi" class="material-symbols next-icon text-fg cursor-pointer" :class="isLoading ? 'text-opacity-10' : 'text-opacity-75'" @click.stop="jumpChapterStart">first_page</span>
<span v-show="!playerSettings.lockUi" class="material-symbols jump-icon text-fg cursor-pointer" :class="isLoading ? 'text-opacity-10' : 'text-opacity-75'" @click.stop="jumpBackwards">{{ jumpBackwardsIcon }}</span>
<div v-show="!playerSettings.lockUi" class="jump-icon text-fg cursor-pointer flex flex-col items-center" :class="isLoading ? 'text-opacity-10' : 'text-opacity-75'" @click.stop="jumpBackwards">
<span class="material-symbols text-3xl leading-none">replay</span>
<span v-if="showFullscreen" class="jump-label text-[10px] font-semibold leading-tight">{{ jumpBackwardsLabel }}</span>
</div>
<div class="play-btn cursor-pointer shadow-sm flex items-center justify-center rounded-full text-primary mx-4 relative overflow-hidden" :style="{ backgroundColor: coverRgb }" :class="{ 'animate-spin': seekLoading }" @mousedown.prevent @mouseup.prevent @click.stop="playPauseClick">
<div v-if="!coverBgIsLight" class="absolute top-0 left-0 w-full h-full bg-white bg-opacity-20 pointer-events-none" />
<span v-if="!isLoading" class="material-symbols fill" :class="{ 'text-white': coverRgb && !coverBgIsLight }">{{ seekLoading ? 'autorenew' : !isPlaying ? 'play_arrow' : 'pause' }}</span>
<widgets-spinner-icon v-else class="h-8 w-8" />
</div>
<span v-show="!playerSettings.lockUi" class="material-symbols jump-icon text-fg cursor-pointer" :class="isLoading ? 'text-opacity-10' : 'text-opacity-75'" @click.stop="jumpForward">{{ jumpForwardIcon }}</span>
<div v-show="!playerSettings.lockUi" class="jump-icon text-fg cursor-pointer flex flex-col items-center" :class="isLoading ? 'text-opacity-10' : 'text-opacity-75'" @click.stop="jumpForward">
<span class="material-symbols text-3xl leading-none">forward_media</span>
<span v-if="showFullscreen" class="jump-label text-[10px] font-semibold leading-tight">{{ jumpForwardLabel }}</span>
</div>
<span v-show="showFullscreen && !playerSettings.lockUi" class="material-symbols next-icon text-fg cursor-pointer" :class="nextChapter && !isLoading ? 'text-opacity-75' : 'text-opacity-10'" @click.stop="jumpNextChapter">last_page</span>
</div>
</div>
@@ -110,6 +116,7 @@ import { AbsAudioPlayer } from '@/plugins/capacitor'
import { Dialog } from '@capacitor/dialog'
import { FastAverageColor } from 'fast-average-color'
import WrappingMarquee from '@/assets/WrappingMarquee.js'
import jumpLabelMixin from '@/mixins/jumpLabel'
export default {
props: {
@@ -121,6 +128,7 @@ export default {
sleepTimeRemaining: Number,
serverLibraryItemId: String
},
mixins: [jumpLabelMixin],
data() {
return {
windowHeight: 0,
@@ -221,11 +229,11 @@ export default {
return items
},
jumpForwardIcon() {
return this.$store.getters['globals/getJumpForwardIcon'](this.jumpForwardTime)
jumpForwardLabel() {
return this.getJumpLabel(this.jumpForwardTime)
},
jumpBackwardsIcon() {
return this.$store.getters['globals/getJumpBackwardsIcon'](this.jumpBackwardsTime)
jumpBackwardsLabel() {
return this.getJumpLabel(this.jumpBackwardsTime)
},
jumpForwardTime() {
return this.$store.getters['getJumpForwardTime']
@@ -1091,6 +1099,9 @@ export default {
margin: 0px 0px;
font-size: 1.6rem;
}
#playerControls .jump-label {
margin-top: 2px;
}
#playerControls .play-btn {
transition: all 0.15s cubic-bezier(0.39, 0.575, 0.565, 1);
transition-property: padding, margin, height, width, min-width, min-height;
+1 -4
View File
@@ -3,10 +3,7 @@
<div class="absolute top-0 left-0 w-full h-full bg-black transition-opacity duration-200" :class="show ? 'bg-opacity-60 pointer-events-auto' : 'bg-opacity-0'" @click="clickBackground" />
<div class="absolute top-0 right-0 w-64 h-full bg-bg transform transition-transform py-6 pointer-events-auto" :class="show ? '' : 'translate-x-64'" @click.stop>
<div class="px-6 mb-4">
<p v-if="user" class="text-base">
Welcome,
<strong>{{ username }}</strong>
</p>
<p v-if="user" class="text-base" v-html="$getString('HeaderWelcome', [username])" />
</div>
<div class="w-full overflow-y-auto">
+6 -43
View File
@@ -1,16 +1,10 @@
<template>
<div class="flex h-full px-1 overflow-hidden">
<covers-book-cover :library-item="libraryItem" :width="coverWidth" :book-cover-aspect-ratio="bookCoverAspectRatio" />
<div class="flex-grow px-2 audiobookSearchCardContent">
<p v-if="matchKey !== 'title'" class="truncate text-sm">{{ title }}</p>
<p v-else class="truncate text-sm" v-html="matchHtml" />
<p v-if="matchKey === 'subtitle'" class="truncate text-xs text-fg-muted">{{ matchHtml }}</p>
<p v-if="matchKey !== 'authors'" class="text-xs text-fg truncate">by {{ authorName }}</p>
<p v-else class="truncate text-xs text-fg" v-html="matchHtml" />
<div v-if="matchKey === 'series' || matchKey === 'tags' || matchKey === 'isbn' || matchKey === 'asin' || matchKey === 'episode' || matchKey === 'narrators'" class="m-0 p-0 truncate text-xs" v-html="matchHtml" />
<div class="grow px-2 audiobookSearchCardContent">
<p class="truncate text-sm">{{ title }}</p>
<p v-if="subtitle" class="truncate text-xs text-gray-300">{{ subtitle }}</p>
<p class="text-xs text-gray-200 truncate">{{ $getString('LabelByAuthor', [authorName]) }}</p>
</div>
</div>
</template>
@@ -22,9 +16,7 @@ export default {
type: Object,
default: () => {}
},
search: String,
matchKey: String,
matchText: String
search: String
},
data() {
return {}
@@ -58,35 +50,6 @@ export default {
authorName() {
if (this.isPodcast) return this.mediaMetadata.author
return this.mediaMetadata.authorName
},
matchHtml() {
if (!this.matchText || !this.search) return ''
if (this.matchKey === 'subtitle') return ''
var matchSplit = this.matchText.toLowerCase().split(this.search.toLowerCase().trim())
if (matchSplit.length < 2) return ''
var html = ''
var totalLenSoFar = 0
for (let i = 0; i < matchSplit.length - 1; i++) {
var indexOf = matchSplit[i].length
var firstPart = this.matchText.substr(totalLenSoFar, indexOf)
var actualWasThere = this.matchText.substr(totalLenSoFar + indexOf, this.search.length)
totalLenSoFar += indexOf + this.search.length
html += `${firstPart}<strong class="text-warning">${actualWasThere}</strong>`
}
var lastPart = this.matchText.substr(totalLenSoFar)
html += lastPart
if (this.matchKey === 'episode') return `<p class="truncate">Episode: ${html}</p>`
if (this.matchKey === 'tags') return `<p class="truncate">Tags: ${html}</p>`
if (this.matchKey === 'subtitle') return `<p class="truncate">${html}</p>`
if (this.matchKey === 'authors') return `by ${html}`
if (this.matchKey === 'isbn') return `<p class="truncate">ISBN: ${html}</p>`
if (this.matchKey === 'asin') return `<p class="truncate">ASIN: ${html}</p>`
if (this.matchKey === 'series') return `<p class="truncate">Series: ${html}</p>`
if (this.matchKey === 'narrators') return `<p class="truncate">Narrator: ${html}</p>`
return `${html}`
}
},
methods: {},
@@ -101,4 +64,4 @@ export default {
flex-direction: column;
justify-content: center;
}
</style>
</style>
+5 -4
View File
@@ -483,8 +483,8 @@ export default {
await this.$hapticsImpact()
const { value } = await Dialog.confirm({
title: 'Confirm',
message: `Remove this server config?`
title: this.$strings.HeaderConfirm,
message: this.$strings.MessageConfirmDeleteServerConfig,
})
if (value) {
this.processing = true
@@ -951,8 +951,9 @@ export default {
init() {
if (this.$route.query.serverConnectionConfigId) {
// Handle force re-login for servers using new JWT auth but still using an old token OR refresh token failed
this.serverConfig = this.serverConnectionConfigs.find((scc) => scc.id === this.$route.query.serverConnectionConfigId)
if (this.serverConfig) {
const _serverConfig = this.serverConnectionConfigs.find((scc) => scc.id === this.$route.query.serverConnectionConfigId)
if (_serverConfig) {
this.serverConfig = { ..._serverConfig }
this.setForceRelogin(this.$route.query.error)
return
} else {
+4 -4
View File
@@ -303,7 +303,7 @@ export default {
// Show confirm if item has progress since it will reset
if (this.userItemProgress && this.userItemProgress.progress > 0 && !this.userIsFinished) {
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message: this.$strings.MessageConfirmMarkAsFinished
})
if (!value) return
@@ -369,7 +369,7 @@ export default {
await this.$hapticsImpact()
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message: this.$strings.MessageConfirmDiscardProgress
})
if (value) {
@@ -407,7 +407,7 @@ export default {
}
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message: this.$getString('MessageConfirmDeleteLocalEpisode', [localFile.basePath])
})
if (value) {
@@ -432,7 +432,7 @@ export default {
await this.$hapticsImpact()
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message: this.$strings.MessageConfirmDeleteLocalFiles
})
if (value) {
+13 -1
View File
@@ -1,7 +1,7 @@
<template>
<modals-modal v-model="show" width="90%">
<div class="w-full h-full bg-primary rounded-lg border border-fg/20">
<ul class="w-full rounded-lg text-base" role="listbox" aria-labelledby="listbox-label">
<ul class="w-full rounded-lg text-base max-h-[70vh] overflow-y-auto overscroll-contain" role="listbox" aria-labelledby="listbox-label">
<template v-for="item in items">
<li :key="item.value" class="text-fg select-none relative py-4 pr-9 cursor-pointer" :class="item.value === selected ? 'bg-bg bg-opacity-50' : ''" role="option" @click="clickedOption(item.value)">
<div class="flex items-center">
@@ -64,6 +64,18 @@ export default {
text: this.$strings.LabelFileModified,
value: 'mtimeMs'
},
{
text: this.$strings.LabelLibrarySortByProgress,
value: 'progress'
},
{
text: this.$strings.LabelLibrarySortByProgressStarted,
value: 'progress.createdAt'
},
{
text: this.$strings.LabelLibrarySortByProgressFinished,
value: 'progress.finishedAt'
},
{
text: this.$strings.LabelRandomly,
value: 'random'
+1 -1
View File
@@ -108,7 +108,7 @@ export default {
async cancelSleepTimer() {
if (this.isAuto) {
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message: this.$strings.MessageConfirmDisableAutoTimer
})
if (!value) return
+2 -2
View File
@@ -228,8 +228,8 @@ export default {
methods: {
async clearDownloadQueue() {
const { value } = await Dialog.confirm({
title: 'Confirm',
message: `Are you sure you want to clear episode download queue?`
title: this.$strings.HeaderConfirm,
message: this.$strings.MessageConfirmDeleteEpisodeDownloadQueue
})
if (value) {
+99 -33
View File
@@ -28,32 +28,70 @@ public class AbsDownloader: CAPPlugin, CAPBridgedPlugin, URLSessionDownloadDeleg
private let progressStatusQueue = DispatchQueue(label: "progress-status-queue", attributes: .concurrent)
private var downloadItemProgress = [String: DownloadItem]()
private var monitoringProgressTimer: Timer?
// Download queue management
private let downloadQueueLock = NSLock()
private var pendingDownloadTasks: [DownloadItemPartTask] = []
private var activeDownloadTasks: Set<String> = [] // Track active task IDs
private let maxConcurrentDownloads = 3
// MARK: - Download Queue Management
private func startNextDownloadInQueue() {
downloadQueueLock.lock()
defer { downloadQueueLock.unlock() }
// Start downloads up to the max concurrent limit
while activeDownloadTasks.count < maxConcurrentDownloads && !pendingDownloadTasks.isEmpty {
let nextTask = pendingDownloadTasks.removeFirst()
activeDownloadTasks.insert(nextTask.partId)
AbsLogger.info(message: "Starting download for \(nextTask.filename) (\(activeDownloadTasks.count)/\(maxConcurrentDownloads) active, \(pendingDownloadTasks.count) pending)")
nextTask.task.resume()
}
}
private func markDownloadTaskCompleted(_ taskId: String) {
downloadQueueLock.lock()
activeDownloadTasks.remove(taskId)
downloadQueueLock.unlock()
// Try to start the next download
startNextDownloadInQueue()
}
// MARK: - Progress handling
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
handleDownloadTaskUpdate(downloadTask: downloadTask) { downloadItem, downloadItemPart in
let realm = try Realm()
let partId = downloadItemPart.id
// Get fresh reference to the object in this realm
guard let liveDownloadItemPart = realm.object(ofType: DownloadItemPart.self, forPrimaryKey: partId) else {
throw LibraryItemDownloadError.downloadItemPartNotFound
}
try realm.write {
downloadItemPart.bytesDownloaded = downloadItemPart.fileSize
downloadItemPart.progress = 100
downloadItemPart.completed = true
liveDownloadItemPart.bytesDownloaded = liveDownloadItemPart.fileSize
liveDownloadItemPart.progress = 100
liveDownloadItemPart.completed = true
}
do {
// Move the downloaded file into place
guard let destinationUrl = downloadItemPart.destinationURL else {
guard let destinationUrl = liveDownloadItemPart.destinationURL else {
throw LibraryItemDownloadError.downloadItemPartDestinationUrlNotDefined
}
try? FileManager.default.removeItem(at: destinationUrl)
try FileManager.default.moveItem(at: location, to: destinationUrl)
try realm.write {
downloadItemPart.moved = true
liveDownloadItemPart.moved = true
}
} catch {
try realm.write {
downloadItemPart.failed = true
liveDownloadItemPart.failed = true
}
throw error
}
@@ -63,13 +101,26 @@ public class AbsDownloader: CAPPlugin, CAPBridgedPlugin, URLSessionDownloadDeleg
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
handleDownloadTaskUpdate(downloadTask: task) { downloadItem, downloadItemPart in
if let error = error {
try Realm().write {
downloadItemPart.completed = true
downloadItemPart.failed = true
let realm = try Realm()
let partId = downloadItemPart.id
// Get fresh reference to the object in this realm
guard let liveDownloadItemPart = realm.object(ofType: DownloadItemPart.self, forPrimaryKey: partId) else {
throw LibraryItemDownloadError.downloadItemPartNotFound
}
try realm.write {
liveDownloadItemPart.completed = true
liveDownloadItemPart.failed = true
}
throw error
}
}
// Mark this task as completed and start the next download in queue
if let taskId = task.taskDescription {
markDownloadTaskCompleted(taskId)
}
}
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
@@ -79,9 +130,17 @@ public class AbsDownloader: CAPPlugin, CAPBridgedPlugin, URLSessionDownloadDeleg
// Only update the progress if we received accurate progress data
if percentDownloaded >= 0.0 && percentDownloaded <= 100.0 {
try Realm().write {
downloadItemPart.bytesDownloaded = Double(totalBytesWritten)
downloadItemPart.progress = percentDownloaded
let realm = try Realm()
let partId = downloadItemPart.id
// Get fresh reference to the object in this realm
guard let liveDownloadItemPart = realm.object(ofType: DownloadItemPart.self, forPrimaryKey: partId) else {
throw LibraryItemDownloadError.downloadItemPartNotFound
}
try realm.write {
liveDownloadItemPart.bytesDownloaded = Double(totalBytesWritten)
liveDownloadItemPart.progress = percentDownloaded
}
}
}
@@ -307,32 +366,37 @@ public class AbsDownloader: CAPPlugin, CAPBridgedPlugin, URLSessionDownloadDeleg
// Persist in the database before status start coming in
try Database.shared.saveDownloadItem(downloadItem)
// Start all the downloads
for task in tasks {
task.task.resume()
}
// Add all tasks to the download queue
downloadQueueLock.lock()
pendingDownloadTasks.append(contentsOf: tasks)
downloadQueueLock.unlock()
AbsLogger.info(message: "Added \(tasks.count) tasks to download queue. Starting downloads...")
// Start downloading (up to maxConcurrentDownloads at a time)
startNextDownloadInQueue()
}
private func startLibraryItemTrackDownload(downloadItemId: String, item: LibraryItem, position: Int, track: AudioTrack, episode: PodcastEpisode?) throws -> DownloadItemPartTask {
AbsLogger.info(message: "TRACK \(track.contentUrl!)")
// If we don't name metadata, then we can't proceed
guard let filename = track.metadata?.filename else {
throw LibraryItemDownloadError.noMetadata
}
let serverUrl = urlForTrack(item: item, track: track)
let itemDirectory = try createLibraryItemFileDirectory(item: item)
let localUrl = "\(itemDirectory)/\(filename)"
let task = session.downloadTask(with: serverUrl)
let part = DownloadItemPart(downloadItemId: downloadItemId, filename: filename, destination: localUrl, itemTitle: track.title ?? "Unknown", serverPath: Store.serverConfig!.address, audioTrack: track, episode: episode, ebookFile: nil, size: track.metadata?.size ?? 0)
// Store the id on the task so the download item can be pulled from the database later
task.taskDescription = part.id
return DownloadItemPartTask(part: part, task: task)
return DownloadItemPartTask(part: part, task: task, partId: part.id, filename: filename)
}
private func startLibraryItemEbookDownload(downloadItemId: String, item: LibraryItem, ebookFile: EBookFile) throws -> DownloadItemPartTask {
@@ -340,14 +404,14 @@ public class AbsDownloader: CAPPlugin, CAPBridgedPlugin, URLSessionDownloadDeleg
let serverPath = "/api/items/\(item.id)/file/\(ebookFile.ino)/download"
let itemDirectory = try createLibraryItemFileDirectory(item: item)
let localUrl = "\(itemDirectory)/\(filename)"
let part = DownloadItemPart(downloadItemId: downloadItemId, filename: filename, destination: localUrl, itemTitle: filename, serverPath: serverPath, audioTrack: nil, episode: nil, ebookFile: ebookFile, size: ebookFile.metadata?.size ?? 0)
let task = session.downloadTask(with: part.downloadURL!)
// Store the id on the task so the download item can be pulled from the database later
task.taskDescription = part.id
return DownloadItemPartTask(part: part, task: task)
return DownloadItemPartTask(part: part, task: task, partId: part.id, filename: filename)
}
private func startLibraryItemCoverDownload(downloadItemId: String, item: LibraryItem) throws -> DownloadItemPartTask {
@@ -355,19 +419,19 @@ public class AbsDownloader: CAPPlugin, CAPBridgedPlugin, URLSessionDownloadDeleg
let serverPath = "/api/items/\(item.id)/cover"
let itemDirectory = try createLibraryItemFileDirectory(item: item)
let localUrl = "\(itemDirectory)/\(filename)"
// Find library file to get cover size
let coverLibraryFile = item.libraryFiles.first(where: {
$0.metadata?.path == item.media?.coverPath
})
let part = DownloadItemPart(downloadItemId: downloadItemId, filename: filename, destination: localUrl, itemTitle: "cover", serverPath: serverPath, audioTrack: nil, episode: nil, ebookFile: nil, size: coverLibraryFile?.metadata?.size ?? 0)
let task = session.downloadTask(with: part.downloadURL!)
// Store the id on the task so the download item can be pulled from the database later
task.taskDescription = part.id
return DownloadItemPartTask(part: part, task: task)
return DownloadItemPartTask(part: part, task: task, partId: part.id, filename: filename)
}
private func urlForTrack(item: LibraryItem, track: AudioTrack) -> URL {
@@ -431,6 +495,8 @@ typealias DownloadProgressHandler = (_ downloadItem: DownloadItem, _ downloadIte
struct DownloadItemPartTask {
let part: DownloadItemPart
let task: URLSessionDownloadTask
let partId: String // Cache the ID to avoid cross-thread Realm access
let filename: String // Cache the filename to avoid cross-thread Realm access
}
enum LibraryItemDownloadError: String, Error {
+1 -1
View File
@@ -33,7 +33,7 @@ export default {
this.$strings.MessageConfirmStreamingUsingCellular
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message
})
return value
+12
View File
@@ -0,0 +1,12 @@
export default {
methods: {
getJumpLabel(seconds) {
const val = Number(seconds)
if (isNaN(val)) return ''
const useMinutes = val >= 120 // keep 60s as seconds
const key = useMinutes ? 'UnitMinutesShort' : 'UnitSecondsShort'
const unitValue = useMinutes ? val / 60 : val
return this.$getString(key, [this.$formatNumber(unitValue)])
}
}
}
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "audiobookshelf-app",
"version": "0.11.0-beta",
"version": "0.12.0-beta",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "audiobookshelf-app",
"version": "0.11.0-beta",
"version": "0.12.0-beta",
"dependencies": {
"@capacitor-community/keep-awake": "^7.0.0",
"@capacitor-community/volume-buttons": "^7.0.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "audiobookshelf-app",
"version": "0.11.0-beta",
"version": "0.12.0-beta",
"author": "advplyr",
"scripts": {
"dev": "nuxt --hostname 0.0.0.0 --port 1337",
+1 -1
View File
@@ -148,7 +148,7 @@ export default {
// Show confirmation dialog and start downloading if user chooses so
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message: startDownloadMessage
})
if (value) {
+1 -1
View File
@@ -11,7 +11,7 @@
<span v-else class="font-semibold text-fg">{{ Math.round(itemPart.progress) }}%</span>
</div>
<div class="flex-grow px-2">
<p class="truncate">{{ itemPart.filename }}</p>
<p class="break-all">{{ itemPart.filename }}</p>
</div>
</div>
+4 -4
View File
@@ -346,7 +346,7 @@ export default {
}
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message: this.$getString('MessageConfirmDeleteLocalEpisode', [localFile.basePath])
})
if (value) {
@@ -514,7 +514,7 @@ export default {
await this.$hapticsImpact()
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message: this.$strings.MessageConfirmDiscardProgress
})
if (value) {
@@ -575,8 +575,8 @@ export default {
await this.$hapticsImpact()
const { value } = await Dialog.confirm({
title: 'Confirm',
message: `Are you sure you want to delete episode "${this.title}" from the server?\nWarning: This will delete the audio file.`
title: this.$strings.HeaderConfirm,
message: this.$getString('MessageConfirmDeleteServerEpisode', [this.title])
})
if (value) {
+8 -4
View File
@@ -535,7 +535,11 @@ export default {
if (this.isPodcast) {
this.episodes.sort((a, b) => {
return String(b.publishedAt).localeCompare(String(a.publishedAt), undefined, { numeric: true, sensitivity: 'base' })
if (this.podcastType === 'serial') {
return String(a.publishedAt).localeCompare(String(b.publishedAt), undefined, { numeric: true, sensitivity: 'base' })
} else {
return String(b.publishedAt).localeCompare(String(a.publishedAt), undefined, { numeric: true, sensitivity: 'base' })
}
})
let episode = this.episodes.find((ep) => {
@@ -584,8 +588,8 @@ export default {
// If start time and is not already streaming then ask for confirmation
if (startTime !== null && startTime !== undefined && !this.$store.getters['getIsMediaStreaming'](libraryItemId, null)) {
const { value } = await Dialog.confirm({
title: 'Confirm',
message: `Start playback for "${this.title}" at ${this.$secondsToTimestamp(startTime)}?`
title: this.$strings.HeaderConfirm,
message: this.$getString('MessageConfirmPlaybackTime', [this.title, this.$secondsToTimestamp(startTime)])
})
if (!value) return
}
@@ -673,7 +677,7 @@ export default {
}
}
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message: startDownloadMessage
})
if (value) {
+1 -1
View File
@@ -100,7 +100,7 @@ export default {
deleteMessage = `Are you sure you want to remove this folder and ${this.localLibraryItems.length} items? (does not delete anything in your file system)`
}
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message: deleteMessage
})
if (value) {
+1 -1
View File
@@ -22,7 +22,7 @@
</div>
<div v-if="!isAndroid10OrBelow || overrideFolderRestriction" class="flex border-t border-fg/10 my-4 py-4">
<div class="flex-grow pr-1">
<ui-dropdown v-model="newFolderMediaType" placeholder="Select media type" :items="mediaTypeItems" />
<ui-dropdown v-model="newFolderMediaType" :placeholder="$strings.LabelSelectMediaType" :items="mediaTypeItems" />
</div>
<ui-btn small class="w-28" color="success" @click="selectFolder">{{ $strings.ButtonNewFolder }}</ui-btn>
</div>
+3 -3
View File
@@ -369,7 +369,7 @@ export default {
confirmMessage += ' The file on the server will be unaffected.'
}
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message: confirmMessage
})
if (value) {
@@ -395,7 +395,7 @@ export default {
confirmMessage += ' The file on the server will be unaffected.'
}
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message: confirmMessage
})
if (value) {
@@ -412,7 +412,7 @@ export default {
confirmMessage += ' The files on the server and your progress will be unaffected.'
}
const { value } = await Dialog.confirm({
title: 'Confirm',
title: this.$strings.HeaderConfirm,
message: confirmMessage
})
if (value) {
+3 -3
View File
@@ -14,7 +14,7 @@
<template v-for="item in bookResults">
<div :key="item.libraryItem.id" class="w-full h-16 py-1">
<nuxt-link :to="`/item/${item.libraryItem.id}`">
<cards-item-search-card :library-item="item.libraryItem" :match-key="item.matchKey" :match-text="item.matchText" :search="lastSearch" />
<cards-item-search-card :library-item="item.libraryItem" :search="lastSearch" />
</nuxt-link>
</div>
</template>
@@ -23,7 +23,7 @@
<template v-for="item in podcastResults">
<div :key="item.libraryItem.id" class="text-fg select-none relative py-1">
<nuxt-link :to="`/item/${item.libraryItem.id}`">
<cards-item-search-card :library-item="item.libraryItem" :match-key="item.matchKey" :match-text="item.matchText" :search="lastSearch" />
<cards-item-search-card :library-item="item.libraryItem" :search="lastSearch" />
</nuxt-link>
</div>
</template>
@@ -160,4 +160,4 @@ export default {
height: calc(100% - 108px);
max-height: calc(100% - 108px);
}
</style>
</style>
+61 -42
View File
@@ -36,24 +36,24 @@
<!-- Playback settings -->
<p class="uppercase text-xs font-semibold text-fg-muted mb-2 mt-10">{{ $strings.HeaderPlaybackSettings }}</p>
<div class="py-3 flex items-center">
<p class="pr-4 w-36">{{ $strings.LabelJumpBackwardsTime }}</p>
<div @click.stop="showJumpBackwardsOptions">
<ui-text-input :value="jumpBackwardsOption" readonly append-icon="expand_more" style="width: 145px; max-width: 145px" />
</div>
</div>
<div class="py-3 flex items-center">
<p class="pr-4 w-36">{{ $strings.LabelJumpForwardsTime }}</p>
<div @click.stop="showJumpForwardOptions">
<ui-text-input :value="jumpForwardOption" readonly append-icon="expand_more" style="width: 145px; max-width: 145px" />
</div>
</div>
<div class="flex items-center py-3">
<div class="w-10 flex justify-center" @click="toggleDisableAutoRewind">
<ui-toggle-switch v-model="settings.disableAutoRewind" @input="saveSettings" />
</div>
<p class="pl-4">{{ $strings.LabelDisableAutoRewind }}</p>
</div>
<div class="flex items-center py-3">
<div class="w-10 flex justify-center" @click="toggleJumpBackwards">
<span class="material-symbols text-4xl">{{ currentJumpBackwardsTimeIcon }}</span>
</div>
<p class="pl-4">{{ $strings.LabelJumpBackwardsTime }}</p>
</div>
<div class="flex items-center py-3">
<div class="w-10 flex justify-center" @click="toggleJumpForward">
<span class="material-symbols text-4xl">{{ currentJumpForwardTimeIcon }}</span>
</div>
<p class="pl-4">{{ $strings.LabelJumpForwardsTime }}</p>
</div>
<div v-if="!isiOS" class="flex items-center py-3">
<div class="w-10 flex justify-center" @click="toggleEnableMp3IndexSeeking">
<ui-toggle-switch v-model="settings.enableMp3IndexSeeking" @input="saveSettings" />
@@ -179,7 +179,7 @@
<ui-loading-indicator />
</div>
<modals-dialog v-model="showMoreMenuDialog" :items="moreMenuItems" @action="clickMenuAction" />
<modals-dialog v-model="showMoreMenuDialog" :items="moreMenuItems" :selected="moreMenuSelected" @action="clickMenuAction" />
<modals-sleep-timer-length-modal v-model="showSleepTimerLengthModal" @change="sleepTimerLengthModalSelection" />
<modals-auto-sleep-timer-rewind-length-modal v-model="showAutoSleepTimerRewindLengthModal" @change="showAutoSleepTimerRewindLengthModalSelection" />
</div>
@@ -187,8 +187,10 @@
<script>
import { Dialog } from '@capacitor/dialog'
import jumpLabelMixin from '@/mixins/jumpLabel'
export default {
mixins: [jumpLabelMixin],
data() {
return {
loading: false,
@@ -352,15 +354,21 @@ export default {
isiOS() {
return this.$platform === 'ios'
},
jumpForwardItems() {
return this.$store.state.globals.jumpForwardItems || []
jumpForwardSecondsOptions() {
return this.$store.state.globals.jumpForwardSecondsOptions || []
},
jumpBackwardsItems() {
return this.$store.state.globals.jumpBackwardsItems || []
jumpBackwardsSecondsOptions() {
return this.$store.state.globals.jumpBackwardsSecondsOptions || []
},
languageOptionItems() {
return this.$languageCodeOptions || []
},
jumpForwardOption() {
return this.getJumpLabel(this.settings.jumpForwardTime)
},
jumpBackwardsOption() {
return this.getJumpLabel(this.settings.jumpBackwardsTime)
},
themeOptionItems() {
return [
{
@@ -377,20 +385,6 @@ export default {
}
]
},
currentJumpForwardTimeIcon() {
return this.jumpForwardItems[this.currentJumpForwardTimeIndex].icon
},
currentJumpForwardTimeIndex() {
var index = this.jumpForwardItems.findIndex((jfi) => jfi.value === this.settings.jumpForwardTime)
return index >= 0 ? index : 1
},
currentJumpBackwardsTimeIcon() {
return this.jumpBackwardsItems[this.currentJumpBackwardsTimeIndex].icon
},
currentJumpBackwardsTimeIndex() {
var index = this.jumpBackwardsItems.findIndex((jfi) => jfi.value === this.settings.jumpBackwardsTime)
return index >= 0 ? index : 1
},
shakeSensitivityOption() {
const item = this.shakeSensitivityItems.find((i) => i.value === this.settings.shakeSensitivity)
return item?.text || 'Error'
@@ -434,7 +428,29 @@ export default {
else if (this.moreMenuSetting === 'downloadUsingCellular') return this.downloadUsingCellularItems
else if (this.moreMenuSetting === 'streamingUsingCellular') return this.streamingUsingCellularItems
else if (this.moreMenuSetting === 'androidAutoBrowseSeriesSequenceOrder') return this.androidAutoBrowseSeriesSequenceOrderItems
else if (this.moreMenuSetting === 'jumpForward')
return this.jumpForwardSecondsOptions.map((value) => ({
text: this.getJumpLabel(value),
value: value
}))
else if (this.moreMenuSetting === 'jumpBackwards')
return this.jumpBackwardsSecondsOptions.map((value) => ({
text: this.getJumpLabel(value),
value: value
}))
return []
},
moreMenuSelected() {
if (this.moreMenuSetting === 'jumpForward') return this.settings.jumpForwardTime
if (this.moreMenuSetting === 'jumpBackwards') return this.settings.jumpBackwardsTime
if (this.moreMenuSetting === 'language') return this.settings.languageCode
if (this.moreMenuSetting === 'theme') return this.theme
if (this.moreMenuSetting === 'downloadUsingCellular') return this.settings.downloadUsingCellular
if (this.moreMenuSetting === 'streamingUsingCellular') return this.settings.streamingUsingCellular
if (this.moreMenuSetting === 'androidAutoBrowseSeriesSequenceOrder') return this.settings.androidAutoBrowseSeriesSequenceOrder
if (this.moreMenuSetting === 'shakeSensitivity') return this.settings.shakeSensitivity
if (this.moreMenuSetting === 'hapticFeedback') return this.settings.hapticFeedback
return null
}
},
methods: {
@@ -468,6 +484,14 @@ export default {
this.moreMenuSetting = 'theme'
this.showMoreMenuDialog = true
},
showJumpForwardOptions() {
this.moreMenuSetting = 'jumpForward'
this.showMoreMenuDialog = true
},
showJumpBackwardsOptions() {
this.moreMenuSetting = 'jumpBackwards'
this.showMoreMenuDialog = true
},
showDownloadUsingCellularOptions() {
this.moreMenuSetting = 'downloadUsingCellular'
this.showMoreMenuDialog = true
@@ -503,6 +527,12 @@ export default {
} else if (this.moreMenuSetting === 'androidAutoBrowseSeriesSequenceOrder') {
this.settings.androidAutoBrowseSeriesSequenceOrder = action
this.saveSettings()
} else if (this.moreMenuSetting === 'jumpForward') {
this.settings.jumpForwardTime = action
this.saveSettings()
} else if (this.moreMenuSetting === 'jumpBackwards') {
this.settings.jumpBackwardsTime = action
this.saveSettings()
}
},
saveTheme(theme) {
@@ -598,17 +628,6 @@ export default {
this.$setOrientationLock(this.settings.lockOrientation)
this.saveSettings()
},
toggleJumpForward() {
var next = (this.currentJumpForwardTimeIndex + 1) % 3
this.settings.jumpForwardTime = this.jumpForwardItems[next].value
this.saveSettings()
},
toggleJumpBackwards() {
var next = (this.currentJumpBackwardsTimeIndex + 4) % 3
if (next > 2) return
this.settings.jumpBackwardsTime = this.jumpBackwardsItems[next].value
this.saveSettings()
},
async saveSettings() {
await this.$hapticsImpact()
const updatedDeviceData = await this.$db.updateDeviceSettings({ ...this.settings })
+1
View File
@@ -25,6 +25,7 @@ const languageCodeMap = {
ru: { label: 'Русский', dateFnsLocale: 'ru' },
sl: { label: 'Slovenščina', dateFnsLocale: 'sl' },
sv: { label: 'Svenska', dateFnsLocale: 'sv' },
tr: { label: 'Türkçe', dateFnsLocale: 'tr' },
uk: { label: 'Українська', dateFnsLocale: 'uk' },
'vi-vn': { label: 'Tiếng Việt', dateFnsLocale: 'vi' },
'zh-cn': { label: '简体中文 (Simplified Chinese)', dateFnsLocale: 'zhCN' }
+2 -2
View File
@@ -314,8 +314,8 @@ export default ({ store, app }, inject) => {
}
if (!canGoBack) {
const { value } = await Dialog.confirm({
title: 'Confirm',
message: `Did you want to exit the app?`
title: eventBus.$strings.HeaderConfirm,
message: eventBus.$strings.MessageConfirmAppExit
})
if (value) {
App.exitApp()
+3 -37
View File
@@ -5,34 +5,8 @@ export const state = () => ({
series: null,
localMediaProgress: [],
lastSearch: null,
jumpForwardItems: [
{
icon: 'forward_5',
value: 5
},
{
icon: 'forward_10',
value: 10
},
{
icon: 'forward_30',
value: 30
}
],
jumpBackwardsItems: [
{
icon: 'replay_5',
value: 5
},
{
icon: 'replay_10',
value: 10
},
{
icon: 'replay_30',
value: 30
}
],
jumpForwardSecondsOptions: [5, 10, 15, 30, 60, 120, 300],
jumpBackwardsSecondsOptions: [5, 10, 15, 30, 60, 120, 300],
libraryIcons: ['database', 'audiobookshelf', 'books-1', 'books-2', 'book-1', 'microphone-1', 'microphone-3', 'radio', 'podcast', 'rss', 'headphones', 'music', 'file-picture', 'rocket', 'power', 'star', 'heart'],
selectedPlaylistItems: [],
showPlaylistsAddCreateModal: false,
@@ -111,15 +85,7 @@ export const getters = {
if (episodeId != null && lmp.episodeId != episodeId) return false
return lmp.libraryItemId == libraryItemId
})
},
getJumpForwardIcon: (state) => (jumpForwardTime) => {
const item = state.jumpForwardItems.find((i) => i.value == jumpForwardTime)
return item ? item.icon : 'forward_10'
},
getJumpBackwardsIcon: (state) => (jumpBackwardsTime) => {
const item = state.jumpBackwardsItems.find((i) => i.value == jumpBackwardsTime)
return item ? item.icon : 'replay_10'
}
}
}
export const actions = {
+7
View File
@@ -146,6 +146,7 @@
"LabelEndOfChapter": "نهاية الفصل",
"LabelEndTime": "وقت النهاية",
"LabelEpisode": "الحلقة",
"LabelExplicit": "محتوى صريح",
"LabelFeedURL": "عنوان التغذية",
"LabelFile": "الملف",
"LabelFileBirthtime": "وقت انشاء الملف",
@@ -154,6 +155,9 @@
"LabelFinished": "المنجزة",
"LabelFolder": "المجلد",
"LabelFontBoldness": "تعريض الخط",
"LabelFontFamily": "عائلة الخطوط",
"LabelFontFamilySans": "سانس",
"LabelFontFamilySerif": "سارف",
"LabelFontScale": "نطاق الخط",
"LabelGenre": "التصنيف",
"LabelGenres": "التصانيف",
@@ -297,6 +301,7 @@
"MessageDownloading": "جاري التنزيل...",
"MessageDownloadingEpisode": "جاري تنزيل الحلقة",
"MessageEpisodesQueuedForDownload": "تمت إضافة {0} حلقة (حلقات) إلى قائمة انتظار التنزيل",
"MessageFailedToRefreshToken": "فشل في تحديث الرمز، إعادة تسجيل الدخول مطلوب",
"MessageFeedURLWillBe": "سيكون رابط التغذية هو {0}",
"MessageFetching": "جاري الجلب...",
"MessageFollowTheProjectOnGithub": "تابع المشروع على Github",
@@ -324,6 +329,8 @@
"MessageNoSeries": "لا توجد سلاسل",
"MessageNoUpdatesWereNecessary": "لا حاجة لأي تحديثات",
"MessageNoUserPlaylists": "ليس لديك أي قوائم تشغيل",
"MessageOldServerAuthReLoginRequired": "تم تحسين المصادقة في الخادم v2.26.0 لضمان الأمان. يُطلب من جميع المستخدمين إعادة تسجيل الدخول.",
"MessageOldServerAuthWarning": "الخادم يستخدم مصادقة قديمة",
"MessageOldServerConnectionWarning": "تكوين اتصال الخادم يستخدم معرّف مستخدم قديم. يرجى حذف اتصال الخادم هذا وإعادة إضافته.",
"MessageOldServerConnectionWarningHelp": "لقد قمتَ بإعداد الاتصال بهذا الخادم قبل ترحيل قاعدة البيانات في الإصدار 2.3.0، الصادر في يونيو 2023. سيؤدي تحديث الخادم المستقبلي إلى إلغاء إمكانية تسجيل الدخول باستخدام هذا الاتصال القديم. يُرجى حذف اتصال الخادم الحالي والاتصال مرة أخرى (باستخدام نفس عنوان الخادم وبيانات الاعتماد). إذا كانت لديك أي وسائط مُنزّلة على هذا الجهاز، فيجب تنزيلها مرة أخرى لمزامنتها مع الخادم.",
"MessagePodcastSearchField": "أدخل مصطلح البحث أو عنوان URL الخاص بتغذية RSS",
+18 -1
View File
@@ -63,6 +63,7 @@
"HeaderChapters": "Capítols",
"HeaderCollection": "Col·lecció",
"HeaderCollectionItems": "Elements de la col·lecció",
"HeaderConfirm": "Confirma",
"HeaderConnectionStatus": "Estat de la connexió",
"HeaderDataSettings": "Paràmetres de dades",
"HeaderDetails": "Detalls",
@@ -91,6 +92,7 @@
"HeaderStatsRecentSessions": "Sessions recents",
"HeaderTableOfContents": "Sumari",
"HeaderUserInterfaceSettings": "Paràmetres de la interfície d'usuari",
"HeaderWelcome": "Benvingut, <strong>{0}</strong>",
"HeaderYourStats": "Les vostres estadístiques",
"LabelAddToPlaylist": "Afegeix a la llista de reproducció",
"LabelAddedAt": "Afegit a",
@@ -113,6 +115,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Quan el temporitzador d'auto sleep acaba, reproduir l'element altra vegada farà que es rebobine automàticament a la teua posició.",
"LabelAutoSleepTimerHelp": "Quan es reprodueix entre hores especificades, el temporitzador s'activarà automàticament.",
"LabelBooks": "Llibres",
"LabelByAuthor": "per {0}",
"LabelChapterTrack": "Seguiment de capítol",
"LabelChapters": "Capítols",
"LabelClosePlayer": "Tanca el reproductor",
@@ -126,11 +129,12 @@
"LabelCustomTime": "Temps personalitzat",
"LabelDescription": "Descripció",
"LabelDisableAudioFadeOut": "Desactivar desaparició d'àudio",
"LabelDisableAudioFadeOutHelp": "El volum de l'audio començara a reduïr-se quan quede menys d'1 minut del temporitzador d'anar a dormir. Habilita este ajustament per a no reduïr el volum.",
"LabelDisableAudioFadeOutHelp": "El volum de l'audio començara a reduïr-se quan quedi menys d'1 minut del temporitzador d'anar a dormir. Habilita aquest ajustament per a no reduïr el volum.",
"LabelDisableAutoRewind": "Desactivar rebobinatge automàtic",
"LabelDisableShakeToReset": "Desactivar sacsejar per reiniciar",
"LabelDisableShakeToResetHelp": "Si sacseges el teu dispositiu quan el temporitzador és actiu o durant els 2 minuts després que hagi expirat, el temporitzador es reinicia. Activa aquesta opció per evitar-ho.",
"LabelDisableVibrateOnReset": "Desactivar la vibració al reiniciar",
"LabelDisableVibrateOnResetHelp": "Quan el temporitzador d'apagat es reinicia, el dispositiu vibra. Activa aquesta opció perquè no vibri quan es reiniciï el temporitzador.",
"LabelDiscover": "Descobrir",
"LabelDownload": "Descarregar",
"LabelDownloadUsingCellular": "Descarregar utilitzant dades mòbils",
@@ -144,6 +148,7 @@
"LabelEndOfChapter": "Final del capítol",
"LabelEndTime": "Hora de finalització",
"LabelEpisode": "Episodi",
"LabelExplicit": "Explícit",
"LabelFeedURL": "Font URL",
"LabelFile": "Fitxer",
"LabelFileBirthtime": "Fitxer creat a",
@@ -152,22 +157,31 @@
"LabelFinished": "Acabat",
"LabelFolder": "Carpeta",
"LabelFontBoldness": "Gruix de la lletra",
"LabelFontFamily": "Família tipogràfica",
"LabelFontFamilySans": "Sans",
"LabelFontFamilySerif": "Serif",
"LabelFontScale": "Escala de la lletra",
"LabelGenre": "Gènere",
"LabelGenres": "Gèneres",
"LabelHapticFeedback": "Resposta hàptica",
"LabelHasEbook": "Té llibre electrònic",
"LabelHasSupplementaryEbook": "Té llibre electrònic suplementari",
"LabelHeavy": "Pesat",
"LabelHigh": "Alt",
"LabelHost": "Amfitrió",
"LabelInProgress": "En procés",
"LabelIncomplete": "Incomplet",
"LabelInternalAppStorage": "Emmagatzematge intern de l'aplicació",
"LabelJumpBackwardsTime": "Saltar enrere",
"LabelJumpForwardsTime": "Salt endavant en el temps",
"LabelKeepScreenAwake": "Manté la pantalla encesa",
"LabelLanguage": "Llengua",
"LabelLayout": "Disposició",
"LabelLayoutAuto": "Automàtic",
"LabelLayoutSinglePage": "Pàgina única",
"LabelLibrarySortByProgress": "Progrés: Última actualització",
"LabelLibrarySortByProgressFinished": "Progrés: Finalitzat",
"LabelLibrarySortByProgressStarted": "Progrés: Començat",
"LabelLight": "Clar",
"LabelLineSpacing": "Interlineat",
"LabelListenAgain": "Escoltar de nou",
@@ -175,14 +189,17 @@
"LabelLocalPodcasts": "Pòdcasts locals",
"LabelLockOrientation": "Bloca l'orientació",
"LabelLockPlayer": "Bloca el reproductor",
"LabelLow": "Baix",
"LabelMediaType": "Tipus de mitjà",
"LabelMedium": "Mitjà",
"LabelMissing": "Falta",
"LabelMore": "Més",
"LabelMoreInfo": "Més informació",
"LabelName": "Nom",
"LabelNarrator": "Narrador",
"LabelNarrators": "Narradors",
"LabelNavigateWithVolume": "Navega amb les tecles de volum",
"LabelNavigateWithVolumeMirrored": "Emmirallat",
"LabelNavigateWithVolumeWhilePlayingDisabled": "⭘",
"LabelNavigateWithVolumeWhilePlayingEnabled": "",
"LabelNever": "Mai",
+3
View File
@@ -155,6 +155,9 @@
"LabelFinished": "Dokončeno",
"LabelFolder": "Složka",
"LabelFontBoldness": "Výraznost písma",
"LabelFontFamily": "Rodina písem",
"LabelFontFamilySans": "Bezpatkové",
"LabelFontFamilySerif": "Patkové",
"LabelFontScale": "Měřítko písma",
"LabelGenre": "Žánr",
"LabelGenres": "Žánry",
+7
View File
@@ -63,6 +63,7 @@
"HeaderChapters": "Kapitler",
"HeaderCollection": "Samling",
"HeaderCollectionItems": "Samlingselementer",
"HeaderConfirm": "Bekræft",
"HeaderConnectionStatus": "Forbindelsesstatus",
"HeaderDataSettings": "Data indstillinger",
"HeaderDetails": "Detaljer",
@@ -91,6 +92,7 @@
"HeaderStatsRecentSessions": "Seneste Sessions",
"HeaderTableOfContents": "Indholdsfortegnelse",
"HeaderUserInterfaceSettings": "Indstillinger for brugergrænseflade",
"HeaderWelcome": "Velkommen, <strong>{0}</strong>",
"HeaderYourStats": "Dine Statistikker",
"LabelAddToPlaylist": "Tilføj til Afspilningsliste",
"LabelAddedAt": "Tilføjet",
@@ -113,6 +115,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Når den automatiske sleep-timer er færdig, vil genafspilning af elementet automatisk spole din position tilbage.",
"LabelAutoSleepTimerHelp": "Når der afspilles medie mellem de angivne start- og sluttidspunkter, starter en sleep-timer automatisk.",
"LabelBooks": "Bøger",
"LabelByAuthor": "Efter Forfatter",
"LabelChapterTrack": "Kapitel spor",
"LabelChapters": "Kapitler",
"LabelClosePlayer": "Luk afspiller",
@@ -155,6 +158,9 @@
"LabelFinished": "Færdig",
"LabelFolder": "Mappe",
"LabelFontBoldness": "Skrift tykkelse",
"LabelFontFamily": "Skrifttypefamilie",
"LabelFontFamilySans": "Font Sans",
"LabelFontFamilySerif": "Font Serif",
"LabelFontScale": "Skriftstørrelse",
"LabelGenre": "Genre",
"LabelGenres": "Genrer",
@@ -298,6 +304,7 @@
"MessageDownloading": "Downloader...",
"MessageDownloadingEpisode": "Downloader episode",
"MessageEpisodesQueuedForDownload": "{0} episoder er sat i kø til download",
"MessageFailedToRefreshToken": "Mislykkedes med at opdatere token, nyt loginforsøg nødvendigt",
"MessageFeedURLWillBe": "Feed-URL vil være {0}",
"MessageFetching": "Henter...",
"MessageFollowTheProjectOnGithub": "Følg projektet på GitHub",
+18 -1
View File
@@ -63,6 +63,7 @@
"HeaderChapters": "Kapitel",
"HeaderCollection": "Sammlung",
"HeaderCollectionItems": "Sammlungseinträge",
"HeaderConfirm": "Bestätigen",
"HeaderConnectionStatus": "Verbindungsstatus",
"HeaderDataSettings": "Daten-Einstellungen",
"HeaderDetails": "Details",
@@ -91,6 +92,7 @@
"HeaderStatsRecentSessions": "Neueste Ereignisse",
"HeaderTableOfContents": "Inhaltsverzeichnis",
"HeaderUserInterfaceSettings": "Einstellungen der Benutzeroberfläche",
"HeaderWelcome": "Willkommen, <strong>{0}</strong>",
"HeaderYourStats": "Eigene Statistiken",
"LabelAddToPlaylist": "Zur Wiedergabeliste hinzufügen",
"LabelAddedAt": "Hinzugefügt am",
@@ -113,6 +115,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Wenn die Schlummerfunktion abgelaufen ist, wird bei der erneuten Wiedergabe des Titels die Position automatisch zurückgespult.",
"LabelAutoSleepTimerHelp": "Bei der Wiedergabe von Medien zwischen der angegebenen Start- und Endzeit wird automatisch eine Schlummerfunktion gestartet.",
"LabelBooks": "Bücher",
"LabelByAuthor": "von {0}",
"LabelChapterTrack": "Kapitelspur",
"LabelChapters": "Kapitel",
"LabelClosePlayer": "Player schließen",
@@ -155,6 +158,9 @@
"LabelFinished": "Beendet",
"LabelFolder": "Ordner",
"LabelFontBoldness": "Schriftstärke",
"LabelFontFamily": "Schriftfamilie",
"LabelFontFamilySans": "Sans",
"LabelFontFamilySerif": "Serifen",
"LabelFontScale": "Schriftgröße",
"LabelGenre": "Kategorie",
"LabelGenres": "Kategorien",
@@ -174,6 +180,9 @@
"LabelLayout": "Ansicht",
"LabelLayoutAuto": "Auto",
"LabelLayoutSinglePage": "Eine Seite",
"LabelLibrarySortByProgress": "Fortschritt: Letzte Aktualisierung",
"LabelLibrarySortByProgressFinished": "Fortschritt: Beendet",
"LabelLibrarySortByProgressStarted": "Fortschritt: Gestartet",
"LabelLight": "Leicht",
"LabelLineSpacing": "Zeilenabstand",
"LabelListenAgain": "Erneut anhören",
@@ -233,6 +242,7 @@
"LabelScaleElapsedTimeBySpeed": "Vergangene Zeit anhand der Geschwindigkeit skalieren",
"LabelSeason": "Staffel",
"LabelSelectADevice": "Wähle ein Gerät",
"LabelSelectMediaType": "Wähle die Art des Mediums",
"LabelSequenceAscending": "Reihenfolge aufsteigend",
"LabelSequenceDescending": "Reihenfolge absteigend",
"LabelSeries": "Serien",
@@ -285,12 +295,17 @@
"MessageAudiobookshelfServerNotConnected": "Audiobookshelf Server nicht verbunden",
"MessageAudiobookshelfServerRequired": "<strong>Wichtig!</strong> Diese App wurde entwickelt, um mit einem Audiobookshelf-Server zu arbeiten, den du oder jemand, den du kennst, hostet. Diese App stellt keine Inhalte zur Verfügung.",
"MessageBookshelfEmpty": "Bücherregal leer",
"MessageConfirmAppExit": "Möchten Sie die App schließen?",
"MessageConfirmDeleteEpisodeDownloadQueue": "Sind Sie sicher, dass Sie die Warteschlange für Epsioden-Downloads leeren wollen?",
"MessageConfirmDeleteLocalEpisode": "Soll die lokale Episode \"{0}\" von deinem Gerät entfernt werden? Die Datei auf dem Server bleibt davon unberührt.",
"MessageConfirmDeleteLocalFiles": "Sollen lokale Dateien dieses Elements von deinem Gerät entfernt werden? Die Dateien auf dem Server und Ihr Fortschritt bleiben davon unberührt.",
"MessageConfirmDeleteServerConfig": "Diese Server-Konfiguration entfernen?",
"MessageConfirmDeleteServerEpisode": "Sind Sie sicher, dass Sie die Episode \"{0}\" vom Server löschen wollen?\nWarnung: Damit wird die Audio-Datei gelöscht.",
"MessageConfirmDisableAutoTimer": "Bist du sicher, dass du den automatischen Timer für den Rest des Tages deaktivieren möchtest? Der Timer wird am Ende dieser automatischen Schlaf-Timer-Periode oder beim Neustart der App wieder aktiviert.",
"MessageConfirmDiscardProgress": "Bist du sicher, dass du deinen Fortschritt zurücksetzen willst?",
"MessageConfirmDownloadUsingCellular": "Du bist dabei, über mobile Daten herunterzuladen. Dies kann zu Gebühren deines Mobilfunkanbieters führen. Möchtest du fortfahren?",
"MessageConfirmMarkAsFinished": "Bist du sicher, dass du diesen Artikel als beendet markieren willst?",
"MessageConfirmPlaybackTime": "Wiedergabe von \"{0}\" bei {1} starten?",
"MessageConfirmRemoveBookmark": "Bist du sicher, dass du das Lesezeichen entfernen willst?",
"MessageConfirmStreamingUsingCellular": "Du bist dabei, über mobile Daten zu streamen. Dies kann zu Gebühren deines Mobilfunkanbieters führen. Möchtest du fortfahren?",
"MessageDiscardProgress": "Fortschritt verwerfen",
@@ -355,5 +370,7 @@
"ToastPodcastCreateSuccess": "Podcast erstellt",
"ToastRSSFeedCloseFailed": "RSS-Feed konnte nicht geschlossen werden",
"ToastRSSFeedCloseSuccess": "RSS-Feed geschlossen",
"ToastStreamingNotAllowedOnCellular": "Das Streamen über mobile Daten ist nicht erlaubt"
"ToastStreamingNotAllowedOnCellular": "Das Streamen über mobile Daten ist nicht erlaubt",
"UnitMinutesShort": "{0}m",
"UnitSecondsShort": "{0}s"
}
+221
View File
@@ -0,0 +1,221 @@
{
"ButtonAdd": "Προσθήκη",
"ButtonAddNewServer": "Προσθήκη Νέου Διακομιστή",
"ButtonAuthors": "Συγγραφείς",
"ButtonBack": "Πίσω",
"ButtonCancel": "Ακύρωση",
"ButtonCancelTimer": "Ακύρωση Χρονόμετρου",
"ButtonClearFilter": "Διαγραφή Φίλτρου",
"ButtonClearLogs": "Διαγραφή Αρχείων Καταγραφής",
"ButtonCloseFeed": "Κλείσιμο Τροφοδοσίας",
"ButtonCollections": "Συλλογές",
"ButtonConnect": "Σύνδεση",
"ButtonConnectToServer": "Σύνδεση σε Διακομιστή",
"ButtonCreate": "Δημιουργία",
"ButtonCreateBookmark": "Δημιουργία Σελιδοδείκτη",
"ButtonCreateNewPlaylist": "Δημιουργία Νέας Λίστας Αναπαραγωγής",
"ButtonDelete": "Διαγραφή",
"ButtonDeleteLocalEpisode": "Διαγραφή τοπικού επεισοδίου",
"ButtonDeleteLocalFile": "Διαγραφή τοπικού αρχείου",
"ButtonDeleteLocalItem": "Διαγραφή τοπικού αντικειμένου",
"ButtonDisableAutoTimer": "Απενεργοποίηση Αυτόματου Χρονόμετρου",
"ButtonDisconnect": "Αποσύνδεση Σύνδσης",
"ButtonGoToWebClient": "Μετάβαση στον Web Client",
"ButtonHistory": "Ιστορικό",
"ButtonHome": "Αρχική",
"ButtonIssues": "Θέματα",
"ButtonLatest": "Τελευταία",
"ButtonLibrary": "Βιβλιοθήκη",
"ButtonLocalMedia": "Τοπικά Μέσα",
"ButtonLogs": "Αρχεία Καταγραφής",
"ButtonManageLocalFiles": "Διαχείριση Τοπικών Αρχείων",
"ButtonMaskServerAddress": "Απόκρυψη διέθυνσης διακομιστή",
"ButtonNewFolder": "Νέος Φάκελος",
"ButtonNextEpisode": "Επόμενο Επεισόδιο",
"ButtonOk": "Εντάξει",
"ButtonOpenFeed": "Άνοιγμα Τροφοδοσίας",
"ButtonOverride": "Παράκαμψη",
"ButtonPause": "Παύση",
"ButtonPlay": "Αναπαραγωγή",
"ButtonPlayEpisode": "Αναπαραγωγή Επεισοδίου",
"ButtonPlaylists": "Λίστες Αναπαραγωγής",
"ButtonRead": "Ανάγνωση",
"ButtonReadLess": "Ανάγνωση λιγότερων",
"ButtonReadMore": "Διάβασε περισσότερα",
"ButtonRemove": "Αφαίρεση",
"ButtonRemoveFromServer": "Αφαίρεση απ'τον Διακομιστή",
"ButtonSave": "Αποθήκευση",
"ButtonSaveOrder": "Αποθήκευση Ταξινόμησης",
"ButtonSearch": "Αναζήτηση",
"ButtonSendEbookToDevice": "Αποστολή Ebook σε Συσκευή",
"ButtonSeries": "Σειρά",
"ButtonSetTimer": "Ορισμός Χρονοδιακόπτη",
"ButtonStream": "Μετάδοση",
"ButtonSubmit": "Υποβολή",
"ButtonSwitchServerUser": "Αλλαγή Διακομιστή/Χρήστη",
"ButtonUnmaskServerAddress": "Αφαίρεση απόκρυψης διακομιστή",
"ButtonUserStats": "Στατιστικά Χρήστη",
"ButtonYes": "Ναι",
"HeaderAccount": "Λογαριασμός",
"HeaderAdvanced": "Για Προχωρημένους",
"HeaderAndroidAutoSettings": "Αυτόματες Ρυθμίσεις Διαχειριστή",
"HeaderAudioTracks": "Κομμάτια Ήχου",
"HeaderChapters": "Κεφάλαια",
"HeaderCollection": "Συλλογή",
"HeaderCollectionItems": "Αντικείμενα Συλλογής",
"HeaderConnectionStatus": "Στατιστικά Σύνδεσης",
"HeaderDataSettings": "Ρυθμίσεις Δεδομένων",
"HeaderDetails": "Λεπτομέρειες",
"HeaderDownloads": "Λήψεις",
"HeaderEbookFiles": "Αρχεία Ebook",
"HeaderEpisodes": "Επεισόδια",
"HeaderEreaderSettings": "Ρυθμίσεις Ereader",
"HeaderLatestEpisodes": "Τελευταία Επεισόδια",
"HeaderLibraries": "Βιβλιοθήκες",
"HeaderLocalFolders": "Τοπικοί Φάκελοι",
"HeaderLocalLibraryItems": "Αντικείμενα Τοπικής Βιβλιοθήκης",
"HeaderNewPlaylist": "Νέα Λίστα Αναπαραγωγής",
"HeaderOpenRSSFeed": "Άνοιγμα Τροφοδοσίας RSS",
"HeaderPlaybackSettings": "Ρυθμίσεις Αναπαραγωγής",
"HeaderPlaylist": "Λίστα Αναπαραγωγής",
"HeaderPlaylistItems": "Αντικείμενα Λίστας Αναπαραγωγής",
"HeaderProgressSyncFailed": "Αποτυχία Συγχρονισμού Προόδου",
"HeaderRSSFeed": "Τροφοδοσία RSS",
"HeaderRSSFeedGeneral": "Λεπτομέρειες RSS",
"HeaderRSSFeedIsOpen": "Η Τροφοδοσία RSS είναι Ανοιχτή",
"HeaderSelectDownloadLocation": "Επιλογή Τοποθεσίας Λήψης",
"HeaderSettings": "Ρυθμίσεις",
"HeaderSleepTimer": "Χρονοδιακόπτης Ύπνου",
"HeaderSleepTimerSettings": "Ρυθμίσεις Χρονοδιακόπτη Ύπνου",
"HeaderStatsMinutesListeningChart": "Λεπτά Ακρόασης (τελευταίες 7 ημέρες)",
"HeaderStatsRecentSessions": "Πρόσφατες Συνεδρίες",
"HeaderTableOfContents": "Πίνακας Περιεχομένων",
"HeaderUserInterfaceSettings": "Ρυθμίσεις Διεπαφής Χρήστη",
"HeaderYourStats": "Τα Στατιστικά Σας",
"LabelAddToPlaylist": "Προσθήκη στην Λίστα Αναπαραγωγής",
"LabelAddedAt": "Προστέθηκε Στις",
"LabelAddedDate": "Προστέθηκε {0}",
"LabelAll": "Όλα",
"LabelAllowSeekingOnMediaControls": "Να επιτρέπεται η αλλαγή θέσης από τα χειριστήρια ειδοποιήσεων πολυμέσων",
"LabelAlways": "Πάντα",
"LabelAndroidAutoBrowseLimitForGrouping": "Όριο λίστας κατά αλφαβητική σειρά",
"LabelAndroidAutoBrowseSeriesSequenceOrder": "Ταξινόμηση βιβλίων σειράς",
"LabelAskConfirmation": "Ερώτηση για επιβεβαίωση",
"LabelAuthor": "Συγγραφέας",
"LabelAuthorFirstLast": "Συγγραφέας (Όνομα Επώνυμο)",
"LabelAuthorLastFirst": "Συγγραφέας (Επώνυμο, Όνομα)",
"LabelAuthors": "Συγγραφείς",
"LabelAutoDownloadEpisodes": "Αυτόματο Κατέβασμα Επεισοδίων",
"LabelAutoSleepTimer": "Αυτόματος Χρονοδιακόπτης Ύπνου",
"LabelBooks": "Βιβλία",
"LabelByAuthor": "κατά {0}",
"LabelChapterTrack": "Κομμάτι Κεφαλαίου",
"LabelChapters": "Κεφάλαια",
"LabelClosePlayer": "Κλείσιμο αναπαραγωγής",
"LabelComplete": "Ολοκλήρωση",
"LabelContinueBooks": "Συνέχεια Βιβλίων",
"LabelContinueEpisodes": "Συνέχεια Επεισοδίων",
"LabelContinueListening": "Συνέχεια Ακρόασης",
"LabelContinueReading": "Συνέχεια Ανάγνωσης",
"LabelContinueSeries": "Συνέχεια Σειράς",
"LabelDescription": "Περιγραφή",
"LabelDownload": "Λήψη",
"LabelDownloadUsingCellular": "Λήψη με χρήση δεδομένων",
"LabelDownloaded": "Ληφθέντα",
"LabelDuration": "Διάρκεια",
"LabelEbook": "Ebook",
"LabelEbooks": "Ebooks",
"LabelEnable": "Ενεργοποίηση",
"LabelEnd": "Τέλος",
"LabelEndOfChapter": "Τέλος Κεφαλαίου",
"LabelEpisode": "Επεισόδιο",
"LabelFile": "Αρχείο",
"LabelFilename": "Όνομα Αρχείου",
"LabelFinished": "Ολοκληρώθηκε",
"LabelFolder": "Φάκελος",
"LabelFontFamily": "Οικογένεια Γραμματοσειράς",
"LabelGenre": "Είδος",
"LabelGenres": "Είδη",
"LabelHost": "Διακομιστής",
"LabelInProgress": "Σε Εξέλιξη",
"LabelLanguage": "Γλώσσα",
"LabelLayoutAuto": "Αυτόματα",
"LabelLayoutSinglePage": "Μονή Σελίδα",
"LabelLight": "Ανοιχτό",
"LabelListenAgain": "Επανάληψη Ακρόασης",
"LabelLocalBooks": "Τοπικά Βιβλία",
"LabelLocalPodcasts": "Τοπικά Podcasts",
"LabelLow": "Χαμηλά",
"LabelMediaType": "Τύπος Πολυμέσων",
"LabelMore": "Περισσότερα",
"LabelMoreInfo": "Περισσότερες Πληροφορίες",
"LabelName": "Όνομα",
"LabelNarrator": "Αφηγητής",
"LabelNarrators": "Αφηγητές",
"LabelNavigateWithVolumeMirrored": "Καθρεπτισμός",
"LabelNavigateWithVolumeWhilePlayingDisabled": "Ανενεργό",
"LabelNavigateWithVolumeWhilePlayingEnabled": "Ενεργό",
"LabelNever": "Ποτέ",
"LabelNewestAuthors": "Πρόσφατοι Συγγραφείς",
"LabelNewestEpisodes": "Πρόσφατα Επεισόδια",
"LabelNo": "Όχι",
"LabelNotStarted": "Δεν Έχει Ξεκινήσει",
"LabelNumEpisodes": "{0} επεισόδια",
"LabelNumberOfEpisodes": "# Επεισοδίων",
"LabelOff": "Ανενεργό",
"LabelOn": "Ενεργό",
"LabelPassword": "Κωδικός Πρόσβασης",
"LabelPath": "Διαδρομή",
"LabelPlaybackLocal": "Τοπικά",
"LabelPlaybackSpeed": "Ταχύτητα Αναπαραγωγής",
"LabelProgress": "Πρόοδος",
"LabelPublishYear": "Χρονολογία Έκδοσης",
"LabelPublishedDate": "Εκδόθηκε {0}",
"LabelRandomly": "Τυχαία",
"LabelRead": "Ανάγνωση",
"LabelReadAgain": "Ανάγνωση Ξανά",
"LabelRecentSeries": "Πρόσφατη Σειρά",
"LabelRecentlyAdded": "Προστέθηκαν Πρόσφατα",
"LabelRemoveFromPlaylist": "Αφαίρεση από την Λίστα Αναπαραγωγής",
"LabelSelectADevice": "Επιλογή συσκευής",
"LabelSeries": "Σειρά",
"LabelServerAddress": "Διεύθυνση Διακομιστή",
"LabelSetEbookAsPrimary": "Ορισμός ως πρωτεύων",
"LabelShowAll": "Εμφάνιση Όλων",
"LabelSize": "Μέγεθος",
"LabelSleepTimer": "Χρονοδιακόπτης Ύπνου",
"LabelStart": "Έναρξη",
"LabelStatsBestDay": "Καλύτερη Ημέρα",
"LabelStatsDailyAverage": "Ημερήσιος Μέσος Όρος",
"LabelStatsDays": "Ημέρες",
"LabelStatsDaysListened": "Ημέρες Ακρόασης",
"LabelStatsInARow": "Σε σειρά",
"LabelStatsItemsFinished": "Ολοκληρωμένα Αντικείμενα",
"LabelStatsMinutes": "λεπτά",
"LabelStatsMinutesListening": "Λεπτά Ακρόασης",
"LabelStatsWeekListening": "Εβδομαδιαία Ακρόαση",
"LabelTheme": "Θέμα",
"LabelThemeBlack": "Μαύρο",
"LabelThemeDark": "Σκοτεινό",
"LabelThemeLight": "Φωτεινό",
"LabelTimeRemaining": "{0} απομένουν",
"LabelTitle": "Τίτλος",
"LabelTotalSize": "Συνολικό Μέγεθος",
"LabelTracks": "Κομμάτια",
"LabelType": "Τύπος",
"LabelUnknown": "Άγνωστο",
"LabelUseBookshelfView": "Χρήση προβολής βιβλιοθήκης",
"LabelUser": "Χρήστης",
"LabelUsername": "Όνομα Χρήστη",
"LabelVeryHigh": "Πολύ Ψηλά",
"LabelVeryLow": "Πολύ Χαμηλά",
"LabelYourProgress": "Η Πρόοδος Σας",
"MessageDownloadCompleteProcessing": "Η λήψη ολοκληρώθηκε. Επεξεργασία...",
"MessageDownloading": "Λήψη...",
"MessageDownloadingEpisode": "Λήψη επεισοδίου",
"MessageLoading": "Φόρτωση...",
"MessageMarkAsFinished": "Σήμανση ως Ολοκληρωμένο",
"MessageNoItemsFound": "Δεν βρέθηκαν αντικείμενα",
"MessageNoNetworkConnection": "Δεν υπάρχει σύνδεση δικτύου",
"MessageNoUserPlaylists": "Δεν έχετε λίστες αναπαραγωγής"
}
+15 -1
View File
@@ -63,6 +63,7 @@
"HeaderChapters": "Chapters",
"HeaderCollection": "Collection",
"HeaderCollectionItems": "Collection Items",
"HeaderConfirm": "Confirm",
"HeaderConnectionStatus": "Connection Status",
"HeaderDataSettings": "Data Settings",
"HeaderDetails": "Details",
@@ -91,6 +92,7 @@
"HeaderStatsRecentSessions": "Recent Sessions",
"HeaderTableOfContents": "Table of Contents",
"HeaderUserInterfaceSettings": "User Interface Settings",
"HeaderWelcome": "Welcome, <strong>{0}</strong>",
"HeaderYourStats": "Your Stats",
"LabelAddToPlaylist": "Add to Playlist",
"LabelAddedAt": "Added At",
@@ -113,6 +115,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "When the auto sleep timer finishes, playing the item again will automatically rewind your position.",
"LabelAutoSleepTimerHelp": "When playing media between the specified start and end times a sleep timer will automatically start.",
"LabelBooks": "Books",
"LabelByAuthor": "by {0}",
"LabelChapterTrack": "Chapter Track",
"LabelChapters": "Chapters",
"LabelClosePlayer": "Close player",
@@ -177,6 +180,9 @@
"LabelLayout": "Layout",
"LabelLayoutAuto": "Auto",
"LabelLayoutSinglePage": "Single page",
"LabelLibrarySortByProgress": "Progress: Last Updated",
"LabelLibrarySortByProgressFinished": "Progress: Finished",
"LabelLibrarySortByProgressStarted": "Progress: Started",
"LabelLight": "Light",
"LabelLineSpacing": "Line spacing",
"LabelListenAgain": "Listen Again",
@@ -236,6 +242,7 @@
"LabelScaleElapsedTimeBySpeed": "Scale Elapsed Time by Speed",
"LabelSeason": "Season",
"LabelSelectADevice": "Select a device",
"LabelSelectMediaType": "Select media type",
"LabelSequenceAscending": "Sequence Ascending",
"LabelSequenceDescending": "Sequence Descending",
"LabelSeries": "Series",
@@ -288,12 +295,17 @@
"MessageAudiobookshelfServerNotConnected": "Audiobookshelf server not connected",
"MessageAudiobookshelfServerRequired": "<strong>Important!</strong> This app is designed to work with an Audiobookshelf server that you or someone you know is hosting. This app does not provide any content.",
"MessageBookshelfEmpty": "Bookshelf empty",
"MessageConfirmAppExit":"Did you want to exit the app?",
"MessageConfirmDeleteEpisodeDownloadQueue": "Are you sure you want to clear episode download queue?",
"MessageConfirmDeleteLocalEpisode": "Remove local episode \"{0}\" from your device? The file on the server will be unaffected.",
"MessageConfirmDeleteLocalFiles": "Remove local files of this item from your device? The files on the server and your progress will be unaffected.",
"MessageConfirmDeleteServerConfig": "Remove this server config?",
"MessageConfirmDeleteServerEpisode": "Are you sure you want to delete episode \"{0}\" from the server?\nWarning: This will delete the audio file.",
"MessageConfirmDisableAutoTimer": "Are you sure you want to disable the auto timer for the rest of today? The timer will be re-enabled at the end of this auto-sleep timer period, or if you restart the app.",
"MessageConfirmDiscardProgress": "Are you sure you want to reset your progress?",
"MessageConfirmDownloadUsingCellular": "You are about to download using cellular data. This may include carrier data charges. Do you wish to continue?",
"MessageConfirmMarkAsFinished": "Are you sure you want to mark this item as finished?",
"MessageConfirmPlaybackTime":"Start playback for \"{0}\" at {1}?",
"MessageConfirmRemoveBookmark": "Are you sure you want to remove bookmark?",
"MessageConfirmStreamingUsingCellular": "You are about to stream using cellular data. This may include carrier data charges. Do you wish to continue?",
"MessageDiscardProgress": "Discard Progress",
@@ -358,5 +370,7 @@
"ToastPodcastCreateSuccess": "Podcast created successfully",
"ToastRSSFeedCloseFailed": "Failed to close RSS feed",
"ToastRSSFeedCloseSuccess": "RSS feed closed",
"ToastStreamingNotAllowedOnCellular": "Streaming is not allowed on cellular data"
"ToastStreamingNotAllowedOnCellular": "Streaming is not allowed on cellular data",
"UnitMinutesShort": "{0}m",
"UnitSecondsShort": "{0}s"
}
+8
View File
@@ -113,6 +113,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Cuando el temporizador de auto apagado finaliza, reproducir el elemento nuevamente rebobinará automáticamente tu posición.",
"LabelAutoSleepTimerHelp": "Cuando se reproduce contenido multimedia entre las horas de inicio y finalización especificadas, se activará automáticamente un temporizador de apagado.",
"LabelBooks": "Libros",
"LabelByAuthor": "por",
"LabelChapterTrack": "Seguimiento de Capítulo",
"LabelChapters": "Capítulos",
"LabelClosePlayer": "Cerrar reproductor",
@@ -155,6 +156,9 @@
"LabelFinished": "Terminado",
"LabelFolder": "Carpeta",
"LabelFontBoldness": "Peso tipográfico",
"LabelFontFamily": "Familia tipográfica",
"LabelFontFamilySans": "Sans",
"LabelFontFamilySerif": "Serif",
"LabelFontScale": "Escala de letra",
"LabelGenre": "Género",
"LabelGenres": "Géneros",
@@ -221,6 +225,7 @@
"LabelPublishedDate": "Publicado {0}",
"LabelRSSFeedCustomOwnerEmail": "Correo electrónico de dueño personalizado",
"LabelRSSFeedCustomOwnerName": "Nombre de dueño personalizado",
"LabelRSSFeedOpen": "Fuente RSS Abierta",
"LabelRSSFeedPreventIndexing": "Evitar indización",
"LabelRSSFeedSlug": "«Slug» de suministro RSS",
"LabelRandomly": "Aleatorio",
@@ -297,6 +302,7 @@
"MessageDownloading": "Descargando...",
"MessageDownloadingEpisode": "Descargando episodio",
"MessageEpisodesQueuedForDownload": "{0} episodio(s) en cola para descargar",
"MessageFailedToRefreshToken": "No se pudo actualizar el token, se requiere reiniciar la sesión",
"MessageFeedURLWillBe": "El URL del suministro será {0}",
"MessageFetching": "Recuperando...",
"MessageFollowTheProjectOnGithub": "Siga el proyecto en GitHub",
@@ -324,6 +330,8 @@
"MessageNoSeries": "Ninguna serie",
"MessageNoUpdatesWereNecessary": "No fue necesario actualizar",
"MessageNoUserPlaylists": "No tiene ninguna lista de reproducción",
"MessageOldServerAuthReLoginRequired": "La autenticación se ha mejorado para seguridad en la versión v2.26.0 del servidor. Todos los usuarios deberán reiniciar sesión.",
"MessageOldServerAuthWarning": "El servidor está utilizando un método de autenticación anticuado",
"MessageOldServerConnectionWarning": "La configuración de la conexión al servidor utiliza un identificador de usuario antiguo. Elimine y vuelva a añadir esta conexión al servidor.",
"MessageOldServerConnectionWarningHelp": "Usted configuró originalmente la conexión a este servidor antes de la migración de la base de datos en la versión 2.3.0, publicada en junio de 2023. Una futura actualización del servidor eliminará la posibilidad de iniciar sesión con esta conexión antigua. Por favor, elimine la conexión existente al servidor y conéctese de nuevo (utilizando la misma dirección del servidor y las mismas credenciales). Si tiene algún medio descargado en este dispositivo, será necesario descargarlo de nuevo para sincronizarlo con el servidor.",
"MessagePodcastSearchField": "Introduzca el término de búsqueda o el URL del suministro RSS",
+18 -1
View File
@@ -63,6 +63,7 @@
"HeaderChapters": "Luvut",
"HeaderCollection": "Kokoelma",
"HeaderCollectionItems": "Kokoelman osat",
"HeaderConfirm": "Vahvista",
"HeaderConnectionStatus": "Kokoelman tila",
"HeaderDataSettings": "Tietojen asetukset",
"HeaderDetails": "Yksityiskohdat",
@@ -91,6 +92,7 @@
"HeaderStatsRecentSessions": "Viimeaikaiset istunnot",
"HeaderTableOfContents": "Sisällysluettelo",
"HeaderUserInterfaceSettings": "Käyttöliittymän asetukset",
"HeaderWelcome": "Tervetuloa, <strong>{0</strong>",
"HeaderYourStats": "Tilastosi",
"LabelAddToPlaylist": "Lisää soittolistaan",
"LabelAddedAt": "Lisätty listalle",
@@ -113,6 +115,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Kun automaattinen uniajastin päättyy, ensi kerralla toistetaan osa kuunenltua uudelleen.",
"LabelAutoSleepTimerHelp": "Toiston alkaessa tällä aikävälillä unikytkin kytketään automaattisesti käyttöön.",
"LabelBooks": "Kirjat",
"LabelByAuthor": "Tekijältä: {0}",
"LabelChapterTrack": "Luvun raita",
"LabelChapters": "Luvut",
"LabelClosePlayer": "Sulje soitin",
@@ -155,6 +158,9 @@
"LabelFinished": "Valmis",
"LabelFolder": "Kansio",
"LabelFontBoldness": "Kirjasintyyppien lihavointi",
"LabelFontFamily": "Fonttiperhe",
"LabelFontFamilySans": "Sans",
"LabelFontFamilySerif": "Serif",
"LabelFontScale": "Kirjasintyyppien skaalautuminen",
"LabelGenre": "Lajityyppi",
"LabelGenres": "Lajityypit",
@@ -174,6 +180,9 @@
"LabelLayout": "Asettelu",
"LabelLayoutAuto": "Automaattinen",
"LabelLayoutSinglePage": "Yksi sivu",
"LabelLibrarySortByProgress": "Edistyminen: Viimeksi päivitetty",
"LabelLibrarySortByProgressFinished": "Edistyminen: Valmis",
"LabelLibrarySortByProgressStarted": "Edistyminen: Aloitettu",
"LabelLight": "Vaalea",
"LabelLineSpacing": "Riviväli",
"LabelListenAgain": "Kuuntele uudelleen",
@@ -233,6 +242,7 @@
"LabelScaleElapsedTimeBySpeed": "Skaalaa kulunut aika nopeuden mukaan",
"LabelSeason": "Kausi",
"LabelSelectADevice": "Valitse laite",
"LabelSelectMediaType": "Valitse mediatyyppi",
"LabelSequenceAscending": "Nouseva sekvenssi",
"LabelSequenceDescending": "Laskeva sekvenssi",
"LabelSeries": "Sarja",
@@ -285,12 +295,17 @@
"MessageAudiobookshelfServerNotConnected": "Audiobookshelf palvelinta ei ole yhdistetty",
"MessageAudiobookshelfServerRequired": "<strong>Tärkeää!</strong> Tämä sovellus on suunniteltu toimimaan sinun tai tuttavasi Audiobookshelf-palvelimen kanssa. Tämä sovellus ei tarjoa sisältöä.",
"MessageBookshelfEmpty": "Kirjahylly on tyhjä",
"MessageConfirmAppExit": "Haluatko poistua sovelluksesta?",
"MessageConfirmDeleteEpisodeDownloadQueue": "Haluatko varmasti tyhjentää jaksojen latausjonon?",
"MessageConfirmDeleteLocalEpisode": "Poista jakso \"{0}\" laitteeltasi? Tämä ei vaikuta palvelimella olevaan tiedostoon.",
"MessageConfirmDeleteLocalFiles": "Poista tämän kohteen tiedostot laitteestasi? Tämä ei vaikuta palvelimella oleviin tiedostoihin tai edistymiseesi.",
"MessageConfirmDeleteServerConfig": "Poistetaanko palvelimen konfiguraatio?",
"MessageConfirmDeleteServerEpisode": "Haluatko varmasti poistaa jakson \"{0}\" palvelimelta?\nVaroitus: Tämä poistaa äänitiedoston.",
"MessageConfirmDisableAutoTimer": "Oletko varma, että haluat poistaa automaattisen ajastimen käytöstä loppupäivän ajaksi? Ajastin otetaan uudelleen käyttöön tämän automaattisen uniajastimen jakson lopussa tai jos käynnistät sovelluksen uudelleen.",
"MessageConfirmDiscardProgress": "Haluatko varmasti nollata edistymisesi?",
"MessageConfirmDownloadUsingCellular": "Olet lataamassa mobiilidatan avulla. Tämä voi aiheuttaa operaattorin datamaksuja. Haluatko jatkaa?",
"MessageConfirmMarkAsFinished": "Haluatko varmasti merkitä tämän kohteen valmiiksi?",
"MessageConfirmPlaybackTime": "Toistetaanko \"{0}\" kohdasta {1}?",
"MessageConfirmRemoveBookmark": "Haluatko varmasti poistaa kirjanmerkin?",
"MessageConfirmStreamingUsingCellular": "Olet suoratoistamassa matkapuhelindatan avulla. Tämä voi aiheuttaa operaattorin datamaksuja. Haluatko jatkaa?",
"MessageDiscardProgress": "Hylkää edistyminen",
@@ -355,5 +370,7 @@
"ToastPodcastCreateSuccess": "Podcastin luominen onnistui",
"ToastRSSFeedCloseFailed": "RSS syötteen sulkeminen epäonnistui",
"ToastRSSFeedCloseSuccess": "RSS syöte suljettu",
"ToastStreamingNotAllowedOnCellular": "Suoratoisto ei ole sallittu mobiilidatalla"
"ToastStreamingNotAllowedOnCellular": "Suoratoisto ei ole sallittu mobiilidatalla",
"UnitMinutesShort": "{0}m",
"UnitSecondsShort": "{0}s"
}
+20 -3
View File
@@ -63,6 +63,7 @@
"HeaderChapters": "Chapitres",
"HeaderCollection": "Collection",
"HeaderCollectionItems": "Entrées de la collection",
"HeaderConfirm": "Confirmer",
"HeaderConnectionStatus": "Status de connexion",
"HeaderDataSettings": "Paramètres de données",
"HeaderDetails": "Détails",
@@ -91,6 +92,7 @@
"HeaderStatsRecentSessions": "Sessions récentes",
"HeaderTableOfContents": "Table des matières",
"HeaderUserInterfaceSettings": "Paramètres de l'interface",
"HeaderWelcome": "Bienvenue, <strong>{0}</strong>",
"HeaderYourStats": "Vos statistiques",
"LabelAddToPlaylist": "Ajouter à la liste de lecture",
"LabelAddedAt": "Date dajout",
@@ -113,6 +115,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Lorsque le minuteur nocturne se termine, relire l'élément fera un saut en arrière.",
"LabelAutoSleepTimerHelp": "Lorsqu'un éléments est lu entre l'heure de début et de fin, un minuteur nocturne se lance automatiquement.",
"LabelBooks": "Livres",
"LabelByAuthor": "de {0}",
"LabelChapterTrack": "Piste des chapitres",
"LabelChapters": "Chapitres",
"LabelClosePlayer": "Fermer le lecteur",
@@ -155,7 +158,10 @@
"LabelFinished": "Fini(e)",
"LabelFolder": "Dossier",
"LabelFontBoldness": "Graisse de la police",
"LabelFontScale": "Taille de la police de caractère",
"LabelFontFamily": "Famille de caractères",
"LabelFontFamilySans": "Sans",
"LabelFontFamilySerif": "Avec empattements",
"LabelFontScale": "Taille de la police",
"LabelGenre": "Genre",
"LabelGenres": "Genres",
"LabelHapticFeedback": "Retour haptique",
@@ -174,7 +180,10 @@
"LabelLayout": "Mise en page",
"LabelLayoutAuto": "Automatique",
"LabelLayoutSinglePage": "Page seule",
"LabelLight": "Léger",
"LabelLibrarySortByProgress": "Progression : Mise à jour",
"LabelLibrarySortByProgressFinished": "Progression : Terminé",
"LabelLibrarySortByProgressStarted": "Progression : En cours",
"LabelLight": "Clair",
"LabelLineSpacing": "Interligne",
"LabelListenAgain": "Écouter à nouveau",
"LabelLocalBooks": "Livres locaux",
@@ -233,6 +242,7 @@
"LabelScaleElapsedTimeBySpeed": "Traduire le temps restant en fonction de la vitesse de lecture",
"LabelSeason": "Saison",
"LabelSelectADevice": "Sélectionner un Appareil",
"LabelSelectMediaType": "Sélectionnez le type de media",
"LabelSequenceAscending": "Séquence ascendante",
"LabelSequenceDescending": "Séquence descendante",
"LabelSeries": "Séries",
@@ -285,12 +295,17 @@
"MessageAudiobookshelfServerNotConnected": "Serveur Audiobookshelf non connecté",
"MessageAudiobookshelfServerRequired": "<strong>Important!</strong> Cette application est faite pour fonctionner avec un serveur Audiobookshelf. L'application ne fournit aucun contenu.",
"MessageBookshelfEmpty": "Bibliothèque vide",
"MessageConfirmAppExit": "Voulez-vous quitter l'application?",
"MessageConfirmDeleteEpisodeDownloadQueue": "Voulez-vous vraiment vider la file d'attente de téléchargement des épisodes?",
"MessageConfirmDeleteLocalEpisode": "Retirer l’épisode local « {0} » de votre appareil? Le fichier sur le serveur ne sera pas affecté.",
"MessageConfirmDeleteLocalFiles": "Supprimer les fichiers locaux de cet élément de votre appareil ? Les fichiers sur le serveur ainsi que votre progression ne serons pas affectés.",
"MessageConfirmDeleteServerConfig": "Supprimer la configuration de ce serveur?",
"MessageConfirmDeleteServerEpisode": "Voulez-vous vraiment supprimer l'épisode \"{0}\" du serveur?\nAttention : le fichier audio sera supprimé.",
"MessageConfirmDisableAutoTimer": "Êtes-vous sûr·e de vouloir désactiver le minuteur automatique pour le reste de la journée? Le minuteur sera réactivé à la fin de cette période de décompte automatique, ou si vous redémarrez l'application.",
"MessageConfirmDiscardProgress": "Êtes-vous sûr·e de vouloir supprimer votre progression?",
"MessageConfirmDownloadUsingCellular": "Vous êtes sur le point deffectuer un téléchargement en utilisant des données mobiles.Il se peut que des frais de données soient facturés par votre opérateur. Souhaitez-vous continuer?",
"MessageConfirmMarkAsFinished": "Êtes-vous sûr·e de vouloir marquer cette élement comme terminé ?",
"MessageConfirmPlaybackTime": "Lancer la lecture de \"{0}\" à {1}?",
"MessageConfirmRemoveBookmark": "Êtes-vous sûr·e de vouloir supprimer le marque-page?",
"MessageConfirmStreamingUsingCellular": "Vous êtes sur le point de diffuser du contenu en utilisant des données mobiles. Il se peut que des frais de données soient facturés par votre opérateur. Souhaitez-vous continuer?",
"MessageDiscardProgress": "Supprimer la progression",
@@ -355,5 +370,7 @@
"ToastPodcastCreateSuccess": "Podcast créé avec succès",
"ToastRSSFeedCloseFailed": "Échec de la fermeture du flux RSS",
"ToastRSSFeedCloseSuccess": "Flux RSS fermé",
"ToastStreamingNotAllowedOnCellular": "La diffusion sur les données mobile nest pas autorisée"
"ToastStreamingNotAllowedOnCellular": "La diffusion sur les données mobile nest pas autorisée",
"UnitMinutesShort": "{0}min",
"UnitSecondsShort": "{0}sec"
}
+3
View File
@@ -174,6 +174,9 @@
"LabelLayout": "Layout",
"LabelLayoutAuto": "אוטומטי",
"LabelLayoutSinglePage": "עמוד יחיד",
"LabelLibrarySortByProgress": "התקדמות: עודכן לאחרונה",
"LabelLibrarySortByProgressFinished": "התקדמות: הושלם",
"LabelLibrarySortByProgressStarted": "התקדמות: הותחל",
"LabelLight": "בהיר",
"LabelLineSpacing": "מרווח שורה",
"LabelListenAgain": "האזן שוב",
+4
View File
@@ -113,6 +113,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Kada automatsk timer za spavanje završi, ponovna reprodukcija stavke će se automatski vratiti na zadani položaj.",
"LabelAutoSleepTimerHelp": "Automatski timer za spavanje uključit će se u zadano vrijeme prilikom izvođenja medija.",
"LabelBooks": "Knjige",
"LabelByAuthor": "autor: {0}",
"LabelChapterTrack": "Zapis poglavlja",
"LabelChapters": "Poglavlja",
"LabelClosePlayer": "Zatvori reproduktor",
@@ -155,6 +156,9 @@
"LabelFinished": "Završeno",
"LabelFolder": "Mapa",
"LabelFontBoldness": "Debljina slova",
"LabelFontFamily": "Skup pisma",
"LabelFontFamilySans": "Sans",
"LabelFontFamilySerif": "Serif",
"LabelFontScale": "Veličina slova",
"LabelGenre": "Žanr",
"LabelGenres": "Žanrovi",
+18 -1
View File
@@ -63,6 +63,7 @@
"HeaderChapters": "Fejezetek",
"HeaderCollection": "Gyűjtemény",
"HeaderCollectionItems": "Gyűjtemény elemek",
"HeaderConfirm": "Megerősítés",
"HeaderConnectionStatus": "Kapcsolat állapota",
"HeaderDataSettings": "Adat beállítások",
"HeaderDetails": "Részletek",
@@ -91,6 +92,7 @@
"HeaderStatsRecentSessions": "Legutóbbi munkamenetek",
"HeaderTableOfContents": "Tartalomjegyzék",
"HeaderUserInterfaceSettings": "Felhasználói felület beállításai",
"HeaderWelcome": "Üdv, <strong>{0}</strong>",
"HeaderYourStats": "Saját statisztikák",
"LabelAddToPlaylist": "Hozzáadás a lejátszási listához",
"LabelAddedAt": "Hozzáadva ekkor",
@@ -113,6 +115,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Amikor az automatikus alvásidőzítő befejeződik, az elem újrajátszásakor automatikusan visszatekeri a pozíciót.",
"LabelAutoSleepTimerHelp": "Amikor a megadott kezdési és befejezési idők között média lejátszása történik, egy alvásidőzítő automatikusan elindul.",
"LabelBooks": "Könyv",
"LabelByAuthor": "{0} által",
"LabelChapterTrack": "Fejezet sáv",
"LabelChapters": "Fejezetek",
"LabelClosePlayer": "Lejátszó bezárása",
@@ -155,6 +158,9 @@
"LabelFinished": "Befejezve",
"LabelFolder": "Mappa",
"LabelFontBoldness": "Betű vastagság",
"LabelFontFamily": "Betűcsalád",
"LabelFontFamilySans": "Sans",
"LabelFontFamilySerif": "Serif",
"LabelFontScale": "Betűméret skála",
"LabelGenre": "Műfaj",
"LabelGenres": "Műfajok",
@@ -174,6 +180,9 @@
"LabelLayout": "Elrendezés",
"LabelLayoutAuto": "Automatikus",
"LabelLayoutSinglePage": "Egyoldalas",
"LabelLibrarySortByProgress": "Folyamat: Legutóbbi frissítés",
"LabelLibrarySortByProgressFinished": "Folyamat: Befejezve",
"LabelLibrarySortByProgressStarted": "Folyamat: Elindult",
"LabelLight": "Könnyű",
"LabelLineSpacing": "Sorköz",
"LabelListenAgain": "Újrahallgatás",
@@ -233,6 +242,7 @@
"LabelScaleElapsedTimeBySpeed": "Eltelt idő skálázása sebesség szerint",
"LabelSeason": "Évad",
"LabelSelectADevice": "Eszköz kiválasztása",
"LabelSelectMediaType": "Médiatípus kiválasztása",
"LabelSequenceAscending": "Emelkedő sorrend",
"LabelSequenceDescending": "Csökkenő sorrend",
"LabelSeries": "Sorozat",
@@ -285,12 +295,17 @@
"MessageAudiobookshelfServerNotConnected": "Az Audiobookshelf szerver nem csatlakozik",
"MessageAudiobookshelfServerRequired": "<strong>Fontos!</strong> Ez az alkalmazás egy Audiobookshelf szervert igényel, amit Ön vagy valaki, akit ismer, üzemeltet. Ez az alkalmazás nem biztosít tartalmat.",
"MessageBookshelfEmpty": "A könyvespolc üres",
"MessageConfirmAppExit": "Biztosan ki szeretne lépni az alkalmazásból?",
"MessageConfirmDeleteEpisodeDownloadQueue": "Biztosan törölni szeretné az epizódletöltési várólistát?",
"MessageConfirmDeleteLocalEpisode": "\"{0}\" helyi epizód eltávolítása az eszközről? A szerveren lévő fájl nem érintett.",
"MessageConfirmDeleteLocalFiles": "Ezen elem helyi fájljainak eltávolítása az eszközről? A szerveren lévő fájlok és a haladás nem érintettek.",
"MessageConfirmDeleteServerConfig": "Eltávolítja ezt a szerverkonfigurációt?",
"MessageConfirmDeleteServerEpisode": "Biztosan törölni szeretnéd a(z) „{0}” epizódot a szerverről?\nFigyelem: ezzel az audi fájl is törlődik.",
"MessageConfirmDisableAutoTimer": "Biztos, hogy a mai nap hátralévő részére ki akarja kapcsolni az automatikus időzítőt? Az időzítő újra aktiválódik az automatikus alvásidőzítő időszak végén, vagy ha újraindítja az alkalmazást.",
"MessageConfirmDiscardProgress": "Biztosan alaphelyzetbe akarja állítani a haladást?",
"MessageConfirmDownloadUsingCellular": "Mobiladat-hálózaton keresztül készülsz letölteni. Ez adatforgalmi díjakkal járhat. Szeretnéd folytatni?",
"MessageConfirmMarkAsFinished": "Biztosan befejezettnek jelöli ezt az elemet?",
"MessageConfirmPlaybackTime": "Elindítod a(z) „{0}” lejátszását {1}-tól?",
"MessageConfirmRemoveBookmark": "Biztosan eltávolítja a könyvjelzőt?",
"MessageConfirmStreamingUsingCellular": "Mobiladat-hálózaton keresztül készülsz streamelni. Ez adatforgalmi díjakkal járhat. Szeretnéd folytatni?",
"MessageDiscardProgress": "Haladás elvetése",
@@ -355,5 +370,7 @@
"ToastPodcastCreateSuccess": "A podcast sikeresen létrehozva",
"ToastRSSFeedCloseFailed": "Az RSS hírcsatorna bezárása sikertelen",
"ToastRSSFeedCloseSuccess": "Az RSS hírcsatorna sikeresen bezárva",
"ToastStreamingNotAllowedOnCellular": "Streamelés mobilinternettel nem engedélyezett"
"ToastStreamingNotAllowedOnCellular": "Streamelés mobilinternettel nem engedélyezett",
"UnitMinutesShort": "{0}p",
"UnitSecondsShort": "{0}mp"
}
+1
View File
@@ -0,0 +1 @@
{}
+4
View File
@@ -113,6 +113,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Al termine del timer di spegnimento automatico, la riproduzione dell'elemento riavvolgerà automaticamente la tua posizione.",
"LabelAutoSleepTimerHelp": "Durante la riproduzione di contenuti multimediali tra l'ora di inizio e quella di fine specificate, verrà avviato automaticamente un timer di spegnimento.",
"LabelBooks": "Libri",
"LabelByAuthor": "di {0}",
"LabelChapterTrack": "Traccia capitolo",
"LabelChapters": "Capitoli",
"LabelClosePlayer": "Chiudi player",
@@ -155,6 +156,9 @@
"LabelFinished": "Finita",
"LabelFolder": "Cartella",
"LabelFontBoldness": "Grassetto",
"LabelFontFamily": "Famiglia caratteri",
"LabelFontFamilySans": "Sans",
"LabelFontFamilySerif": "Serif",
"LabelFontScale": "Dimensione font",
"LabelGenre": "Genere",
"LabelGenres": "Generi",
+45 -2
View File
@@ -47,8 +47,10 @@
"ButtonSave": "保存",
"ButtonSaveOrder": "並び替えを保存",
"ButtonSearch": "検索",
"ButtonSendEbookToDevice": "Ebookをデバイスに転送",
"ButtonSeries": "シリーズ",
"ButtonSetTimer": "タイマーを設定",
"ButtonStream": "ストリーム",
"ButtonSubmit": "送信",
"ButtonSwitchServerUser": "サーバー/ユーザーの切り替え",
"ButtonUnmaskServerAddress": "サーバーアドレスを表示",
@@ -61,6 +63,7 @@
"HeaderChapters": "チャプター",
"HeaderCollection": "コレクション",
"HeaderCollectionItems": "コレクションの項目",
"HeaderConfirm": "確認",
"HeaderConnectionStatus": "接続状況",
"HeaderDataSettings": "データ設定",
"HeaderDetails": "詳細",
@@ -74,38 +77,65 @@
"HeaderLocalLibraryItems": "ローカルライブラリーの項目",
"HeaderNewPlaylist": "新しいプレイリスト",
"HeaderOpenRSSFeed": "RSS Feedを開く",
"HeaderPlaybackSettings": "再生設定",
"HeaderPlaylist": "プレイリスト",
"HeaderPlaylistItems": "プレイリストアイテム",
"HeaderProgressSyncFailed": "進行中の同期失敗",
"HeaderRSSFeed": "RSS Feed",
"HeaderRSSFeed": "RSSフィード",
"HeaderRSSFeedGeneral": "RSS 詳細",
"HeaderRSSFeedIsOpen": "RSSフィードが開いています",
"HeaderSelectDownloadLocation": "保存場所の選択",
"HeaderSettings": "設定",
"HeaderSleepTimer": "スリープタイマー",
"HeaderSleepTimerSettings": "スリープタイマー設定",
"HeaderStatsMinutesListeningChart": "過去7日間の視聴時間(分)",
"HeaderUserInterfaceSettings": "UI設定",
"HeaderStatsRecentSessions": "最近の再生履歴",
"HeaderTableOfContents": "目次",
"HeaderUserInterfaceSettings": "画面設定",
"HeaderWelcome": "ようこそ <strong>{0}</strong>",
"HeaderYourStats": "再生統計",
"LabelAddToPlaylist": "プレイリストの追加",
"LabelAddedAt": "追加日時",
"LabelAddedDate": "追加日時 ­­{0}",
"LabelAll": "すべて",
"LabelAllowSeekingOnMediaControls": "メディア通知コントロールでの位置情報の取得を許可",
"LabelAlways": "常に",
"LabelAndroidAutoBrowseLimitForGrouping": "アルファベット順表示の制限",
"LabelAndroidAutoBrowseLimitForGroupingHelp": "表示項目数がこの数未満の場合、アルファベット順ドローダウンを使用しません",
"LabelAndroidAutoBrowseSeriesSequenceOrder": "シリーズ内の順序",
"LabelAskConfirmation": "確認を求める",
"LabelAuthor": "著者",
"LabelAuthorFirstLast": "著者(名 氏)",
"LabelAuthorLastFirst": "著者(氏 名)",
"LabelAuthors": "著者",
"LabelAutoDownloadEpisodes": "エピソードの自動ダウンロード",
"LabelAutoRewindTime": "自動巻き戻し時間",
"LabelAutoSleepTimer": "自動スリープタイマー",
"LabelAutoSleepTimerAutoRewind": "スリープタイマー時の自動巻き戻し",
"LabelAutoSleepTimerAutoRewindHelp": "自動スリープタイマーが終了した後、再生を再開すると再生位置が自動的に巻き戻されます。",
"LabelAutoSleepTimerHelp": "指定した開始時刻から終了時刻の間にメディアを再生すると、スリープタイマーが自動的に開始されます。",
"LabelBooks": "ほん",
"LabelByAuthor": "著 {0}",
"LabelChapterTrack": "チャプタートラック",
"LabelChapters": "チャプター",
"LabelClosePlayer": "プレイヤーを閉じる",
"LabelCollapseSeries": "シリーズを折りたたむ",
"LabelComplete": "完了",
"LabelContinueBooks": "続きを読む本",
"LabelContinueEpisodes": "続きのエピソード",
"LabelContinueListening": "続きから聞く",
"LabelContinueReading": "続きを読む",
"LabelContinueSeries": "シリーズを続く",
"LabelCustomTime": "指定時間",
"LabelDescription": "説明",
"LabelDisableAudioFadeOut": "オーディオフェードアウトを無効",
"LabelDisableAudioFadeOutHelp": "スリープタイマーの残り時間が1分を切ると、音量が徐々に小さくなります。フェードアウトしないようにするには、この設定を有効にしてください。",
"LabelDisableAutoRewind": "自動巻き戻しを無効",
"LabelDisableShakeToReset": "シェイクでリセットを無効化",
"LabelDisableShakeToResetHelp": "タイマー作動中、またはタイマー終了後2分以内に端末を振ると、スリープタイマーがリセットされます。この設定を有効にすると、振ってリセットする機能を無効にできます。",
"LabelDisableVibrateOnReset": "リセット時の振動を無効化",
"LabelDisableVibrateOnResetHelp": "スリープタイマーがリセットされると、デバイスが振動します。この設定を有効にすると、スリープタイマーがリセットされた際に振動しなくなります。",
"LabelDiscover": "おすすめ",
"LabelDownload": "ダウンロード",
"LabelDownloadUsingCellular": "モバイル通信を使用してダウンロード",
"LabelDownloaded": "ダウンロード完了",
@@ -115,20 +145,33 @@
"LabelEnable": "有効",
"LabelEnableMp3IndexSeeking": "mp3インデックス検索を有効化",
"LabelEnableMp3IndexSeekingHelp": "この設定は、正しくシークできないMP3ファイルがある場合にのみ有効にしてください。シークの不正確さは、可変ビットレート(VBR)のMP3ファイルが原因である可能性が高いです。この設定はインデックスシークを強制し、ファイルの読み取り時に時間-バイトマッピングを構築します。大きなMP3ファイルの場合、ファイルの終わり付近をシークする際に遅延が生じる場合があります。",
"LabelEnd": "終了",
"LabelEndOfChapter": "チャプターの最後",
"LabelEndTime": "終了時間",
"LabelEpisode": "エピソード",
"LabelExplicit": "露骨な表現",
"LabelFeedURL": "Feed URL",
"LabelFile": "ファイル",
"LabelFileBirthtime": "ファイル作成日時",
"LabelFileModified": "ファイル更新日時",
"LabelFilename": "ファイル名",
"LabelFinished": "完了",
"LabelFolder": "フォルダ",
"LabelFontBoldness": "フォントの太さ",
"LabelFontFamily": "フォントファミリー",
"LabelFontFamilySans": "サン",
"LabelFontFamilySerif": "セリフ",
"LabelFontScale": "フォントサイズ",
"LabelGenre": "ジャンル",
"LabelGenres": "ジャンル",
"LabelHapticFeedback": "ハプティックフィードバック",
"LabelHasEbook": "eBookあり",
"LabelHasSupplementaryEbook": "付属eBookあり",
"LabelHeavy": "思い",
"LabelHigh": "高い",
"LabelHost": "ホスト",
"LabelInProgress": "進行中",
"LabelIncomplete": "未完了",
"LabelInternalAppStorage": "アプリ内ストレージ",
"LabelKeepScreenAwake": "画面をスリープにしない",
"LabelLanguage": "言語",
+362 -1
View File
@@ -1 +1,362 @@
{}
{
"ButtonAdd": "추가",
"ButtonAddNewServer": "새로운 서버 추가",
"ButtonAuthors": "작가",
"ButtonBack": "뒤로",
"ButtonCancel": "취소",
"ButtonCancelTimer": "타이머 취소",
"ButtonClearFilter": "필터 지우기",
"ButtonClearLogs": "로그 지우기",
"ButtonCloseFeed": "피드 닫기",
"ButtonCollections": "컬렉션",
"ButtonConnect": "접속",
"ButtonConnectToServer": "서버에 연결",
"ButtonCreate": "만들기",
"ButtonCreateBookmark": "북마크 만들기",
"ButtonCreateNewPlaylist": "새로운 재생목록 만들기",
"ButtonDelete": "삭제",
"ButtonDeleteLocalEpisode": "로컬 에피소드 삭제",
"ButtonDeleteLocalFile": "로컬 파일 삭제",
"ButtonDeleteLocalItem": "로컬 항목 삭제",
"ButtonDisableAutoTimer": "자동 타이머 비활성화",
"ButtonDisconnect": "연결 해제",
"ButtonGoToWebClient": "웹 클라이언트로 이동",
"ButtonHistory": "히스토리",
"ButtonHome": "홈",
"ButtonIssues": "이슈",
"ButtonLatest": "최신",
"ButtonLibrary": "라이브러리",
"ButtonLocalMedia": "로컬 미디어",
"ButtonLogs": "로그",
"ButtonManageLocalFiles": "로컬 파일 관리",
"ButtonMaskServerAddress": "마스크 서버 주소",
"ButtonNewFolder": "새 폴더",
"ButtonNextEpisode": "다음 에피소드",
"ButtonOk": "확인",
"ButtonOpenFeed": "피드 열기",
"ButtonOverride": "Override",
"ButtonPause": "일시정지",
"ButtonPlay": "재생",
"ButtonPlayEpisode": "에피소드 재생",
"ButtonPlaylists": "재생목록",
"ButtonRead": "읽기",
"ButtonReadLess": "덜 읽기",
"ButtonReadMore": "더 읽기",
"ButtonRemove": "제거",
"ButtonRemoveFromServer": "서버에서 제거",
"ButtonSave": "저장",
"ButtonSaveOrder": "저장 순서",
"ButtonSearch": "검색",
"ButtonSendEbookToDevice": "기기로 전자책 보내기",
"ButtonSeries": "시리즈",
"ButtonSetTimer": "타이머 설정",
"ButtonStream": "스트림",
"ButtonSubmit": "제출",
"ButtonSwitchServerUser": "서버/사용자 전환",
"ButtonUnmaskServerAddress": "서버 주소 마스크 해제",
"ButtonUserStats": "사용자 통계",
"ButtonYes": "예",
"HeaderAccount": "계정",
"HeaderAdvanced": "고급",
"HeaderAndroidAutoSettings": "안드로이드 오토 설정",
"HeaderAudioTracks": "오디오 트랙",
"HeaderChapters": "챕터",
"HeaderCollection": "컬렉션",
"HeaderCollectionItems": "컬렉션 항목",
"HeaderConnectionStatus": "연결 상태",
"HeaderDataSettings": "데이터 설정",
"HeaderDetails": "세부사항",
"HeaderDownloads": "다운로드",
"HeaderEbookFiles": "전자책 파일",
"HeaderEpisodes": "에피소드",
"HeaderEreaderSettings": "전자책 리더 설정",
"HeaderLatestEpisodes": "최신 에피소드",
"HeaderLibraries": "라이브러리",
"HeaderLocalFolders": "로컬 폴더",
"HeaderLocalLibraryItems": "로컬 라이브러리 항목",
"HeaderNewPlaylist": "새로운 플레이리스트",
"HeaderOpenRSSFeed": "RSS 피드 열기",
"HeaderPlaybackSettings": "재생 설정",
"HeaderPlaylist": "재생목록",
"HeaderPlaylistItems": "재생 목록 항목",
"HeaderProgressSyncFailed": "진행률 동기화 실패",
"HeaderRSSFeed": "RSS 피드",
"HeaderRSSFeedGeneral": "RSS 자세히",
"HeaderRSSFeedIsOpen": "RSS 피드가 열려 있습니다",
"HeaderSelectDownloadLocation": "다운로드 위치 선택",
"HeaderSettings": "설정",
"HeaderSleepTimer": "슬립 타이머",
"HeaderSleepTimerSettings": "슬립 타이머 설정",
"HeaderStatsMinutesListeningChart": "청취 시간(지난 7일)",
"HeaderStatsRecentSessions": "최근 세션",
"HeaderTableOfContents": "목차",
"HeaderUserInterfaceSettings": "사용자 인터페이스 설정",
"HeaderYourStats": "내 통계",
"LabelAddToPlaylist": "재생목록에 추가",
"LabelAddedAt": "추가됨",
"LabelAddedDate": "{0} 추가됨",
"LabelAll": "모두",
"LabelAllowSeekingOnMediaControls": "미디어 알림 컨트롤에서 위치 탐색 허용",
"LabelAlways": "항상",
"LabelAndroidAutoBrowseLimitForGrouping": "알파벳별 인출 한도",
"LabelAndroidAutoBrowseLimitForGroupingHelp": "표시할 항목 수가 이 금액보다 적을 경우 알파벳 순으로 삭감하지 마십시오.",
"LabelAndroidAutoBrowseSeriesSequenceOrder": "시리즈 책 주문",
"LabelAskConfirmation": "확인을 요청하세요",
"LabelAuthor": "작가",
"LabelAuthorFirstLast": "작가 (이름 성)",
"LabelAuthorLastFirst": "작가 (성, 이름)",
"LabelAuthors": "작가",
"LabelAutoDownloadEpisodes": "에피소드 자동 다운로드",
"LabelAutoRewindTime": "자동 되감기 시간",
"LabelAutoSleepTimer": "자동 슬립 타이머",
"LabelAutoSleepTimerAutoRewind": "자동 슬립 타이머 자동 되감기",
"LabelAutoSleepTimerAutoRewindHelp": "자동 슬립 타이머가 끝나면 해당 항목을 다시 재생하면 자동으로 위치가 되돌려집니다.",
"LabelAutoSleepTimerHelp": "지정된 시작 및 종료 시간 사이에 미디어를 재생하면 슬립 타이머가 자동으로 시작됩니다.",
"LabelBooks": "전자책",
"LabelChapterTrack": "챕터 트랙",
"LabelChapters": "챕터",
"LabelClosePlayer": "플레이어 닫기",
"LabelCollapseSeries": "시리즈 펴기",
"LabelComplete": "완료",
"LabelContinueBooks": "책 계속 읽기",
"LabelContinueEpisodes": "에피소드 계속하기",
"LabelContinueListening": "계속 듣기",
"LabelContinueReading": "계속 읽기",
"LabelContinueSeries": "시리즈 계속하기",
"LabelCustomTime": "사용자 지정 시간",
"LabelDescription": "설명",
"LabelDisableAudioFadeOut": "오디오 페이드아웃 비활성화",
"LabelDisableAudioFadeOutHelp": "슬립 타이머가 1분 미만으로 남았을 때 오디오 볼륨이 감소하기 시작합니다. 이 설정을 활성화하면 볼륨이 점점 작아지지 않습니다.",
"LabelDisableAutoRewind": "자동 되감기 비활성화",
"LabelDisableShakeToReset": "흔들어서 재설정을 해제하세요",
"LabelDisableShakeToResetHelp": "타이머가 작동하는 동안 또는 타이머가 만료되기 2분 전에 기기를 흔들면 슬립 타이머가 재설정됩니다. 이 설정을 활성화하면 흔들어서 재설정하는 기능을 비활성화할 수 있습니다.",
"LabelDisableVibrateOnReset": "재설정 시 진동 비활성화",
"LabelDisableVibrateOnResetHelp": "슬립 타이머가 재설정되면 기기가 진동합니다. 슬립 타이머가 재설정될 때 진동하지 않도록 하려면 이 설정을 활성화하세요.",
"LabelDiscover": "발견",
"LabelDownload": "다운로드",
"LabelDownloadUsingCellular": "셀룰러를 사용하여 다운로드",
"LabelDownloaded": "다운로드됨",
"LabelDuration": "기간",
"LabelEbook": "전자책",
"LabelEbooks": "전자책",
"LabelEnable": "활성화",
"LabelEnableMp3IndexSeeking": "mp3 인덱스 검색 활성화",
"LabelEnableMp3IndexSeekingHelp": "이 설정은 MP3 파일의 탐색이 제대로 이루어지지 않는 경우에만 활성화해야 합니다. 탐색이 부정확한 이유는 가변 비트레이트(VBR) MP3 파일 때문일 가능성이 높습니다. 이 설정은 파일을 읽을 때 시간-바이트 매핑이 생성되는 인덱스 탐색을 강제로 실행합니다. 대용량 MP3 파일의 경우 파일 끝부분을 탐색할 때 지연이 발생할 수 있습니다.",
"LabelEnd": "마지막",
"LabelEndOfChapter": "챕터의 마지작",
"LabelEndTime": "종료 시간",
"LabelEpisode": "에피소드",
"LabelExplicit": "명백한",
"LabelFeedURL": "피드 URL",
"LabelFile": "파일",
"LabelFileBirthtime": "파일 생년월일",
"LabelFileModified": "파일 수정됨",
"LabelFilename": "파일 이름",
"LabelFinished": "완료됨",
"LabelFolder": "폴더",
"LabelFontBoldness": "글꼴 굵기",
"LabelFontFamily": "글꼴 모양",
"LabelFontFamilySans": "Sans",
"LabelFontFamilySerif": "Serif",
"LabelFontScale": "글꼴 크기",
"LabelGenre": "장르",
"LabelGenres": "장르",
"LabelHapticFeedback": "햅틱 피드백",
"LabelHasEbook": "보유한 전자책",
"LabelHasSupplementaryEbook": "보유한 보충 전자책",
"LabelHeavy": "무거운",
"LabelHigh": "높게",
"LabelHost": "호스트",
"LabelInProgress": "진행 중",
"LabelIncomplete": "불완전한",
"LabelInternalAppStorage": "내부 앱 저장소",
"LabelJumpBackwardsTime": "뒤로 시간 점프",
"LabelJumpForwardsTime": "앞으로 시간 점프",
"LabelKeepScreenAwake": "화면 항상 켜기",
"LabelLanguage": "언어",
"LabelLayout": "레이아웃",
"LabelLayoutAuto": "자동",
"LabelLayoutSinglePage": "단일 페이지",
"LabelLight": "Light",
"LabelLineSpacing": "줄 간격",
"LabelListenAgain": "다시 듣기",
"LabelLocalBooks": "로컬 전자책",
"LabelLocalPodcasts": "로컬 팟케스트",
"LabelLockOrientation": "잠금 방향",
"LabelLockPlayer": "플레이어 잠금",
"LabelLow": "낮게",
"LabelMediaType": "미디어 유형",
"LabelMedium": "중간",
"LabelMissing": "누락",
"LabelMore": "더보기",
"LabelMoreInfo": "정보 더 보기",
"LabelName": "이름",
"LabelNarrator": "내레이터",
"LabelNarrators": "내레이터",
"LabelNavigateWithVolume": "볼륨 키로 탐색",
"LabelNavigateWithVolumeMirrored": "미러링됨",
"LabelNavigateWithVolumeWhilePlaying": "재생 중 볼륨 키를 사용하여 탐색할 수 있도록 허용",
"LabelNavigateWithVolumeWhilePlayingDisabled": "오프",
"LabelNavigateWithVolumeWhilePlayingEnabled": "온",
"LabelNever": "Never",
"LabelNewestAuthors": "최신 작가",
"LabelNewestEpisodes": "최신 에피소드",
"LabelNo": "아니오",
"LabelNotFinished": "완료되지 않음",
"LabelNotStarted": "시작되지 않음",
"LabelNumEpisodes": "{0}개 에피소드",
"LabelNumEpisodesIncomplete": "{0}개 에피소드, {1}개 미완료",
"LabelNumberOfEpisodes": "# 의 에피소드",
"LabelOff": "오프",
"LabelOn": "온",
"LabelPassword": "비밀번호",
"LabelPath": "경로",
"LabelPlaybackDirect": "직접",
"LabelPlaybackLocal": "로컬",
"LabelPlaybackSpeed": "재생 속도",
"LabelPlaybackTranscode": "트랜스코드",
"LabelPodcast": "팟케스트",
"LabelPodcasts": "팟케스트",
"LabelPreventIndexing": "iTunes 및 Google Podcast 디렉토리에서 피드가 인덱싱되는 것을 방지합니다.",
"LabelProgress": "진행",
"LabelPubDate": "출판 날짜",
"LabelPublishYear": "출판 연도",
"LabelPublishedDate": "출판됨 {0}",
"LabelRSSFeedCustomOwnerEmail": "사용자 정의 이메일",
"LabelRSSFeedCustomOwnerName": "사용자 정의 이름",
"LabelRSSFeedOpen": "RSS 피드 열기",
"LabelRSSFeedPreventIndexing": "인덱싱 방지",
"LabelRSSFeedSlug": "RSS 피드 슬러그",
"LabelRandomly": "무작위로",
"LabelRead": "읽기",
"LabelReadAgain": "다시 읽기",
"LabelRecentSeries": "최근 시리즈",
"LabelRecentlyAdded": "최근 추가됨",
"LabelRemoveFromPlaylist": "재생 목록에서 제거",
"LabelScaleElapsedTimeBySpeed": "속도에 따른 경과 시간 스케일링",
"LabelSeason": "시즌",
"LabelSelectADevice": "기기를 선택하세요",
"LabelSequenceAscending": "시퀀스 오름차순",
"LabelSequenceDescending": "시퀀스 내림차순",
"LabelSeries": "시리즈",
"LabelServerAddress": "서버 주소",
"LabelSetEbookAsPrimary": "기본으로 설정",
"LabelSetEbookAsSupplementary": "보충으로 설정",
"LabelShakeSensitivity": "흔들림 감도",
"LabelShowAll": "모두 표시",
"LabelSize": "크기",
"LabelSleepTimer": "슬립 타이머",
"LabelSleepTimerAlmostDoneChime": "거의 끝나면 차임벨을 울리세요",
"LabelSleepTimerAlmostDoneChimeHelp": "슬립 타이머가 30초 남았을 때 차임음을 재생합니다.",
"LabelStart": "시작",
"LabelStartTime": "시작 시간",
"LabelStatsBestDay": "최고의 날",
"LabelStatsDailyAverage": "일일 평균",
"LabelStatsDays": "일",
"LabelStatsDaysListened": "청취 일수",
"LabelStatsInARow": "in a row",
"LabelStatsItemsFinished": "완료된 항목",
"LabelStatsMinutes": "분",
"LabelStatsMinutesListening": "청취 분수",
"LabelStatsWeekListening": "주간 청취",
"LabelStreamingUsingCellular": "셀룰러를 이용한 스트리밍",
"LabelTag": "태그",
"LabelTags": "태그",
"LabelTheme": "테마",
"LabelThemeBlack": "Black",
"LabelThemeDark": "Dark",
"LabelThemeLight": "Light",
"LabelTimeRemaining": "{0} 남음",
"LabelTitle": "제목",
"LabelTotalSize": "전체 크기",
"LabelTotalTrack": "총 트랙",
"LabelTracks": "트랙",
"LabelType": "유형",
"LabelUnknown": "미상",
"LabelUnlockPlayer": "플레이어 잠금 해제",
"LabelUseBookshelfView": "bookshelf view 사용",
"LabelUser": "사용자",
"LabelUsername": "사용자 이름",
"LabelVeryHigh": "매우 높음",
"LabelVeryLow": "매우 낮음",
"LabelYearReviewHide": "연간 리뷰 숨기기",
"LabelYearReviewShow": "올해의 리뷰 보기",
"LabelYourBookmarks": "내 북마크",
"LabelYourProgress": "내 진행 상황",
"MessageAndroid10Downloads": "Android 10 이하에서는 다운로드를 위해 내부 앱 저장소를 사용합니다.",
"MessageAttemptingServerConnection": "서버 연결을 시도 중입니다...",
"MessageAudiobookshelfServerNotConnected": "Audiobookshelf 서버가 연결되지 않았습니다",
"MessageAudiobookshelfServerRequired": "<strong>중요!</strong> 이 앱은 본인이나 아는 사람이 호스팅하는 Audiobookshelf 서버와 함께 사용하도록 설계되었습니다. 이 앱은 어떠한 콘텐츠도 제공하지 않습니다.",
"MessageBookshelfEmpty": "책장이 비어 있음",
"MessageConfirmDeleteLocalEpisode": "기기에서 로컬 에피소드 \"{0}\"을(를) 삭제하시겠습니까? 서버에 있는 파일은 영향을 받지 않습니다.",
"MessageConfirmDeleteLocalFiles": "이 항목의 로컬 파일을 기기에서 제거하시겠습니까? 서버의 파일과 진행 상황에는 아무런 영향이 없습니다.",
"MessageConfirmDisableAutoTimer": "오늘 남은 시간 동안 자동 타이머를 비활성화하시겠습니까? 자동 슬립 타이머 기간이 끝나거나 앱을 다시 시작하면 타이머가 다시 활성화됩니다.",
"MessageConfirmDiscardProgress": "진행 상황을 재설정하시겠습니까?",
"MessageConfirmDownloadUsingCellular": "셀룰러 데이터를 사용하여 다운로드하려고 합니다. 이동통신사 데이터 요금이 부과될 수 있습니다. 계속하시겠습니까?",
"MessageConfirmMarkAsFinished": "이 항목을 완료로 표시하시겠습니까?",
"MessageConfirmRemoveBookmark": "북마크를 삭제하시겠습니까?",
"MessageConfirmStreamingUsingCellular": "셀룰러 데이터를 사용하여 스트리밍하려고 합니다. 이동통신사 데이터 요금이 부과될 수 있습니다. 계속하시겠습니까?",
"MessageDiscardProgress": "진행 상황 삭제",
"MessageDownloadCompleteProcessing": "다운로드가 완료되었습니다. 처리 중입니다...",
"MessageDownloading": "다운로드 중...",
"MessageDownloadingEpisode": "에피소드 다운로드 중",
"MessageEpisodesQueuedForDownload": "{0}개의 에피소드가 다운로드 대기 중입니다.",
"MessageFailedToRefreshToken": "토큰 새로 고침에 실패했습니다. 다시 로그인해야 합니다.",
"MessageFeedURLWillBe": "피드 URL은 {0}입니다.",
"MessageFetching": "가져오는 중...",
"MessageFollowTheProjectOnGithub": "Github에서 프로젝트를 팔로우하세요",
"MessageItemDownloadCompleteFailedToCreate": "항목 다운로드가 완료되었지만 라이브러리 항목을 생성하지 못했습니다.",
"MessageItemMissing": "항목이 누락되어 서버에서 수정해야 합니다. 일반적으로 파일 경로에 접근할 수 없기 때문에 항목이 누락으로 표시됩니다.",
"MessageLoading": "로딩중...",
"MessageLoadingServerData": "서버 데이터를 로딩 중입니다...",
"MessageLocalFolderDescription": "''내부 앱 저장소'는 이 앱에서만 접근할 수 있습니다. 이 앱은 앱을 통해 직접 다운로드한 미디어만 지원합니다. 공유 저장소 폴더를 사용하면 다른 앱이 이 앱에서 다운로드한 미디어에 접근할 수 있습니다.",
"MessageMarkAsFinished": "완료로 표시",
"MessageMediaLinkedToADifferentServer": "미디어가 다른 주소({0})의 오디오북셸프 서버에 연결되어 있습니다. 이 서버 주소에 연결되면 진행 상황이 동기화됩니다.",
"MessageMediaLinkedToADifferentUser": "미디어가 이 서버에 연결되어 있지만 다른 사용자가 다운로드했습니다. 진행 상황은 해당 미디어를 다운로드한 사용자에게만 동기화됩니다.",
"MessageMediaLinkedToServer": "서버 {0}에 연결됨",
"MessageMediaLinkedToThisServer": "다운로드한 미디어가 이 서버에 연결되었습니다.",
"MessageMediaNotLinkedToServer": "미디어가 오디오북 셸프 서버에 연결되지 않았습니다. 진행 상황이 동기화되지 않습니다.",
"MessageNoBookmarks": "북마크 없음",
"MessageNoChapters": "챕터 없음",
"MessageNoCollections": "컬렉션 없음",
"MessageNoItems": "항목 없음",
"MessageNoItemsFound": "항목을 찾을 수 없음",
"MessageNoListeningSessions": "청취 세션 없음",
"MessageNoLogs": "로그 없음",
"MessageNoMediaFolders": "미디어 폴더 없음",
"MessageNoNetworkConnection": "네트워크 연결이 없음",
"MessageNoPodcastsFound": "팟캐스트를 찾을 수 없음",
"MessageNoSeries": "시리즈 없음",
"MessageNoUpdatesWereNecessary": "업데이트가 필요하지 않음",
"MessageNoUserPlaylists": "재생목록이 없음",
"MessageOldServerAuthReLoginRequired": "서버 v2.26.0에서는 보안을 위해 인증 기능이 개선되었습니다. 모든 사용자는 다시 로그인해야 합니다.",
"MessageOldServerAuthWarning": "서버가 오래된 인증을 사용하고 있습니다.",
"MessageOldServerAuthWarningHelp": "이 서버는 v2.26.0 이전 버전을 사용하고 있습니다. v2.26.0에서는 더욱 안전한 인증 시스템이 추가되었습니다. 서버를 최신 버전으로 업데이트하는 것을 강력히 권장합니다. 이미 서버를 업데이트하셨다면, 새로운 인증을 사용하려면 다시 로그인하세요.",
"MessageOldServerConnectionWarning": "서버 연결 구성에서 이전 사용자 ID를 사용하고 있습니다. 이 서버 연결을 삭제하고 다시 추가하세요.",
"MessageOldServerConnectionWarningHelp": "2023년 6월에 출시된 2.3.0 버전의 데이터베이스 마이그레이션 이전에 이 서버에 대한 연결을 설정했습니다. 향후 서버 업데이트에서는 이 이전 연결로 로그인할 수 있는 기능이 제거됩니다. 기존 서버 연결을 삭제하고 동일한 서버 주소와 사용자 인증 정보를 사용하여 다시 연결하세요. 이 기기에 다운로드한 미디어가 있는 경우, 서버와 동기화하려면 미디어를 다시 다운로드해야 합니다.",
"MessagePodcastSearchField": "검색어 또는 RSS 피드 URL을 입력하세요",
"MessageProgressSyncFailed": "서버에 청취 진행 상황을 보고하려는 최근 시도가 실패했습니다. 미디어 재생 중에는 15초에서 1분 간격으로 진행 상황 동기화 요청이 계속 시도됩니다.",
"MessageReportBugsAndContribute": "버그 보고, 기능 요청 및 기여",
"MessageSeriesAlreadyDownloaded": "이 시리즈의 모든 책을 이미 다운로드했습니다.",
"MessageSeriesDownloadConfirm": "{1}개의 파일과 함께 누락된 {0}권의 책, 총 {2}권을 {3} 폴더로 다운로드하시겠습니까?",
"MessageSeriesDownloadConfirmIos": "{1}개의 파일과 함께 누락된 {0}권의 책을 다운로드하시겠습니까? 총 {2}개입니다.",
"MessageSocketConnectedOverMeteredCellular": "미터링된 셀룰러를 통해 연결된 소켓",
"MessageSocketConnectedOverMeteredWifi": "미터기 Wi-Fi로 연결된 소켓",
"MessageSocketConnectedOverUnmeteredCellular": "무제한 셀룰러를 통해 연결된 소켓",
"MessageSocketConnectedOverUnmeteredWifi": "무제한 Wi-Fi로 연결된 소켓",
"MessageSocketNotConnected": "소켓이 연결되지 않음",
"NoteRSSFeedPodcastAppsHttps": "경고: 대부분의 팟캐스트 앱에서는 RSS 피드 URL이 HTTPS를 사용해야 합니다.",
"NoteRSSFeedPodcastAppsPubDate": "경고: 1개 이상의 에피소드에 게시 날짜가 없습니다. 일부 팟캐스트 앱에서는 게시 날짜가 필요합니다.",
"ToastBookmarkCreateFailed": "북마크를 생성하지 못했습니다.",
"ToastBookmarkRemoveFailed": "북마크를 삭제하지 못했습니다.",
"ToastBookmarkUpdateFailed": "북마크 업데이트에 실패했습니다",
"ToastDownloadNotAllowedOnCellular": "셀룰러 데이터에서는 다운로드가 허용되지 않습니다.",
"ToastItemMarkedAsFinishedFailed": "완료로 표시하지 못했습니다.",
"ToastItemMarkedAsNotFinishedFailed": "완료되지 않음으로 표시하는 데 실패했습니다.",
"ToastPlaylistCreateFailed": "플레이리스트를 생성하지 못했습니다",
"ToastPodcastCreateFailed": "팟캐스트를 만들지 못했습니다",
"ToastPodcastCreateSuccess": "팟캐스트가 성공적으로 생성되었습니다.",
"ToastRSSFeedCloseFailed": "RSS 피드를 닫지 못했습니다.",
"ToastRSSFeedCloseSuccess": "RSS 피드가 닫혔습니다",
"ToastStreamingNotAllowedOnCellular": "셀룰러 데이터에서는 스트리밍이 허용되지 않습니다."
}
+9
View File
@@ -6,6 +6,7 @@
"ButtonCancel": "Atšaukti",
"ButtonCancelTimer": "Atšaukti laikmatį",
"ButtonClearFilter": "Valyti filtrą",
"ButtonClearLogs": "Išvalyti žurnalus",
"ButtonCloseFeed": "Uždaryti srautą",
"ButtonCollections": "Kolekcijos",
"ButtonConnect": "Prijungti",
@@ -21,6 +22,7 @@
"ButtonIssues": "Problemos",
"ButtonLatest": "Naujausias",
"ButtonLibrary": "Biblioteka",
"ButtonLogs": "Žurnalai",
"ButtonManageLocalFiles": "Tvarkyti vietinius failus",
"ButtonNewFolder": "Naujas aplankas",
"ButtonNextEpisode": "Kitas epizodas",
@@ -68,6 +70,8 @@
"LabelAddToPlaylist": "Pridėti į grojaraštį",
"LabelAddedAt": "Pridėta {0}",
"LabelAll": "Visi",
"LabelAlways": "Visada",
"LabelAskConfirmation": "Prašyti patvirtinimo",
"LabelAuthor": "Autorius",
"LabelAuthorFirstLast": "Autorius (Vardas Pavardė)",
"LabelAuthorLastFirst": "Autorius (Pavardė, Vardas)",
@@ -80,10 +84,13 @@
"LabelComplete": "Baigta",
"LabelDescription": "Aprašymas",
"LabelDownload": "Atsisiųsti",
"LabelDownloaded": "Atsisiųsta",
"LabelDuration": "Trukmė",
"LabelEbook": "Elektroninė knyga",
"LabelEbooks": "El. knygos",
"LabelEnable": "Įjungti",
"LabelEnd": "Pabaiga",
"LabelEndOfChapter": "Skyriaus pabaiga",
"LabelEpisode": "Epizodas",
"LabelFeedURL": "Srauto URL",
"LabelFile": "Failas",
@@ -95,6 +102,8 @@
"LabelFontScale": "Šrifto mastelis",
"LabelGenre": "Žanras",
"LabelGenres": "Žanrai",
"LabelHasEbook": "Turi el. knygą",
"LabelHasSupplementaryEbook": "Turi papildomą el. knygą",
"LabelHost": "Serveris",
"LabelInProgress": "Vyksta",
"LabelIncomplete": "Nebaigta",
+15 -8
View File
@@ -48,7 +48,7 @@
"ButtonSaveOrder": "Zapisz kolejność",
"ButtonSearch": "Szukaj",
"ButtonSendEbookToDevice": "Wyślij ebook do urządzenia",
"ButtonSeries": "Seria",
"ButtonSeries": "Serie",
"ButtonSetTimer": "Ustaw wyłącznik",
"ButtonStream": "Strumieniuj",
"ButtonSubmit": "Zapisz",
@@ -79,7 +79,7 @@
"HeaderPlaybackSettings": "Ustawienia odtwarzania",
"HeaderPlaylist": "Playlista",
"HeaderPlaylistItems": "Pozycje listy odtwarzania",
"HeaderProgressSyncFailed": "Błąd synchronizacji postępów",
"HeaderProgressSyncFailed": "Synchronizacja postępu nie powiodła się",
"HeaderRSSFeed": "Kanał RSS",
"HeaderRSSFeedGeneral": "Szczegóły RSS",
"HeaderRSSFeedIsOpen": "Kanał RSS jest otwarty",
@@ -93,8 +93,8 @@
"HeaderUserInterfaceSettings": "Ustawienia inferfejsu użytkownika",
"HeaderYourStats": "Twoje statystyki",
"LabelAddToPlaylist": "Dodaj do playlisty",
"LabelAddedAt": "Dodano w",
"LabelAddedDate": "Dodano",
"LabelAddedAt": "Dodano",
"LabelAddedDate": "Dodano {0}",
"LabelAll": "Wszystkie",
"LabelAllowSeekingOnMediaControls": "Zezwól na wyszukiwanie pozycji na ekranie blokady",
"LabelAlways": "Zawsze",
@@ -146,6 +146,7 @@
"LabelEndOfChapter": "Koniec rozdziału",
"LabelEndTime": "Koniec czasu",
"LabelEpisode": "Odcinek",
"LabelExplicit": "18+",
"LabelFeedURL": "URL kanału",
"LabelFile": "Plik",
"LabelFileBirthtime": "Data utworzenia pliku",
@@ -154,6 +155,9 @@
"LabelFinished": "Zakończone",
"LabelFolder": "Katalog",
"LabelFontBoldness": "Grubość czcionki",
"LabelFontFamily": "Krój pisma",
"LabelFontFamilySans": "Pismo bezszeryfowe",
"LabelFontFamilySerif": "Pismo szeryfowe",
"LabelFontScale": "Rozmiar czcionki",
"LabelGenre": "Gatunek",
"LabelGenres": "Gatunki",
@@ -168,12 +172,14 @@
"LabelInternalAppStorage": "Pamięć wewnętrzna aplikacji",
"LabelJumpBackwardsTime": "Przeskok wstecz",
"LabelJumpForwardsTime": "Przeskok w przód",
"LabelKeepScreenAwake": "Utrzymuj włączony ekran",
"LabelKeepScreenAwake": "Utrzymuj ekran w stanie czuwania",
"LabelLanguage": "Język",
"LabelLayout": "Układ",
"LabelLayoutAuto": "Automatycznie",
"LabelLayoutSinglePage": "Pojedyncza strona",
"LabelLight": "Lekko",
"LabelLibrarySortByProgressFinished": "Postęp: Ukończony",
"LabelLibrarySortByProgressStarted": "Postęp: Rozpoczęty",
"LabelLight": "Jasny",
"LabelLineSpacing": "Odstęp między wierszami",
"LabelListenAgain": "Słuchaj ponownie",
"LabelLocalBooks": "Książki lokalne",
@@ -297,14 +303,15 @@
"MessageDownloading": "Pobieranie...",
"MessageDownloadingEpisode": "Pobieranie odcinka",
"MessageEpisodesQueuedForDownload": "{0} odcinki w kolejce do pobrania",
"MessageFailedToRefreshToken": "Odświeżenie tokenu nie powiodło się. Wymagane jest ponowne zalogowanie.",
"MessageFailedToRefreshToken": "Odświeżenie tokenu nie powiodło się. Wymagane jest ponowne zalogowanie",
"MessageFeedURLWillBe": "URL kanału: {0}",
"MessageFetching": "Pobieranie...",
"MessageFollowTheProjectOnGithub": "Obserwuj projekt na Github'ie",
"MessageItemDownloadCompleteFailedToCreate": "Pobieranie elementu zostało zakończone, ale nie udało się utworzyć elementu biblioteki",
"MessageItemMissing": "Brakujący element, należy go naprawić na serwerze. Zazwyczaj element jest oznaczany jako brakujący, ponieważ ścieżki do plików nie są dostępne.",
"MessageItemMissing": "Brakuje elementu i należy go naprawić na serwerze. Zazwyczaj element jest oznaczany jako brakujący, ponieważ ścieżki do plików nie są dostępne.",
"MessageLoading": "Ładowanie...",
"MessageLoadingServerData": "Ładowanie danych serwera...",
"MessageLocalFolderDescription": "„Wewnętrzna pamięć aplikacji” jest dostępna tylko dla tej aplikacji. Ta aplikacja obsługuje wyłącznie multimedia pobrane bezpośrednio za jej pośrednictwem. Udostępnione foldery pamięci można wykorzystać, aby umożliwić innym aplikacjom dostęp do multimediów pobranych przez tę aplikację.",
"MessageMarkAsFinished": "Oznacz jako ukończone",
"MessageMediaLinkedToADifferentServer": "Multimedia są połączone z serwerem Audiobookshelf pod innym adresem ({0}). Postęp zostanie zsynchronizowany po nawiązaniu połączenia z tym adresem serwera.",
"MessageMediaLinkedToADifferentUser": "Multimedia są połączone z tym serwerem, ale zostały pobrane przez innego użytkownika. Postęp zostanie zsynchronizowany tylko z użytkownikiem, który je pobrał.",
+10
View File
@@ -63,6 +63,7 @@
"HeaderChapters": "Capítulos",
"HeaderCollection": "Coleção",
"HeaderCollectionItems": "Itens da Coleção",
"HeaderConfirm": "Confirmar",
"HeaderConnectionStatus": "Status da Conexão",
"HeaderDataSettings": "Configurações de dados",
"HeaderDetails": "Detalhes",
@@ -91,6 +92,7 @@
"HeaderStatsRecentSessions": "Sessões Recentes",
"HeaderTableOfContents": "Sumário",
"HeaderUserInterfaceSettings": "Configurações da Interface do Usuário",
"HeaderWelcome": "Olá, <strong>{0}</strong>",
"HeaderYourStats": "Suas Estatísticas",
"LabelAddToPlaylist": "Adicionar à Lista de Reprodução",
"LabelAddedAt": "Acrescentado Em",
@@ -113,6 +115,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Após o timer terminar, da próxima vez que o item for reproduzido a sua posição será retrocedida automaticamente.",
"LabelAutoSleepTimerHelp": "Ao reproduzir uma mídia entre as horas especificadas como inicío e fim, um timer será iniciado automaticamente.",
"LabelBooks": "Livros",
"LabelByAuthor": "por {0}",
"LabelChapterTrack": "Trilha do Capítulo",
"LabelChapters": "Capítulos",
"LabelClosePlayer": "Fechar Reprodutor",
@@ -155,6 +158,9 @@
"LabelFinished": "Concluído",
"LabelFolder": "Pasta",
"LabelFontBoldness": "Intensidade do negrito",
"LabelFontFamily": "Família de fontes",
"LabelFontFamilySans": "Sans",
"LabelFontFamilySerif": "Serif",
"LabelFontScale": "Escala de fonte",
"LabelGenre": "Gênero",
"LabelGenres": "Gêneros",
@@ -174,6 +180,9 @@
"LabelLayout": "Layout",
"LabelLayoutAuto": "Automático",
"LabelLayoutSinglePage": "Uma página",
"LabelLibrarySortByProgress": "Progresso: Ultima Atualização",
"LabelLibrarySortByProgressFinished": "Progresso: Terminado",
"LabelLibrarySortByProgressStarted": "Progresso: Iniciado",
"LabelLight": "Leve",
"LabelLineSpacing": "Espaçamento entre linhas",
"LabelListenAgain": "Escutar novamente",
@@ -233,6 +242,7 @@
"LabelScaleElapsedTimeBySpeed": "Proporcionalizar Tempo Decorrido com a Velocidade",
"LabelSeason": "Temporada",
"LabelSelectADevice": "Selecione um dispositivo",
"LabelSelectMediaType": "Escolha o tipo da media",
"LabelSequenceAscending": "Sequência Ascendente",
"LabelSequenceDescending": "Sequence Descendente",
"LabelSeries": "Série",
+4
View File
@@ -113,6 +113,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Когда таймер сна закончится, то позиция воспроизведения будет отмотана назад.",
"LabelAutoSleepTimerHelp": "Если медиа воспроизводится между указанными началом и окончанием, таймер сна будет включаться автоматически.",
"LabelBooks": "Книги",
"LabelByAuthor": "от {0}",
"LabelChapterTrack": "Трек главы",
"LabelChapters": "Главы",
"LabelClosePlayer": "Закрыть проигрыватель",
@@ -155,6 +156,9 @@
"LabelFinished": "Закончен",
"LabelFolder": "Папка",
"LabelFontBoldness": "Жирность шрифта",
"LabelFontFamily": "Семейство шрифта",
"LabelFontFamilySans": "Sans",
"LabelFontFamilySerif": "Serif",
"LabelFontScale": "Масштаб шрифта",
"LabelGenre": "Жанр",
"LabelGenres": "Жанры",
+5 -1
View File
@@ -100,7 +100,7 @@
"LabelAlways": "Vždy",
"LabelAndroidAutoBrowseLimitForGrouping": "Limit abecedného posunu",
"LabelAndroidAutoBrowseLimitForGroupingHelp": "Nezobrazí možnosť abecedného posunu, ak je počet zobrazených položiek menší ako limit",
"LabelAndroidAutoBrowseSeriesSequenceOrder": "Poradie kníh série",
"LabelAndroidAutoBrowseSeriesSequenceOrder": "Poradie kníh v sérii",
"LabelAskConfirmation": "Požiadať o potvrdenie",
"LabelAuthor": "Autor",
"LabelAuthorFirstLast": "Autor (Meno Priezvisko)",
@@ -113,6 +113,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Keď Auto časovač spánku skončí, pred nasledujúcim prehratím položky sa prehrávanie automaticky posunie.",
"LabelAutoSleepTimerHelp": "keď sa prehrávanie začne vo vymedzenom časovom intervale, časovač spánku sa automaticky spustí tiež.",
"LabelBooks": "Knihy",
"LabelByAuthor": "od",
"LabelChapterTrack": "Zvuková stopa kapitoly",
"LabelChapters": "Kapitoly",
"LabelClosePlayer": "Zavrieť prehrávač",
@@ -155,6 +156,9 @@
"LabelFinished": "Ukončené",
"LabelFolder": "Priečinok",
"LabelFontBoldness": "Hrúbka písma",
"LabelFontFamily": "Písmo",
"LabelFontFamilySans": "Sans",
"LabelFontFamilySerif": "Serif",
"LabelFontScale": "Veľkosť písma",
"LabelGenre": "Žáner",
"LabelGenres": "Žánre",
+3
View File
@@ -155,6 +155,9 @@
"LabelFinished": "Zaključeno",
"LabelFolder": "Mapa",
"LabelFontBoldness": "Krepkost pisave",
"LabelFontFamily": "Družina pisav",
"LabelFontFamilySans": "Sans",
"LabelFontFamilySerif": "Serif",
"LabelFontScale": "Merilo pisave",
"LabelGenre": "Žanr",
"LabelGenres": "Žanri",
+21 -4
View File
@@ -63,6 +63,7 @@
"HeaderChapters": "Kapitel",
"HeaderCollection": "Samling",
"HeaderCollectionItems": "Böcker i samlingen",
"HeaderConfirm": "Bekräfta",
"HeaderConnectionStatus": "Anslutnings Status",
"HeaderDataSettings": "Data Inställningar",
"HeaderDetails": "Detaljer",
@@ -91,6 +92,7 @@
"HeaderStatsRecentSessions": "Senaste tillfällena",
"HeaderTableOfContents": "Innehållsförteckning",
"HeaderUserInterfaceSettings": "Användargränssnittsinställningar",
"HeaderWelcome": "Välkommen, <strong>{0}</strong>",
"HeaderYourStats": "Din statistik",
"LabelAddToPlaylist": "Lägg till i en spellista",
"LabelAddedAt": "Tillagd vid",
@@ -113,6 +115,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "När den automatiska insomningstimern är klar spolas din position automatiskt tillbaka.",
"LabelAutoSleepTimerHelp": "Vid uppspelning av media mellan de angivna start- och sluttiderna startar en insomningstimer automatiskt.",
"LabelBooks": "Böcker",
"LabelByAuthor": "av {0}",
"LabelChapterTrack": "Kapitel Spår",
"LabelChapters": "Kapitel",
"LabelClosePlayer": "Stäng spelaren",
@@ -155,10 +158,13 @@
"LabelFinished": "Avslutad",
"LabelFolder": "Mapp",
"LabelFontBoldness": "Fetstil",
"LabelFontScale": "Teckensnittsskala",
"LabelFontFamily": "Typsnittsfamilj",
"LabelFontFamilySans": "Utan klackar",
"LabelFontFamilySerif": "Med klackar",
"LabelFontScale": "Storlek på typsnitt",
"LabelGenre": "Genre",
"LabelGenres": "Genrer",
"LabelHapticFeedback": "Haptisk feedback",
"LabelHapticFeedback": "Haptisk återkoppling",
"LabelHasEbook": "Har e-bok",
"LabelHasSupplementaryEbook": "Har kompletterande e-bok",
"LabelHeavy": "Tung",
@@ -174,6 +180,9 @@
"LabelLayout": "Layout",
"LabelLayoutAuto": "Automatisk",
"LabelLayoutSinglePage": "En sida",
"LabelLibrarySortByProgress": "Status: Senast uppdaterad",
"LabelLibrarySortByProgressFinished": "Status: Avslutad",
"LabelLibrarySortByProgressStarted": "Status: Startad",
"LabelLight": "Lätt",
"LabelLineSpacing": "Radavstånd",
"LabelListenAgain": "Lyssna igen",
@@ -233,8 +242,9 @@
"LabelScaleElapsedTimeBySpeed": "Skaländra uppspelningsposition efter uppspelningshastighet.",
"LabelSeason": "Säsong",
"LabelSelectADevice": "Välj en enhet",
"LabelSelectMediaType": "Ange mediatyp",
"LabelSequenceAscending": "Stigande",
"LabelSequenceDescending": "Sekvens Fallande",
"LabelSequenceDescending": "Fallande",
"LabelSeries": "Serie",
"LabelServerAddress": "Server-adress",
"LabelSetEbookAsPrimary": "Ange som primär",
@@ -285,12 +295,17 @@
"MessageAudiobookshelfServerNotConnected": "Audiobookshelf-server är ej ansluten",
"MessageAudiobookshelfServerRequired": "<strong>Viktigt!</strong> Den här appen måste användas tillsammans med en Audiobookshelf-server som hostas av dig eller dina bekanta. Appen tillhandahåller själv inget innehåll.",
"MessageBookshelfEmpty": "Bokhyllan är tom",
"MessageConfirmAppExit": "Vill du avsluta appen?",
"MessageConfirmDeleteEpisodeDownloadQueue": "Är du säker på att du vill rensa kön för nedladdning av avsnitt?",
"MessageConfirmDeleteLocalEpisode": "Ta bort lokalt avsnitt \"{0}\" från enheten? Filen på servern påverkas inte.",
"MessageConfirmDeleteLocalFiles": "Ta bort lokala filer för detta objekt från din enhet? Filerna på servern och din uppspelningsposition raderas inte.",
"MessageConfirmDeleteServerConfig": "Vill du radera serverkonfigurationen?",
"MessageConfirmDeleteServerEpisode": "Är du säkert på att du vill radera avsnitt \"{0}\" från servern?\nOBSERVERA: Ljudfilen kommer då att raderas.",
"MessageConfirmDisableAutoTimer": "Är du säker att du vill stänga av auto timer för resten av idag? Timern kommer att sättas på igen vid slutet av den här auto-sömn timer perioden, eller om du startar om appen.",
"MessageConfirmDiscardProgress": "Är du säker på att du vill återställa din uppspelningsposition?",
"MessageConfirmDownloadUsingCellular": "Du kommer påbörja en nedladdning över mobildata. Detta kan leda till avgifter från din operatör. Vill du fortsätta?",
"MessageConfirmMarkAsFinished": "Är du säker på att du vill färdigmarkera det här objektet.",
"MessageConfirmPlaybackTime": "Vill du starta uppspelning av \"{0}\" på {1}?",
"MessageConfirmRemoveBookmark": "Är du säker på att du vill ta bort bokmärket?",
"MessageConfirmStreamingUsingCellular": "Du kommer påbörja en strömmning över mobildata. Detta kan leda till avgifter från din operatör. Vill du fortsätta?",
"MessageDiscardProgress": "Avfärda uppspelningsposition",
@@ -355,5 +370,7 @@
"ToastPodcastCreateSuccess": "Podcasten skapades framgångsrikt",
"ToastRSSFeedCloseFailed": "Misslyckades med att stänga RSS-flödet",
"ToastRSSFeedCloseSuccess": "RSS-flödet stängt",
"ToastStreamingNotAllowedOnCellular": "Strömning tillåts inte över mobildata."
"ToastStreamingNotAllowedOnCellular": "Strömning tillåts inte över mobildata.",
"UnitMinutesShort": "{0}m",
"UnitSecondsShort": "{0}s"
}
+2
View File
@@ -113,6 +113,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Otomatik uyku zamanlayıcısı bittiğinde, öğeyi tekrar oynatmak konumunuzu otomatik olarak geri saracaktır.",
"LabelAutoSleepTimerHelp": "Belirtilen başlangıç ve bitiş zamanları arasında medya oynatıldığında bir uyku zamanlayıcısı otomatik olarak başlar.",
"LabelBooks": "Kitaplar",
"LabelByAuthor": "{0} tarafından",
"LabelChapterTrack": "Bölüm Parçası",
"LabelChapters": "Bölümler",
"LabelClosePlayer": "Oynatıcıyı kapat",
@@ -155,6 +156,7 @@
"LabelFinished": "Bitirildi",
"LabelFolder": "Klasör",
"LabelFontBoldness": "Yazı Tipi Kalınlığı",
"LabelFontFamily": "Yazı tipi ailesi",
"LabelFontScale": "Yazı Tipi Ölçeği",
"LabelGenre": "Tür",
"LabelGenres": "Türler",
+4
View File
@@ -113,6 +113,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "Коли сплине автотаймер вимкнення, відтворення знову автоматично перемотає доріжку.",
"LabelAutoSleepTimerHelp": "Таймер вимкнення автоматично ввімкнеться при відтворенні медіа між вказаним початковим та кінцевим часом.",
"LabelBooks": "Книг",
"LabelByAuthor": "від {0}",
"LabelChapterTrack": "Прогрес глави",
"LabelChapters": "Глави",
"LabelClosePlayer": "Закрити програвач",
@@ -155,6 +156,9 @@
"LabelFinished": "Завершено",
"LabelFolder": "Тека",
"LabelFontBoldness": "Товщина шрифту",
"LabelFontFamily": "Сімейство шрифтів",
"LabelFontFamilySans": "Санс",
"LabelFontFamilySerif": "Засічка",
"LabelFontScale": "Розмір шрифту",
"LabelGenre": "Жанр",
"LabelGenres": "Жанри",
+18 -1
View File
@@ -63,6 +63,7 @@
"HeaderChapters": "章节",
"HeaderCollection": "收藏",
"HeaderCollectionItems": "收藏项目",
"HeaderConfirm": "确认",
"HeaderConnectionStatus": "连接状态",
"HeaderDataSettings": "数据设置",
"HeaderDetails": "详情",
@@ -91,6 +92,7 @@
"HeaderStatsRecentSessions": "历史会话",
"HeaderTableOfContents": "目录",
"HeaderUserInterfaceSettings": "用户界面设置",
"HeaderWelcome": "欢迎, <strong>{0}</strong>",
"HeaderYourStats": "你的统计数据",
"LabelAddToPlaylist": "添加到播放列表",
"LabelAddedAt": "添加于",
@@ -113,6 +115,7 @@
"LabelAutoSleepTimerAutoRewindHelp": "当自动睡眠计时器结束时, 再次播放该项目将自动倒带你之前的位置.",
"LabelAutoSleepTimerHelp": "当在指定的时间范围内播放媒体时, 睡眠计时器将自动启动.",
"LabelBooks": "图书",
"LabelByAuthor": "作者: {0}",
"LabelChapterTrack": "章节音轨",
"LabelChapters": "章节",
"LabelClosePlayer": "关闭播放器",
@@ -155,6 +158,9 @@
"LabelFinished": "已听完",
"LabelFolder": "文件夹",
"LabelFontBoldness": "字体粗细",
"LabelFontFamily": "字体",
"LabelFontFamilySans": "无衬线字体",
"LabelFontFamilySerif": "衬线字体",
"LabelFontScale": "字体比例",
"LabelGenre": "流派",
"LabelGenres": "流派",
@@ -174,6 +180,9 @@
"LabelLayout": "布局",
"LabelLayoutAuto": "自动",
"LabelLayoutSinglePage": "单页",
"LabelLibrarySortByProgress": "进度: 上次更新",
"LabelLibrarySortByProgressFinished": "进度: 已完成",
"LabelLibrarySortByProgressStarted": "进度: 已开始",
"LabelLight": "轻",
"LabelLineSpacing": "行间距",
"LabelListenAgain": "再次收听",
@@ -233,6 +242,7 @@
"LabelScaleElapsedTimeBySpeed": "按速度缩放播放时间",
"LabelSeason": "季",
"LabelSelectADevice": "选择设备",
"LabelSelectMediaType": "选择媒体类型",
"LabelSequenceAscending": "序列升序",
"LabelSequenceDescending": "序列降序",
"LabelSeries": "系列",
@@ -285,12 +295,17 @@
"MessageAudiobookshelfServerNotConnected": "Audiobookshelf 服务器未连接",
"MessageAudiobookshelfServerRequired": "<strong>重要提示!</strong>此应用旨在与你或你认识的人托管的 Audiobookshelf 服务器配合使用. 此应用不提供任何内容.",
"MessageBookshelfEmpty": "书架是空的",
"MessageConfirmAppExit": "确定要退出应用吗?",
"MessageConfirmDeleteEpisodeDownloadQueue": "确定要清空剧集下载队列吗?",
"MessageConfirmDeleteLocalEpisode": "要从设备中删除本地剧集 \"{0}\" 吗? 服务器上的文件将不受影响.",
"MessageConfirmDeleteLocalFiles": "要从设备中删除此项目的本地文件吗? 服务器上的文件和你的进度将不受影响.",
"MessageConfirmDeleteServerConfig": "确定要移除此服务器配置吗?",
"MessageConfirmDeleteServerEpisode": "确定要从服务器删除剧集 \"{0}\" 吗?\n警告: 这将会删除音频文件.",
"MessageConfirmDisableAutoTimer": "你确定要在今天剩余时间内禁用自动定时器吗? 定时器将在自动睡眠定时器周期结束时或你重新启动应用时重新启用.",
"MessageConfirmDiscardProgress": "你确定要重置进度吗?",
"MessageConfirmDownloadUsingCellular": "你即将使用移动数据进行下载. 这可能包括运营商数据费用. 是否要继续?",
"MessageConfirmMarkAsFinished": "你确定要要将此项目标记为已完成吗?",
"MessageConfirmPlaybackTime": "确定从 {1} 开始播放 \"{0}\" 吗?",
"MessageConfirmRemoveBookmark": "你确定要删除书签吗?",
"MessageConfirmStreamingUsingCellular": "你将使用移动数据进行流媒体播放. 这可能包括运营商数据费用. 是否要继续?",
"MessageDiscardProgress": "放弃进度",
@@ -355,5 +370,7 @@
"ToastPodcastCreateSuccess": "已成功创建播客",
"ToastRSSFeedCloseFailed": "关闭 RSS 源失败",
"ToastRSSFeedCloseSuccess": "RSS 源已关闭",
"ToastStreamingNotAllowedOnCellular": "不允许通过移动数据进行流媒体播放"
"ToastStreamingNotAllowedOnCellular": "不允许通过移动数据进行流媒体播放",
"UnitMinutesShort": "{0}分",
"UnitSecondsShort": "{0}秒"
}