Compare commits

...

331 Commits

Author SHA1 Message Date
Hosted Weblate 324936e0c8 Translated using Weblate
Currently translated at 100.0% (1208 of 1208 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Translated using Weblate

Currently translated at 100.0% (1208 of 1208 strings) (Catalan)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ca/

Co-authored-by: Ondo <SparkyOndo@proton.me>
Co-authored-by: York <goog10216922@gmail.com>
2026-05-05 05:09:50 +00:00
Hosted Weblate 868ec15b16 Added translation using Weblate (Thai)
Translated using Weblate

Currently translated at 100.0% (1208 of 1208 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 100.0% (1208 of 1208 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Translated using Weblate

Currently translated at 100.0% (1208 of 1208 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Co-authored-by: Anucha Hlownonkor <anucha.initdz@gmail.com>
Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: skajmer <skajmer@protonmail.com>
2026-05-03 12:06:39 +02:00
Hosted Weblate 775c4e68fa Translated using Weblate
Currently translated at 81.3% (981 of 1206 strings) (Russian)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ru/

Translated using Weblate

Currently translated at 100.0% (1206 of 1206 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Translated using Weblate

Currently translated at 85.6% (1033 of 1206 strings) (Basque)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/eu/

Co-authored-by: Aitor Astorga <a.astorga.sdv@protonmail.com>
Co-authored-by: York <goog10216922@gmail.com>
Co-authored-by: spoon <monkeyfart907@gmail.com>
2026-05-02 04:34:18 +00:00
jeffvli 34e0c4bd4a prevent first lyric line highlight before timestamp (#1965) 2026-05-01 21:33:40 -07:00
jeffvli 323130a877 add toggle for app-suspension for powersave block (#1992) 2026-05-01 21:24:45 -07:00
jeffvli 3b2aab74ac enforce web player seek by seconds when less than 1 (#1993) 2026-05-01 21:12:20 -07:00
Hosted Weblate bc7ef0624b Translated using Weblate
Currently translated at 100.0% (1205 of 1205 strings) (Dutch)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/nl/

Translated using Weblate

Currently translated at 100.0% (1205 of 1205 strings) (Dutch)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/nl/

Co-authored-by: Joren Vansteenkiste <vansteenkiste.joren@telenet.be>
Co-authored-by: bokse <weblate@bokse.nl>
2026-05-01 21:32:24 +02:00
Pedro Daniel Reis 304ce8b881 [UI] Made sidebar image just use flex (#1975)
* made sidebar image just use flex

* force aspect ratio to be square

* prevent image container from expanding

---------

Co-authored-by: jeffvli <jeffvictorli@gmail.com>
2026-05-01 12:32:18 -07:00
Jonne Saloranta 01011a49a2 Replace success toast with info when no songs are added (#1994) 2026-05-01 11:44:15 -07:00
York d24ca04878 fix: detect Homebrew mpv on macOS (#1989) 2026-05-01 11:43:07 -07:00
Hosted Weblate 640d38e5a9 Translated using Weblate
Currently translated at 100.0% (1205 of 1205 strings) (Catalan)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ca/

Co-authored-by: Ondo <SparkyOndo@proton.me>
2026-04-30 15:09:57 +00:00
jeffvli ac0c074d4b fix undefined / null parameter string for Subsonic (#1978) 2026-04-28 21:17:44 -07:00
jeffvli 6be5818493 migrate to mantine v9 2026-04-28 21:02:27 -07:00
Hosted Weblate 03edd5a639 Translated using Weblate
Currently translated at 100.0% (1205 of 1205 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 100.0% (1205 of 1205 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Translated using Weblate

Currently translated at 100.0% (1205 of 1205 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Translated using Weblate

Currently translated at 99.8% (1201 of 1203 strings) (French)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: KosmoMoustache <kosmomoustache@users.noreply.hosted.weblate.org>
Co-authored-by: York <goog10216922@gmail.com>
2026-04-29 04:45:44 +02:00
jeffvli f5eb3f1488 wrap useHotkeys to disable on command palette open (#1925) 2026-04-28 19:31:41 -07:00
jeffvli 8eab9edb15 fix performance issue related to blurred library header 2026-04-28 19:05:43 -07:00
Mitch Ray fcc69980e4 Stretch the wavesurfer waveform to the full height (#1962)
* Stretch the wavesurfer waveform to the full height

* Add waveform stretch setting
2026-04-27 20:28:03 -07:00
Hosted Weblate 053b78a3fd Translated using Weblate
Currently translated at 100.0% (1203 of 1203 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 100.0% (1203 of 1203 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Translated using Weblate

Currently translated at 100.0% (1203 of 1203 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Translated using Weblate

Currently translated at 100.0% (1203 of 1203 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: linger <linger0517@gmail.com>
Co-authored-by: skajmer <skajmer@protonmail.com>
2026-04-22 11:09:49 +02:00
mathew4 42ded966e4 fix: proper selection of next song when using shuffle and repeat-one (#1932) 2026-04-21 00:10:21 -07:00
Kendall Garner ea9119431c use urlsearchparams instead of qs (#1970) 2026-04-21 00:09:23 -07:00
vimae add0345f10 feat(lyrics): non-active lyric settings (#1954)
* feat: non-active lyric settings
2026-04-21 00:09:03 -07:00
Hosted Weblate e5a8324a79 Translated using Weblate
Currently translated at 99.3% (1193 of 1201 strings) (Chinese (Simplified Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hans/

Co-authored-by: yidaduizuoye <yidaduizuoye@outlook.com>
2026-04-19 06:09:51 +02:00
jeffvli cc4e933c07 fix missing path replacement transformations 2026-04-16 00:29:13 -07:00
Hosted Weblate 382d279dad Translated using Weblate
Currently translated at 100.0% (1201 of 1201 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 100.0% (1201 of 1201 strings) (French)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/

Translated using Weblate

Currently translated at 100.0% (1201 of 1201 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Translated using Weblate

Currently translated at 100.0% (1201 of 1201 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Translated using Weblate

Currently translated at 100.0% (1201 of 1201 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Translated using Weblate

Currently translated at 79.9% (959 of 1200 strings) (Russian)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ru/

Co-authored-by: Dylan MONTIGAUD <dylanmontigaud17@gmail.com>
Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nick <n.grakhov08@gmail.com>
Co-authored-by: York <goog10216922@gmail.com>
Co-authored-by: skajmer <skajmer@protonmail.com>
2026-04-15 06:10:05 +02:00
York b99899f128 fix MPV visualizer on macOS and handle exclusive mode UX (#1930) 2026-04-13 20:47:03 -07:00
korpseluv f5839bf39c normalize album release types and improve grouping logic (#1892) 2026-04-13 20:40:11 -07:00
Damien Erambert 914ed5b8f3 macOS 26-friendly icon (#1941) 2026-04-13 20:32:21 -07:00
Ross ca0a1569f8 Add everfrost dark and light themes (#1934)
Co-authored-by: Ross <ro@noirlab.edu>
2026-04-13 20:22:37 -07:00
Hosted Weblate 9f10fe398a Translated using Weblate
Currently translated at 58.1% (698 of 1200 strings) (Portuguese (Brazil))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pt_BR/

Translated using Weblate

Currently translated at 38.8% (466 of 1200 strings) (Ukrainian)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/uk/

Co-authored-by: Yuri Shumyatsky <shumy260404@gmail.com>
Co-authored-by: albatrays <weblate.duct925@passmail.net>
2026-04-12 12:09:54 +00:00
Kendall Garner 8869278898 make theme selector serachable 2026-04-10 20:03:50 -07:00
Jeff 16c9e6cc1b Fix various build issues (#1942)
* remove dynamic import for platform features

* increase node memory limit on macOS build

* fix invalid dynamic imports in renderer

* remove discord-rpc import in renderer
2026-04-10 01:54:11 -07:00
Kendall Garner 2a6e9b6ad3 add extendInfo to alpha/beta builders 2026-04-08 07:28:34 -07:00
Kendall Garner 167b42df2b Merge pull request #1926 from noctuum/fix/wayland-screen-share-dialog
fix(linux): remove unnecessary screen capture from audio loopback handler
2026-04-08 02:11:36 +00:00
jeffvli e6a2bc3acf disable useTransition in router again 2026-04-07 18:21:32 -07:00
jeffvli ca3c7015c6 add fallback to direct streamURL if getTranscodeDecision fails 2026-04-07 18:14:47 -07:00
jeffvli c7c15d917a isolate item card control renders 2026-04-07 18:14:47 -07:00
noctuum 6adb29bc38 fix(linux): remove unnecessary desktopCapturer call from display media handler
The setDisplayMediaRequestHandler was calling desktopCapturer.getSources()
to provide a video source that the renderer never uses (it requests
video: false and only consumes audio tracks). On Wayland, this created a
new xdg-desktop-portal ScreenCast session on every launch, showing an
unavoidable screen share dialog because Electron does not persist
PipeWire restore tokens across desktopCapturer sessions.

Simplified the handler to return only { audio: 'loopback' }, which
captures system audio via PipeWire/PulseAudio monitor source without
any portal interaction.
2026-04-08 04:56:05 +07:00
Hosted Weblate 2c3cd7af24 Translated using Weblate
Currently translated at 94.6% (1136 of 1200 strings) (German)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/de/

Translated using Weblate

Currently translated at 100.0% (1200 of 1200 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Translated using Weblate

Currently translated at 100.0% (1200 of 1200 strings) (Japanese)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ja/

Translated using Weblate

Currently translated at 100.0% (1200 of 1200 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Translated using Weblate

Currently translated at 100.0% (1200 of 1200 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 100.0% (1200 of 1200 strings) (French)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/

Translated using Weblate

Currently translated at 100.0% (1200 of 1200 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: KosmoMoustache <kosmomoustache@users.noreply.hosted.weblate.org>
Co-authored-by: York <goog10216922@gmail.com>
Co-authored-by: Zarakkas <kaz@users.noreply.hosted.weblate.org>
Co-authored-by: karigane <169052233+karigane-cha@users.noreply.github.com>
Co-authored-by: lorduskordus <lorduskordus@gmail.com>
Co-authored-by: skajmer <skajmer@protonmail.com>
2026-04-07 08:10:05 +02:00
jeffvli 3c442a2d40 update to v1.11.0 2026-04-06 17:10:18 -07:00
Andrzej Voss d67c185c93 feat: Make "Clear" button "Refresh" when there are no lyrics found. (#1920)
Ref: effvli/feishin#1919 - tl;dr: Button actually reloads/refreshes
lyrics info from the server too, it makes it, well, clearer what it does
in that case - allows to reread lyrics from server without clearing whole cache.
2026-04-06 16:59:01 -07:00
jeffvli ff96a5f121 lint 2026-04-06 12:06:55 -07:00
jeffvli 6fc7b6b271 support image drop for upload 2026-04-06 11:41:33 -07:00
jeffvli 918f453066 support navidrome artist image upload/delete 2026-04-06 11:41:26 -07:00
jeffvli 4a986069f8 set flac as default transcoding profile 2026-04-06 10:58:37 -07:00
jeffvli 11d26af893 remove arm/v7 from container build 2026-04-06 09:47:28 -07:00
jeffvli ad13fea033 update to v1.10.0 2026-04-05 22:41:06 -07:00
Hosted Weblate 8a75ec2558 Translated using Weblate
Currently translated at 100.0% (1196 of 1196 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Co-authored-by: York <goog10216922@gmail.com>
2026-04-06 05:27:10 +00:00
Auzlex 895cbb4d16 fix(media-session): prevent handlers from being destroyed during playback (#1898)
Handlers were being registered and destroyed on state change/re-render,
causing media controls to vanish during rapid use or quick track skipping.
Persist handlers and add debounce for rapid track skipping.

Tested on Windows, Linux, and Android.
2026-04-05 22:27:04 -07:00
jeffvli 3f300c40cc add in-app prompt for system audio connection 2026-04-05 22:19:09 -07:00
jeffvli c8e8f58cce re-add useTransition to router 2026-04-05 21:54:07 -07:00
jeffvli 56cd50e0ed add react compiler 2026-04-05 18:38:06 -07:00
jeffvli 1b2a6dfc1f optimize item list controls 2026-04-05 18:21:28 -07:00
jeffvli 356f5487b0 reorder playlist context menu items 2026-04-05 14:10:07 -07:00
jeffvli 37501f2983 remove automatic autosize, use dummy fill column instead 2026-04-05 09:06:03 -07:00
jeffvli d61587b16f add automatic autosize columns when auto-fit is disabled 2026-04-05 08:12:10 -07:00
Kendall Garner 06b7b53dc9 feat(macos): add NSLocalNetworkUsageDescription 2026-04-05 08:03:28 -07:00
Kendall Garner 6c2cd1c274 fix(mpris): serve minimal metadata when playing radio
1. MPRIS (or `mpris-service`) is very fragile. If an invalid `mpris:trackid` (something with `-` or spaces) is passed in, it breaks. Use a minimal track id instead
2. Only populate album/artist/title
2026-04-05 08:01:28 -07:00
jeffvli ef129e4638 remove video from displayMedia request 2026-04-05 07:58:01 -07:00
jeffvli a01b4e664d add plex fork notice 2026-04-05 07:57:41 -07:00
jeffvli 0b45ab7f36 support real-time table column resizing 2026-04-05 07:48:54 -07:00
jeffvli 031d365262 decrease padding on list header 2026-04-05 03:49:31 -07:00
jeffvli 4fd56281d5 increase font size of smart playlist JSON editor 2026-04-05 02:42:05 -07:00
jeffvli 08ce8a4028 add nd v0.61.1 smart playlist fields 2026-04-05 02:38:40 -07:00
jeffvli e06877af76 make visualizer idle kill consistent for both 2026-04-05 02:35:32 -07:00
jeffvli 84395ce5b4 pass muted text props to JoinedArtists in left controls 2026-04-05 00:59:53 -07:00
jeffvli 94886a2d5a add system audio loopback for webaudio 2026-04-05 00:48:38 -07:00
jeffvli 25bb7f7069 fix scroll shadow z-indexing issue with table scrollbars 2026-04-04 23:48:48 -07:00
jeffvli 573fe5ee35 use external store for scroll shadow 2026-04-04 23:32:32 -07:00
jeffvli a868d4d539 combine wav codec check 2026-04-04 23:11:55 -07:00
jeffvli 564ee721c4 revert default transcoding profile to opus, add safari check for mp3 2026-04-04 23:08:53 -07:00
jeffvli a8d990db23 fix subsonic transcoding stream url to return raw string instead of fetch 2026-04-04 23:03:46 -07:00
jeffvli e21515f7fb add additional codec probes for transcoding profile, use mp3 instead of opus for default transcode 2026-04-04 23:03:29 -07:00
jeffvli 3e5a8ac78d re-add default suspense to album/artist routes 2026-04-04 22:25:21 -07:00
jeffvli 6c73d06dcf remove useTransition from router 2026-04-04 22:14:07 -07:00
jeffvli a8954bfa2a remove imageUrl in favor or imageId for artistInfo 2026-04-04 21:52:44 -07:00
jeffvli 19a1617a8d remove suspense spinner from router 2026-04-04 18:26:25 -07:00
jeffvli 1abae986f8 move server selector into app menu 2026-04-04 18:25:04 -07:00
jeffvli 43fa574dab add responsive breakpoint for queue control items 2026-04-04 17:37:47 -07:00
jeffvli 99530c670e redesign queue controls bar 2026-04-04 17:37:05 -07:00
jeffvli 3a0dfe59ce improve visibily of keyboard-focused search items 2026-04-04 17:37:05 -07:00
York d60ed0a793 feat: macOS menu enhancement (#1903) 2026-04-04 17:35:30 -07:00
Kendall Garner a32fed3bcf chore: upgrade dependencies (#1906)
* upgrade dependencies

* downgrade fast-average-color
2026-04-04 17:10:57 -07:00
Kendall Garner 132ac92984 chore: use consistent order of track / artist / ablum on full screen page 2026-04-04 14:46:13 -07:00
jeffvli 141a20f042 refactor item table props 2026-04-04 12:34:27 -07:00
jeffvli 1592204515 add fallback sort order for subsonic playlist list 2026-04-04 12:03:41 -07:00
jeffvli b9f5459725 fix layout shift on grid carousel page change 2026-04-03 20:25:12 -07:00
jeffvli d4e9b9b7a6 adjust bg loading on album detail page 2026-04-03 20:11:10 -07:00
jeffvli ec9e4b1339 fix type error due to new param on mediaStop 2026-04-03 19:09:42 -07:00
Hosted Weblate f09109b887 Translated using Weblate
Currently translated at 100.0% (1194 of 1194 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Translated using Weblate

Currently translated at 100.0% (1194 of 1194 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Translated using Weblate

Currently translated at 100.0% (1194 of 1194 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Translated using Weblate

Currently translated at 100.0% (1193 of 1193 strings) (French)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/

Translated using Weblate

Currently translated at 100.0% (1193 of 1193 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: KosmoMoustache <kosmomoustache@users.noreply.hosted.weblate.org>
Co-authored-by: York <goog10216922@gmail.com>
Co-authored-by: skajmer <skajmer@protonmail.com>
2026-04-04 04:05:50 +02:00
jeffvli 1494c8e044 fix mpv seek error on queue end 2026-04-03 19:05:34 -07:00
jeffvli f3a6027e6d fix mpv progress interval still running after queue ends 2026-04-03 18:58:58 -07:00
jeffvli 3c42355c1e attempt to fix mpv playback sync on song insertion (#1855) 2026-04-03 18:54:49 -07:00
jeffvli feda1bb06f remove square image param, default item id for image 2026-04-03 11:24:39 -07:00
jeffvli 72f1d2f9f9 improve date parsing for partial dates (#1683) 2026-04-02 19:39:08 -07:00
jeffvli ad11a9303c add playlist description to expanded header 2026-04-02 18:36:42 -07:00
jeffvli db06e7f601 add native nd radio endpoints, support radio station images 2026-04-02 18:26:26 -07:00
jeffvli fbf82c1ef0 add playlist image upload to edit playlist modal 2026-04-02 17:41:25 -07:00
jeffvli 92cea5dfda add log for direct play profiles 2026-04-02 01:27:14 -07:00
jeffvli 7442f9d3ca support navidrome playlist image upload 2026-04-02 01:23:09 -07:00
jeffvli 68dacea228 use resized images in artist header 2026-04-01 21:57:32 -07:00
jeffvli 51425b5e86 various performance refactors 2026-04-01 21:57:26 -07:00
jeffvli c60610cb42 lint files 2026-03-31 21:12:48 -07:00
jeffvli d3881ee3be support limitPercent for smart playlists 2026-03-31 21:09:13 -07:00
jeffvli de403ea6ac add new nd smart playlist fields
- averagerating

- albumdateloved
- albumlastplayed
- albumdaterated
- albumloved
- albumrating

- artistdateloved
 -artistlastplayed
- artistdaterated
- artistloved
- artistplaycount
2026-03-31 20:55:36 -07:00
jeffvli a30b1ec90b add OS transcoding extension 2026-03-31 20:45:22 -07:00
Hosted Weblate 7982c0e1bd Translated using Weblate
Currently translated at 100.0% (1193 of 1193 strings) (Chinese (Simplified Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hans/

Translated using Weblate

Currently translated at 83.4% (996 of 1193 strings) (Basque)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/eu/

Co-authored-by: Aitor Astorga <a.astorga.sdv@protonmail.com>
Co-authored-by: 無情天 <kofzhanganguo@126.com>
2026-03-31 16:09:57 +02:00
dependabot[bot] baf4e7bc0b Bump fast-xml-parser in the npm_and_yarn group across 1 directory (#1777)
Bumps the npm_and_yarn group with 1 update in the / directory: [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser).


Updates `fast-xml-parser` from 5.3.6 to 5.3.8
- [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases)
- [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.3.6...v5.3.8)

---
updated-dependencies:
- dependency-name: fast-xml-parser
  dependency-version: 5.3.8
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-29 21:43:31 -07:00
Sutaai 74c44558fe fix: window bar disappearing in Glassy Dark (#1878)
* fix: glassy dark content container claiming entire width  (#1713)

* fix: apply container height fix only when using window bar

---------

Co-authored-by: Jeff <42182408+jeffvli@users.noreply.github.com>
2026-03-29 21:43:08 -07:00
Pyx 4033619421 glassy dark theme improvements (#1844)
* glassy dark theme improvements
2026-03-29 21:27:56 -07:00
jeffvli 5d206bbb1f toggle fullscreen visualizer on left controls image (#1857) 2026-03-29 21:05:53 -07:00
Hosted Weblate 3db801f2de Translated using Weblate
Currently translated at 89.1% (1063 of 1193 strings) (German)
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/de/

Translated using Weblate

Currently translated at 100.0% (1193 of 1193 strings) (Czech)
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Translated using Weblate

Currently translated at 100.0% (1193 of 1193 strings) (Japanese)
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ja/

Translated using Weblate

Currently translated at 100.0% (1193 of 1193 strings) (Spanish)
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translated using Weblate

Currently translated at 100.0% (1194 of 1194 strings) (Chinese (Traditional Han script))
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: PhillyMay <mein.alias@outlook.com>
Co-authored-by: karigane <169052233+karigane-cha@users.noreply.github.com>
Co-authored-by: linger <linger0517@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/
Translation: feishin/Translation
2026-03-30 05:34:25 +02:00
ebee04 0d3cf912d3 fix click on feishin icon in macos menu bar (tray) causing switch to feishin window (#1881) 2026-03-29 20:34:18 -07:00
jeffvli d81f30a8b5 disable lyrics on radio playback (#1885) 2026-03-29 20:33:31 -07:00
Kendall Garner a5c3b454f4 add flathub to readme 2026-03-28 21:33:51 -07:00
Kendall Garner 68e6e3cf65 feat(playlist): support updating playlist track order (#1875)
* feat(playlist): support updating playlist track order

* force track mode when editing

* use common confirmation for save

* remove en editPLaylist key
2026-03-27 21:36:08 -07:00
Romain VIGNERES 86e6b88555 feat(albums): show grouping tags on album detail page (#1872)
* feat(albums): show grouping tags on album detail page

---------

Co-authored-by: Romain VIGNERES <romain.vigneres@texa.fr>
2026-03-27 18:51:44 -07:00
jeffvli 5cdc45836f rework queue persistence (#1862) 2026-03-27 18:48:38 -07:00
Kendall Garner d438c802a4 fix(normalize): do not duplicate remixer when included in credit 2026-03-27 18:46:12 -07:00
Hosted Weblate a838bdebb7 Translated using Weblate
Currently translated at 79.5% (949 of 1193 strings) (Basque)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/eu/

Co-authored-by: Aitor Astorga <a.astorga.sdv@protonmail.com>
2026-03-27 20:09:51 +01:00
Hosted Weblate 8ff2f4dfb4 Translated using Weblate
Currently translated at 100.0% (1193 of 1193 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Translated using Weblate

Currently translated at 100.0% (1193 of 1193 strings) (Japanese)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ja/

Translated using Weblate

Currently translated at 100.0% (1193 of 1193 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 100.0% (1193 of 1193 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: York <goog10216922@gmail.com>
Co-authored-by: karigane <169052233+karigane-cha@users.noreply.github.com>
2026-03-26 08:09:54 +01:00
jeffvli ede47fbf8f fix missing artist name in lyrics search query for lrclib (#1871) 2026-03-25 17:49:50 -07:00
jeffvli 9eb64079f7 handle disabled features in a single flag (#1271) 2026-03-25 17:41:08 -07:00
Hosted Weblate 3b955bb319 Translated using Weblate
Currently translated at 100.0% (1191 of 1191 strings) (Chinese (Simplified Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hans/

Translated using Weblate

Currently translated at 100.0% (1191 of 1191 strings) (Dutch)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/nl/

Co-authored-by: bokse <weblate@bokse.nl>
Co-authored-by: 無情天 <kofzhanganguo@126.com>
2026-03-25 07:09:59 +01:00
Darius 816adfa6c7 Waveform playerbar improvements (#1781)
* Defer waveform loading & show default seek bar as fallback

* Add configurable waveform loading delay

* Add 2s default value for waveform loading delay

* disable transcoding config on waveform url

---------

Co-authored-by: jeffvli <jeffvictorli@gmail.com>
2026-03-24 10:06:25 -07:00
Hosted Weblate f91dcc6af6 Translated using Weblate
Currently translated at 100.0% (1191 of 1191 strings) (French)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/

Co-authored-by: KosmoMoustache <kosmomoustache@users.noreply.hosted.weblate.org>
2026-03-24 06:10:58 +01:00
kast3t 6dc58a3ff8 fix playlist sort by id (#1867) (#1868)
* fix playlist sort by id (#1867)
2026-03-23 18:27:21 -07:00
Kendall Garner 09fa10a4e9 fix(web): do not load umami if env is disabled 2026-03-22 15:08:21 -07:00
Hosted Weblate 6f45e1a814 Translated using Weblate
Currently translated at 100.0% (1191 of 1191 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Co-authored-by: skajmer <skajmer@protonmail.com>
2026-03-21 23:09:51 +01:00
Hosted Weblate 62ba721f26 Translated using Weblate
Currently translated at 100.0% (1191 of 1191 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Translated using Weblate

Currently translated at 100.0% (1191 of 1191 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Translated using Weblate

Currently translated at 100.0% (1191 of 1191 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 100.0% (1191 of 1191 strings) (Japanese)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ja/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: York <goog10216922@gmail.com>
Co-authored-by: karigane <169052233+karigane-cha@users.noreply.github.com>
2026-03-19 13:09:56 +01:00
jeffvli 67231753e4 add list search links to command palette 2026-03-18 02:51:27 -07:00
jeffvli c16eccaecb fix tab index on command palette play buttons 2026-03-18 02:17:31 -07:00
Hosted Weblate 0bdf1dcb75 Translated using Weblate
Currently translated at 100.0% (1190 of 1190 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Co-authored-by: York <goog10216922@gmail.com>
2026-03-18 08:03:12 +00:00
jeffvli 598e9ca5c2 replace lastfm, musicbrainz, and listenbrainz logos 2026-03-18 01:02:57 -07:00
jeffvli 615f9c3515 refactor search into individual sections by itemtype, add infinite loader 2026-03-18 00:59:04 -07:00
jeffvli b7cbdb4d6c persist command palette collapsed sections to app store 2026-03-17 22:34:07 -07:00
jeffvli 3c562c1398 redesign command palette
- add collapsible search groups
- reduce modal padding
- reduce command item padding
- use breadcrumbs for pagination
- move page breadcrumbs to the bottom
2026-03-17 22:28:07 -07:00
jeffvli 3eafa73217 adjust padding / design of layout toggle 2026-03-17 21:40:16 -07:00
Hosted Weblate 74864d9621 Translated using Weblate
Currently translated at 100.0% (1184 of 1184 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Co-authored-by: York <goog10216922@gmail.com>
2026-03-18 04:25:29 +00:00
jeffvli cb5562d32e decrease height of single feature carousel (#1850) 2026-03-17 21:25:18 -07:00
jeffvli e40a175e12 add qobuz and listenbrainz external links 2026-03-17 21:10:31 -07:00
jeffvli f996b111b9 add new external brand icons 2026-03-17 21:10:31 -07:00
Hosted Weblate 0cb5c49924 Translated using Weblate
Currently translated at 100.0% (1180 of 1180 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
2026-03-18 02:06:56 +00:00
jeffvli c636029003 assert appstore state migration return type 2026-03-17 19:06:45 -07:00
jeffvli db88a6bc22 support vertical play queue layout 2026-03-17 19:01:01 -07:00
Hosted Weblate 8ccd97b574 Translated using Weblate
Currently translated at 100.0% (1180 of 1180 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 100.0% (1180 of 1180 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Translated using Weblate

Currently translated at 100.0% (1180 of 1180 strings) (Japanese)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ja/

Translated using Weblate

Currently translated at 45.5% (537 of 1180 strings) (Norwegian Bokmål)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/nb_NO/

Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: Kristoffer <spinal-onto-rebel@duck.com>
Co-authored-by: karigane <169052233+karigane-cha@users.noreply.github.com>
Co-authored-by: linger <linger0517@gmail.com>
2026-03-17 09:10:00 +01:00
jeffvli 3f99acf473 update to v1.9.0 2026-03-16 00:19:48 -07:00
Hosted Weblate 0cd37ce8ec Translated using Weblate
Currently translated at 100.0% (1180 of 1180 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Co-authored-by: linger <linger0517@gmail.com>
2026-03-16 08:19:17 +01:00
jeffvli ee04878580 set mpv audio device to auto if undefined 2026-03-15 20:17:59 -07:00
jeffvli e987049f20 improve sleep timer ui 2026-03-15 18:20:12 -07:00
Hosted Weblate 122552287a Translated using Weblate
Currently translated at 100.0% (1175 of 1175 strings) (Chinese (Simplified Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hans/

Translated using Weblate

Currently translated at 100.0% (1175 of 1175 strings) (Japanese)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ja/

Translated using Weblate

Currently translated at 100.0% (1175 of 1175 strings) (French)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/

Translated using Weblate

Currently translated at 10.1% (119 of 1175 strings) (Arabic)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ar/

Translated using Weblate

Currently translated at 89.0% (1046 of 1175 strings) (German)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/de/

Translated using Weblate

Currently translated at 100.0% (1175 of 1175 strings) (Catalan)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ca/

Co-authored-by: Benjamin <ben@iipython.dev>
Co-authored-by: KosmoMoustache <kosmomoustache@users.noreply.hosted.weblate.org>
Co-authored-by: PhillyMay <mein.alias@outlook.com>
2026-03-16 01:01:08 +00:00
jeffvli d318e6d341 ensure no concurrent playback on non-transition state on web player (#1829) 2026-03-15 18:00:51 -07:00
riccardo d96b282cae feat: "open in spotify" button (#1839)
* feat: open in spotify

* fix: disable native spotify URI by default
2026-03-15 11:49:33 -07:00
jeffvli f2ab01199f disable WaylandFractionScaleV1 (#1271) 2026-03-15 11:42:31 -07:00
Kendall Garner 04b22431f4 fix(settings): proper description for sidebar configuration 2026-03-15 09:16:12 -07:00
Kendall Garner 31fce705ab feat(docker): rootless container) 2026-03-14 18:39:38 -07:00
jeffvli a28fab0ff3 optimize skeleton animation (#1832) 2026-03-14 15:31:13 -07:00
Hosted Weblate 0a1d4788ee Translated using Weblate
Currently translated at 81.1% (954 of 1175 strings) (Russian)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ru/

Translated using Weblate

Currently translated at 100.0% (1175 of 1175 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Translated using Weblate

Currently translated at 44.1% (519 of 1175 strings) (Norwegian Bokmål)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/nb_NO/

Co-authored-by: klodrik <klodrik@zoominn.no>
Co-authored-by: qvap <qvapelsin@gmail.com>
Co-authored-by: skajmer <skajmer@protonmail.com>
2026-03-14 14:09:54 +01:00
jeffvli fafb9d4f56 remove vercel.json due to incorrect edge request configuration 2026-03-13 17:23:03 -07:00
jeffvli 4fdc38caee remove duplicate only-built-dependencies 2026-03-13 17:15:12 -07:00
jeffvli 799cdb44d3 use pnpm v10 on runners 2026-03-13 17:11:24 -07:00
jeffvli 372892199f pin pnpm/action-setup to v4 2026-03-13 17:02:34 -07:00
jeffvli d16184fb25 bump actions dependencies to latest due to deprecated Node v20 2026-03-13 16:59:55 -07:00
jeffvli b8564f6d41 skip wait-for-lint on workflow dispatch 2026-03-13 16:38:32 -07:00
Hosted Weblate d474e60c51 Translated using Weblate
Currently translated at 100.0% (1175 of 1175 strings) (French)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/

Translated using Weblate

Currently translated at 87.5% (1029 of 1175 strings) (Japanese)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ja/

Co-authored-by: Mario Gervais <social.m@riogervais.ca>
Co-authored-by: karigane <169052233+karigane-cha@users.noreply.github.com>
2026-03-13 09:09:54 +00:00
Lyall dfdac28f53 Fix server queue saving/restoring on Navidrome and OpenSubsonic (#1828)
* fix server queue saving

* fix error when attempting to restore empty queue

* queue items optional

* make playQueueByIndex optional

* fix incorrect error message
2026-03-12 13:41:50 +00:00
jeffvli 16b713bc85 add missing suspense boundary around playlist filter sidebar 2026-03-11 22:00:39 -07:00
Kendall Garner 81cd0722b1 fix(mpv): replace mpv queue when restoring queue 2026-03-11 21:42:16 -07:00
jeffvli 1526f9b8d6 re-add session cache for loaded images 2026-03-11 21:20:31 -07:00
jeffvli 5b4da3bc29 use batched fetching for nd song list
- albumIds get culled from query parameters after a certain number, resulting in not all items fetched
2026-03-11 20:46:49 -07:00
jeffvli d78ea440cc set low fetchPriority for carousel images 2026-03-11 19:41:04 -07:00
jeffvli 1595805b83 add additional render optimizations to ArtistAlbums 2026-03-11 19:12:11 -07:00
jeffvli 00fa45f15d isolate render of sticky elements on item table 2026-03-11 19:07:18 -07:00
Luna M ab05be30c0 Fix typo in docker-compose config (#1827) 2026-03-12 01:08:13 +00:00
Hosted Weblate 3d407e5f24 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translated using Weblate

Currently translated at 99.8% (1173 of 1175 strings) (Polish)
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Translated using Weblate

Currently translated at 74.1% (871 of 1175 strings) (Russian)
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ru/

Translated using Weblate

Currently translated at 74.1% (871 of 1175 strings) (Russian)
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ru/

Translated using Weblate

Currently translated at 85.7% (1007 of 1175 strings) (Japanese)
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ja/

Co-authored-by: DanisimoR <danisimogg22@gmail.com>
Co-authored-by: Gentor <gentor92@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: karigane <169052233+karigane-cha@users.noreply.github.com>
Co-authored-by: skajmer <skajmer@protonmail.com>
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/
Translation: feishin/Translation
2026-03-11 21:10:02 +01:00
jeffvli 60776b5f02 fix missing list query invalidation on playlist create/delete 2026-03-11 02:04:51 -07:00
jeffvli 8699b1ffea add sort to artist favorite songs page (#1691) 2026-03-11 01:48:39 -07:00
riccardo 16ac536f93 feat(lyrics): simpmusic lyrics provider (#1820)
* feat(lyrics): simpmusic lyrics provider
2026-03-11 01:04:55 -07:00
jeffvli f51d3d5711 prevent no lyrics message fade out on fullscreen player (#1821) 2026-03-11 01:00:32 -07:00
jeffvli 17a4a14a4e fix isValid condition on REMOTE_URL for server lock (#1822) 2026-03-10 20:02:37 -07:00
jeffvli ecda918b46 update to v1.8.0 2026-03-09 21:53:26 -07:00
Tarulia 93834788b5 use electron-builder's static AppImage runtime (#1816)
electron-builder added compatibility with the AppImage Type2 runtime
(i.e. FUSE-less runtime). However, this is - for now anyway - an opt-in
feature, which this commit enables.
2026-03-09 21:52:48 -07:00
jeffvli 66e7b44d75 add client-side sort to artist favorite songs (#1691) 2026-03-09 20:58:02 -07:00
jeffvli 8825fc1e84 unhide image on error on libraryheader 2026-03-09 20:49:02 -07:00
jeffvli ac0cc19c04 prefer artistInfo artist image 2026-03-09 20:49:02 -07:00
jeffvli de29465b1f enable skeleton animations by default 2026-03-09 20:49:02 -07:00
jeffvli 31a201ca32 rewrite Image component
- remove react-image dependency
- use manual blob load
- abort load when exiting viewport
2026-03-09 20:49:02 -07:00
Hosted Weblate 3644ea2969 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translated using Weblate

Currently translated at 100.0% (1175 of 1175 strings) (Czech)
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Translated using Weblate

Currently translated at 100.0% (1175 of 1175 strings) (Spanish)
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 98.2% (1155 of 1175 strings) (French)
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: KosmoMoustache <kosmomoustache@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/
Translation: feishin/Translation
2026-03-10 03:08:35 +01:00
ashe e46c61e026 Remote URL hardcoding compatibility (#1810)
* Remote URL compatibility
---------

Co-authored-by: jeffvli <jeffvictorli@gmail.com>
2026-03-09 19:08:28 -07:00
Oliver Tzeng 3873218e94 fix translated zh-Hant and zh-Hans (#1807) 2026-03-09 17:08:07 -07:00
Jeff b4a61cbd6e use ad-hoc code signing for macOS build, disable hardenedRuntime (#1815) 2026-03-09 17:05:12 -07:00
jeffvli accc6e53f0 bump electron-builder for pnpm v10.3 ( #1796) 2026-03-09 12:54:32 -07:00
jeffvli adf48decc4 run PR publish on electron-builder config changes 2026-03-09 09:52:42 -07:00
jeffvli 49ff928414 refactor artist header to better handle artist image from info endpoint 2026-03-09 01:54:04 -07:00
Hosted Weblate 71efd4a6d7 Translated using Weblate
Currently translated at 97.8% (1149 of 1174 strings) (Chinese (Simplified Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hans/

Co-authored-by: 無情天 <kofzhanganguo@126.com>
2026-03-09 09:38:55 +01:00
jeffvli 01e4907295 update to v1.7.0 2026-03-09 01:36:19 -07:00
jeffvli 6a47e99680 add manual update notice for macOS, disable autoinstall (#1725) 2026-03-09 01:31:33 -07:00
jeffvli 078d8068e0 fix file path replacement to handle both add/replace (#1749) 2026-03-09 00:55:13 -07:00
jeffvli 58ae76ce2a use album order on artist page for queue add (#1754) 2026-03-09 00:47:55 -07:00
jeffvli bc6cd5b014 refactor grid columns internally into album artist sections to handle null cases 2026-03-08 22:15:54 -07:00
jeffvli 17deac8d65 decouple AlbumArtistInfo from AlbumArtistDetail (#1809) 2026-03-08 22:06:18 -07:00
jeffvli 7dbf8dd9fe add conditional render to queue/lyric state on mobile player (#1797) 2026-03-08 21:06:22 -07:00
Hosted Weblate 27ab9f89c9 Translated using Weblate
Currently translated at 100.0% (1174 of 1174 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 100.0% (1174 of 1174 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Fordas <fordas15@gmail.com>
2026-03-08 13:09:50 +00:00
jeffvli 602808c742 directly replace playlist rules on save and replace 2026-03-07 21:18:55 -08:00
jeffvli c1051956ad add size to album detail header 2026-03-07 20:25:04 -08:00
York 6d2c084355 fix: sleep timer end-of-song mode (#1706) 2026-03-07 20:23:19 -08:00
Hosted Weblate 6e3f0f2253 Translated using Weblate
Currently translated at 100.0% (1174 of 1174 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Co-authored-by: York <goog10216922@gmail.com>
2026-03-07 10:09:54 +01:00
jeffvli d3d3688d60 add Symbola font for explicit status indicator 2026-03-07 00:50:00 -08:00
Kendall Garner 49c28299af remove package.lock, make lint happy 2026-03-06 21:04:51 -08:00
Kendall Garner 0bb6fea3db don't assume server exists in enable either 2026-03-06 20:59:13 -08:00
Kendall Garner 7027084394 fix(autosave): server isn't guaranteed to exist 2026-03-06 20:52:41 -08:00
Kendall Garner 7c4cbaad9a feat(player): add server-side autosave capability 2026-03-06 20:01:35 -08:00
jeffvli e603048a80 add settings override with env variables 2026-03-06 19:32:38 -08:00
jeffvli 9e08157517 add has_rating filter for Navidrome song list 2026-03-06 18:03:14 -08:00
Hosted Weblate d4c2b1e914 Translated using Weblate
Currently translated at 84.1% (985 of 1170 strings) (Japanese)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ja/

Co-authored-by: UnknownExplorer13 <kyedylanfenton@gmail.com>
2026-03-06 19:09:49 +00:00
Hosted Weblate 65dd67ec96 Translated using Weblate
Currently translated at 100.0% (1170 of 1170 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Co-authored-by: linger <linger0517@gmail.com>
2026-03-06 12:09:50 +00:00
Hosted Weblate 76259309af Translated using Weblate
Currently translated at 74.7% (875 of 1170 strings) (Finnish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fi/

Co-authored-by: jonoafi <joona@jonottaa.com>
2026-03-06 00:09:53 +01:00
Hosted Weblate 3e5a9db279 Translated using Weblate
Currently translated at 100.0% (1170 of 1170 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 100.0% (1170 of 1170 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Translated using Weblate

Currently translated at 100.0% (1170 of 1170 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: skajmer <skajmer@protonmail.com>
2026-03-05 15:09:54 +00:00
Hosted Weblate c155bbdb37 Translated using Weblate
Currently translated at 100.0% (1169 of 1169 strings) (Indonesian)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/id/

Co-authored-by: Arif Budiman <arifpedia@gmail.com>
2026-03-05 07:39:54 +01:00
jeffvli ecbc03f052 add dummy onErrorPause handler for radio player 2026-03-04 22:39:46 -08:00
jeffvli 6ef9efc8bf add 10s retry for playback on network err (#1779) 2026-03-04 22:32:33 -08:00
jeffvli 513e9e822d attempt to fix viewport size for mobile browsers (#1787) 2026-03-04 21:51:04 -08:00
jeffvli dbc215c44f add toggle visibility behavior to tray icon (#1793) 2026-03-04 21:38:11 -08:00
jeffvli 43c5cf4275 fix primary color css variable to use new shade value 2026-03-04 21:26:47 -08:00
Benjamin 41f1f376bc feat: customizable item layout on fullscreen player (#1769)
* change container display to release type, readd badge styling to improve contrast

* make everything customizable
2026-03-04 21:23:14 -08:00
jeffvli cad7fef454 add type assertion for primaryShade 2026-03-04 21:01:56 -08:00
jeffvli 93791aea15 add setting to override theme primary shade (#1791) 2026-03-04 20:58:30 -08:00
Hosted Weblate 884dcde289 Translated using Weblate
Currently translated at 67.2% (782 of 1163 strings) (Finnish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fi/

Co-authored-by: Lauri Koo <late91@gmail.com>
2026-03-05 05:09:50 +01:00
Hosted Weblate 21f993a951 Translated using Weblate
Currently translated at 100.0% (1163 of 1163 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Co-authored-by: linger <linger0517@gmail.com>
2026-03-04 05:09:49 +00:00
Hosted Weblate 4784228831 Translated using Weblate
Currently translated at 100.0% (1163 of 1163 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Co-authored-by: skajmer <skajmer@protonmail.com>
2026-03-03 21:09:48 +00:00
Hosted Weblate c6e3e0c07e Translated using Weblate
Currently translated at 100.0% (1163 of 1163 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 100.0% (1163 of 1163 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Fordas <fordas15@gmail.com>
2026-03-03 15:09:50 +00:00
Kendall Garner 30685e7252 fix(subsonic): do favorite filter processing on artist favorite 2026-03-03 06:54:59 -08:00
Kendall Garner 12a398a65c fix(server selector): better handling for large server/folder list 2026-03-02 22:30:14 -08:00
Kendall Garner 71360e37de fix(favorites): filter favorite artists on favorite page for Jellyfin 2026-03-02 21:02:24 -08:00
Kendall Garner f99b8ea9ee feat(queue): add go to current button 2026-03-02 20:30:35 -08:00
Kendall Garner 2854b928f6 fix(player): handle items in the queue moved to next before current index 2026-03-02 20:05:01 -08:00
Hosted Weblate 14e1f1d003 Translated using Weblate
Currently translated at 73.7% (857 of 1162 strings) (Russian)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ru/

Translated using Weblate

Currently translated at 100.0% (1162 of 1162 strings) (Tamil)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ta/

Co-authored-by: Платон Петров <pplaton6@gmail.com>
Co-authored-by: தமிழ்நேரம் <tamilneram247@gmail.com>
2026-03-01 23:10:04 +01:00
Hosted Weblate 85c490bd06 Translated using Weblate
Currently translated at 100.0% (1162 of 1162 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Co-authored-by: York <goog10216922@gmail.com>
2026-03-01 08:09:52 +01:00
Hosted Weblate 96d78f8bda Translated using Weblate
Currently translated at 44.6% (519 of 1162 strings) (Norwegian Bokmål)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/nb_NO/

Co-authored-by: klodrik <klodrik@zoominn.no>
2026-02-28 14:09:50 +00:00
jeffvli 5f65aebe63 convert nd album rating filter to yes/no (#1775) 2026-02-27 19:30:33 -08:00
Hosted Weblate cd96da9cd5 Translated using Weblate
Currently translated at 100.0% (1162 of 1162 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Translated using Weblate

Currently translated at 100.0% (1162 of 1162 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Translated using Weblate

Currently translated at 100.0% (1162 of 1162 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: skajmer <skajmer@protonmail.com>
2026-02-27 23:09:53 +00:00
Hosted Weblate 674b66b682 Translated using Weblate
Currently translated at 84.6% (984 of 1162 strings) (Japanese)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ja/

Co-authored-by: karigane <169052233+karigane-cha@users.noreply.github.com>
2026-02-27 15:09:56 +01:00
jeffvli 934851456b prevent click propagation on detached queue button (#1762) 2026-02-27 00:53:09 -08:00
jeffvli afca396654 attempt to fix mpv autoNext behavior (#1768) 2026-02-27 00:39:27 -08:00
jeffvli b62f62671d fix table config drag and drop interaction on bottom edge 2026-02-26 20:59:28 -08:00
Norman eb8913479b Add album grouping column (#1722)
* Add album grouping column

---------

Co-authored-by: jeffvli <jeffvictorli@gmail.com>
2026-02-26 20:34:55 -08:00
Alexander Welsing 4918b412b2 Album radio (#1759)
* added album radio feature

---------

Co-authored-by: jeffvli <jeffvictorli@gmail.com>
2026-02-26 20:33:00 -08:00
jeffvli a78f5803a5 fix mediasession play hotkey on after pause on web (#1758)
- chrome (and other browsers) determine that the audio element is inactive if the volume is set to 0 when paused, leading to the resume (play) mediasession event to no longer be available
2026-02-26 01:11:24 -08:00
dependabot[bot] 0d1799cbf7 Bump the npm_and_yarn group across 1 directory with 6 updates (#1763)
Bumps the npm_and_yarn group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [axios](https://github.com/axios/axios) | `1.13.2` | `1.13.5` |
| [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) | `5.3.3` | `5.3.6` |
| [lodash](https://github.com/lodash/lodash) | `4.17.21` | `4.17.23` |
| [qs](https://github.com/ljharb/qs) | `6.14.1` | `6.14.2` |
| [minimatch](https://github.com/isaacs/minimatch) | `3.1.2` | `3.1.5` |
| [tar](https://github.com/isaacs/node-tar) | `6.2.1` | `7.5.9` |



Updates `axios` from 1.13.2 to 1.13.5
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.13.2...v1.13.5)

Updates `fast-xml-parser` from 5.3.3 to 5.3.6
- [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases)
- [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.3.3...v5.3.6)

Updates `lodash` from 4.17.21 to 4.17.23
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.21...4.17.23)

Updates `qs` from 6.14.1 to 6.14.2
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.14.1...v6.14.2)

Updates `minimatch` from 3.1.2 to 3.1.5
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5)

Updates `tar` from 6.2.1 to 7.5.9
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v6.2.1...v7.5.9)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.13.5
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: fast-xml-parser
  dependency-version: 5.3.6
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: lodash
  dependency-version: 4.17.23
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: qs
  dependency-version: 6.14.2
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: minimatch
  dependency-version: 3.1.5
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: tar
  dependency-version: 7.5.9
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 22:22:53 -08:00
jeffvli 438db40d0e remove audio prefix from subsonic contentType property 2026-02-25 22:22:13 -08:00
dependabot[bot] aca5e1fe87 Bump react-router in the npm_and_yarn group across 1 directory (#1534)
Bumps the npm_and_yarn group with 1 update in the / directory: [react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router).


Updates `react-router` from 7.11.0 to 7.12.0
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router@7.12.0/packages/react-router)

---
updated-dependencies:
- dependency-name: react-router
  dependency-version: 7.12.0
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 22:06:26 -08:00
Tarulia 8aaf24ff87 Redo Icons in SVG (#1731)
Also includes exports from SVG for all relevant files:
- `assets/icons/` in 16-1024px size PNGs
- `assets/icons/icon.ico` using same sizes as the old one
- `assets/icons/` IconTemplate
- `media/` black and white logo-only variants
- `resource/icon.png`
2026-02-25 21:35:13 -08:00
Hosted Weblate 75dbea1ab7 Translated using Weblate
Currently translated at 100.0% (1160 of 1160 strings) (Catalan)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ca/

Co-authored-by: HUMET <ressaguer@proton.me>
2026-02-25 16:09:51 +00:00
jeffvli 61616dd2b9 move remote hook to global scope (#1752) 2026-02-24 00:45:43 -08:00
jeffvli ceef7964af add originalyear to smart playlist filters (#1746) 2026-02-24 00:34:07 -08:00
jeffvli ec12e89653 fix missing blur config from expanded album image 2026-02-23 23:48:56 -08:00
Hosted Weblate 386ca41a5d Translated using Weblate
Currently translated at 99.3% (1152 of 1160 strings) (French)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/

Co-authored-by: KosmoMoustache <kosmomoustache@users.noreply.hosted.weblate.org>
2026-02-24 01:09:49 +00:00
Hosted Weblate a8fd5a4f46 Translated using Weblate
Currently translated at 100.0% (1160 of 1160 strings) (Dutch)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/nl/

Co-authored-by: bokse <weblate@bokse.nl>
2026-02-23 16:09:54 +01:00
Hosted Weblate 4590383a97 Translated using Weblate
Currently translated at 83.1% (964 of 1160 strings) (Japanese)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ja/

Translated using Weblate

Currently translated at 100.0% (1160 of 1160 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: karigane <169052233+karigane-cha@users.noreply.github.com>
2026-02-22 14:09:50 +01:00
Hosted Weblate 405208cf92 Translated using Weblate
Currently translated at 97.8% (1135 of 1160 strings) (Chinese (Simplified Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hans/

Co-authored-by: 無情天 <kofzhanganguo@126.com>
2026-02-22 00:09:48 +01:00
Hosted Weblate f19c37276a Translated using Weblate
Currently translated at 100.0% (1160 of 1160 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Co-authored-by: skajmer <skajmer@protonmail.com>
2026-02-21 15:09:49 +01:00
Hosted Weblate 3269034bfb Translated using Weblate
Currently translated at 88.9% (1032 of 1160 strings) (German)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/de/

Translated using Weblate

Currently translated at 99.1% (1150 of 1160 strings) (French)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/

Translated using Weblate

Currently translated at 42.4% (492 of 1160 strings) (Norwegian Bokmål)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/nb_NO/

Co-authored-by: KosmoMoustache <kosmomoustache@users.noreply.hosted.weblate.org>
Co-authored-by: PhillyMay <mein.alias@outlook.com>
Co-authored-by: klodrik <klodrik@zoominn.no>
2026-02-20 22:09:52 +00:00
Lyosha e5f99af43b Fix image resolution setting value checking (#1741) 2026-02-20 13:10:26 -08:00
Hosted Weblate 2866ca9537 Translated using Weblate
Currently translated at 100.0% (1160 of 1160 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 40.6% (471 of 1160 strings) (Norwegian Bokmål)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/nb_NO/

Translated using Weblate

Currently translated at 99.1% (1150 of 1160 strings) (French)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/

Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: KosmoMoustache <kosmomoustache@users.noreply.hosted.weblate.org>
Co-authored-by: klodrik <klodrik@zoominn.no>
2026-02-20 17:09:51 +00:00
Kendall Garner a377eae2f4 fix(build): do not add hash to favicon and assets 2026-02-20 08:48:36 -08:00
Hosted Weblate dbd8ce2380 Translated using Weblate
Currently translated at 100.0% (1160 of 1160 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Co-authored-by: linger <linger0517@gmail.com>
2026-02-20 12:09:53 +01:00
Kendall Garner 0741351318 fix(share): only copy to clipboard if available and secure 2026-02-19 19:55:10 -08:00
Hosted Weblate ab9e02adfc Translated using Weblate
Currently translated at 39.6% (459 of 1158 strings) (Norwegian Bokmål)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/nb_NO/

Co-authored-by: klodrik <klodrik@zoominn.no>
2026-02-19 19:09:47 +01:00
Kendall Garner 12ff690619 fix(window): recreate window on macos when closed but not quit 2026-02-18 21:50:44 -08:00
jeffvli 5039012fcb catch errors on desktop scrobble notification failure (#1723) 2026-02-18 20:54:31 -08:00
jeffvli 75af57a7b3 use correct player seek event for mpris updater (#1740) 2026-02-18 20:37:18 -08:00
jeffvli 9027eee99f fix lyrics type in player sidebar 2026-02-18 20:28:14 -08:00
jeffvli 50fe373f1e simplify lyrics implementation
- removes complex lyrics fetch and override logic, and instead uses a single query as a source of truth for the lyrics
- properly handles loading state, invalidation, and refetch
2026-02-18 20:25:52 -08:00
Alexander Welsing 2c546867a8 change "Fields" query parameter to array (#1733)
* change "Fields" query parameter to array

* platformToTarget.key() -> to array
2026-02-17 18:45:31 -08:00
Kendall Garner 9dad934a40 transcode player bar waveform 2026-02-17 14:30:26 -08:00
Hosted Weblate 34dbb4c794 Translated using Weblate
Currently translated at 77.2% (894 of 1158 strings) (Italian)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/it/

Co-authored-by: Giuseppe Filomeno <giusefilo@gmail.com>
2026-02-17 19:10:04 +00:00
Hosted Weblate 7472af66ef Translated using Weblate
Currently translated at 99.3% (1150 of 1158 strings) (French)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/

Co-authored-by: KosmoMoustache <kosmomoustache@users.noreply.hosted.weblate.org>
2026-02-17 00:09:52 +01:00
Adam f293fb287d Add hook script to update and publish appstream metainfo on electron build (#1719) 2026-02-16 12:54:11 -08:00
libussa 7656e84c20 fix stale SERVER_URL when changing env var in Docker (#1714)
settings.js (which injects SERVER_URL into the browser) was served
without Cache-Control headers, causing Cloudflare and other reverse
proxies to cache the old value indefinitely. Additionally, when
SERVER_LOCK is enabled, the persisted server URL in localStorage was
never compared against the current window.SERVER_URL, so same-browser
sessions kept using the old server even after settings.js was updated.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 12:44:29 -08:00
Kendall Garner c524e8d3b7 fix(left-controls): use joined artsts instead of array by artist id 2026-02-16 07:52:36 -08:00
Hosted Weblate 7f13ce491b Translated using Weblate
Currently translated at 92.0% (1066 of 1158 strings) (French)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/

Co-authored-by: Nicolas DERIVE <kalon33@ubuntu.com>
2026-02-16 15:09:54 +00:00
Hosted Weblate 6c16aabce0 Translated using Weblate
Currently translated at 88.3% (1023 of 1158 strings) (German)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/de/

Co-authored-by: PhillyMay <mein.alias@outlook.com>
2026-02-15 13:10:11 +01:00
Hosted Weblate f5240b1766 Translated using Weblate
Currently translated at 78.7% (912 of 1158 strings) (German)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/de/

Co-authored-by: PhillyMay <mein.alias@outlook.com>
2026-02-15 04:09:48 +01:00
Hosted Weblate cc5a95d725 Translated using Weblate
Currently translated at 100.0% (1158 of 1158 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Translated using Weblate

Currently translated at 100.0% (1158 of 1158 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: York <goog10216922@gmail.com>
2026-02-14 20:09:53 +01:00
Hosted Weblate 8ba63988d8 Translated using Weblate
Currently translated at 97.8% (1133 of 1158 strings) (Chinese (Simplified Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hans/

Translated using Weblate

Currently translated at 100.0% (1158 of 1158 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Translated using Weblate

Currently translated at 100.0% (1158 of 1158 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: skajmer <skajmer@protonmail.com>
Co-authored-by: 無情天 <kofzhanganguo@126.com>
2026-02-14 15:09:49 +01:00
jeffvli 289f307a52 update to v1.6.0 2026-02-13 23:08:33 -08:00
jeffvli 91ac36c835 fix Subsonic root folder condition (#1686)
- some older subsonic servers used numeric ids which causes the rootFolderId regex to fail which resulted in the getFolder endpoint to always attempt to fetch the root
2026-02-13 23:03:24 -08:00
jeffvli 503e4b2bac fix list refresh not working on discography/genre pages 2026-02-13 21:38:12 -08:00
jeffvli c39ddc3b45 refactor PlaylistQueryEditor to new file 2026-02-13 21:05:37 -08:00
jeffvli 1163c4ad5e add JSON editor for playlist query builder (#1711) 2026-02-13 21:05:34 -08:00
jeffvli e497734c07 allow all rule groups to be empty (#1710) 2026-02-13 20:26:58 -08:00
Kendall Garner 77fef33cbf improve album artist favorite performance and search (#1709)
* improve album artist favorite performance and search

* adjust top songs / favorite songs sections

---------

Co-authored-by: jeffvli <jeffvictorli@gmail.com>
2026-02-13 20:13:28 -08:00
Hosted Weblate 81189db1e1 Translated using Weblate
Currently translated at 100.0% (1156 of 1156 strings) (Catalan)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ca/

Co-authored-by: HUMET <ressaguer@proton.me>
2026-02-14 03:46:02 +00:00
Maevi 054a3d005e Listen on IPv6 by default in docker image (#1707) 2026-02-13 19:45:55 -08:00
jeffvli dfbff64430 fix duplicate server add when SERVER_LOCK is configured (#1623) 2026-02-13 19:42:36 -08:00
jeffvli 2b4046a82e fix double click propagation on the table expand button 2026-02-13 17:49:49 -08:00
jeffvli 9eb879fc37 hide favorite / rating from playlist album view items 2026-02-13 17:39:35 -08:00
jeffvli 9e63ee2735 add loading spinners for some lazy loaded content 2026-02-13 15:04:54 -08:00
jeffvli 9950e51d45 remove lazy loading from context menu initialization 2026-02-13 15:01:18 -08:00
jeffvli 70fdd4bdc3 refactor album expansion to global scope 2026-02-13 14:59:15 -08:00
jeffvli e855f7dd01 remove invalid detail view type for song list config 2026-02-13 12:19:14 -08:00
jeffvli 123842dfda attempt to optimize the tagList query
- this query in some cases can return a very large amount of data, depending on the size of the user's library
- increasing the cacheTime reduces the frequency of fetches while disabling structuralSharing reduces the need for react-query to do a deep equality comparison for the cache
2026-02-13 11:53:42 -08:00
Hosted Weblate 1338513f82 Translated using Weblate
Currently translated at 100.0% (1156 of 1156 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Co-authored-by: Fjuro <fjuro@alius.cz>
2026-02-13 19:09:45 +01:00
Hosted Weblate c9c88dd82d Translated using Weblate
Currently translated at 100.0% (1156 of 1156 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Translated using Weblate

Currently translated at 100.0% (1156 of 1156 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: York <goog10216922@gmail.com>
2026-02-13 14:09:48 +01:00
York 02a5395453 fix: regenerate macOS icon (.icns) to fix glitched small icons (#1705) 2026-02-13 00:15:12 -08:00
jeffvli 7ba2f6b827 fix removed filter functions 2026-02-12 22:04:08 -08:00
jeffvli f1b5dc8ef3 add additional client-side filters to playlist songs 2026-02-12 22:00:07 -08:00
Kendall Garner 78875572e9 add explicit blurring to left expanded image and full screen (#1701)
* add explicit blurring to left expanded image and full screen
2026-02-12 18:49:57 -08:00
jeffvli f487560ec5 fix vite web build again for hashed assets and PWA cache clear 2026-02-12 18:21:27 -08:00
jeffvli f752090c78 Revert "attempt fix for web/docker cache busting on new release"
This reverts commit 91e7c7434c.
2026-02-12 18:17:49 -08:00
jeffvli 96f5b2b82a Revert "fix vite web build to work with subpath"
This reverts commit 1a9f36ce9e.
2026-02-12 18:17:44 -08:00
jeffvli 80292ae579 fix alpha autoupdater logic to use correct config for latest 2026-02-12 18:17:08 -08:00
Hosted Weblate 1d156ac506 Translated using Weblate
Currently translated at 100.0% (1154 of 1154 strings) (Czech)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/

Co-authored-by: Fjuro <fjuro@alius.cz>
2026-02-13 00:09:58 +00:00
jeffvli dc5586f859 adjuat audioDevice description to remove web player disclaimer 2026-02-12 11:18:55 -08:00
jeffvli 1a9f36ce9e fix vite web build to work with subpath 2026-02-12 11:18:55 -08:00
York 203c8a6588 fix: restore original macOS squircle icon and regenerate icns properly (#1703) 2026-02-12 10:03:23 -08:00
Hosted Weblate 2e6cf8d869 Translated using Weblate
Currently translated at 100.0% (1154 of 1154 strings) (Spanish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/

Co-authored-by: Fordas <fordas15@gmail.com>
2026-02-12 17:09:48 +00:00
Hosted Weblate b1827dd352 Translated using Weblate
Currently translated at 100.0% (1154 of 1154 strings) (Polish)
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/

Translated using Weblate

Currently translated at 100.0% (1154 of 1154 strings) (Chinese (Traditional Han script))
Translation: feishin/Translation
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/

Co-authored-by: York <goog10216922@gmail.com>
Co-authored-by: skajmer <skajmer@protonmail.com>
2026-02-12 11:09:50 +01:00
jeffvli 0d2dddddbc fix invalid comparison on detail rating column hide condition 2026-02-12 01:40:01 -08:00
jeffvli 1d8e1957ba handle image drag from item detail list 2026-02-12 01:37:59 -08:00
jeffvli dc957cb3cc hide detail rating column on zero value 2026-02-12 00:57:24 -08:00
jeffvli c314fa0bf3 properly handle context menu in playlist album view 2026-02-12 00:54:45 -08:00
jeffvli c5ebfac647 fix playlist grid view itemType to PLAYLIST_SONG to support remove from playlist 2026-02-12 00:28:39 -08:00
jeffvli 4adea11a93 support select all hotkey in detail list view 2026-02-12 00:13:32 -08:00
Jeff e6f49b9f1f Add album view for playlists (#1700)
* update client side song ordering to include album order

* add compact styling to LibraryHeader

* move search button to top right of LibraryHeader
2026-02-11 21:48:25 -08:00
York 9cde569c7d Add option to show playing icon in Discord RPC (#1699)
* feat: add option to show playing/paused icon in Discord RPC
2026-02-11 21:14:58 -08:00
jeffvli 91e7c7434c attempt fix for web/docker cache busting on new release
- remove static asset filenames
- add cache clear config to PWA
- move PWA to base dir instead of assets
2026-02-11 20:52:28 -08:00
Yoshua Wakeham ffef5dfdee fix: actually show Jellyfin recently played songs carousel (#1697) 2026-02-11 20:35:23 -08:00
Kendall Garner 409dd69fcb reduce explicit indicator spacing slightly 2026-02-11 19:34:20 -08:00
Hosted Weblate 064cf5103a Translated using Weblate
Currently translated at 100.0% (1152 of 1152 strings)

Co-authored-by: Ondo <SparkyOndo@proton.me>
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/ca/
Translation: feishin/Translation
2026-02-11 23:09:47 +01:00
Hosted Weblate 7e3a613a93 Translated using Weblate
Currently translated at 100.0% (1152 of 1152 strings)

Translated using Weblate

Currently translated at 100.0% (1152 of 1152 strings)

Translated using Weblate

Currently translated at 99.9% (1151 of 1152 strings)

Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: skajmer <skajmer@protonmail.com>
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/cs/
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/pl/
Translation: feishin/Translation
2026-02-11 16:09:52 +01:00
Hosted Weblate e7c49f6d67 Translated using Weblate
Currently translated at 36.6% (422 of 1152 strings)

Translated using Weblate

Currently translated at 33.5% (387 of 1152 strings)

Translated using Weblate

Currently translated at 100.0% (1152 of 1152 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 96.3% (1101 of 1143 strings)

Translated using Weblate (Ukrainian)

Currently translated at 32.1% (368 of 1143 strings)

Translated using Weblate (French)

Currently translated at 91.3% (1044 of 1143 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (1143 of 1143 strings)

Translated using Weblate (Chinese (Traditional Han script))

Currently translated at 100.0% (1143 of 1143 strings)

Co-authored-by: Fordas <fordas15@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Raphael <raphael.margueron@gmail.com>
Co-authored-by: York <goog10216922@gmail.com>
Co-authored-by: Yurii <04_hours.lambing@icloud.com>
Co-authored-by: linger <linger0517@gmail.com>
Co-authored-by: 無情天 <kofzhanganguo@126.com>
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/es/
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/fr/
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/uk/
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hans/
Translate-URL: https://hosted.weblate.org/projects/feishin/translation/zh_Hant/
Translation: feishin/Translation
2026-02-11 11:02:22 +01:00
427 changed files with 25680 additions and 28686 deletions
+12 -12
View File
@@ -40,12 +40,12 @@ jobs:
version: ${{ steps.version.outputs.version }} version: ${{ steps.version.outputs.version }}
steps: steps:
- name: Checkout git repo - name: Checkout git repo
uses: actions/checkout@v1 uses: actions/checkout@v6
- name: Install Node and PNPM - name: Install Node and PNPM
uses: pnpm/action-setup@v4.1.0 uses: pnpm/action-setup@v4
with: with:
version: 9 version: 10
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
@@ -121,16 +121,16 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [windows-latest, macos-latest, ubuntu-latest] os: [windows-latest, macos-26, ubuntu-latest]
steps: steps:
- name: Checkout git repo - name: Checkout git repo
uses: actions/checkout@v1 uses: actions/checkout@v6
- name: Install Node and PNPM - name: Install Node and PNPM
uses: pnpm/action-setup@v4.1.0 uses: pnpm/action-setup@v4
with: with:
version: 9 version: 10
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
@@ -146,7 +146,7 @@ jobs:
- name: Build and Publish to R2 (Windows) - name: Build and Publish to R2 (Windows)
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -156,8 +156,8 @@ jobs:
on_retry_command: pnpm cache delete on_retry_command: pnpm cache delete
- name: Build and Publish to R2 (macOS) - name: Build and Publish to R2 (macOS)
if: matrix.os == 'macos-latest' if: matrix.os == 'macos-26'
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -168,7 +168,7 @@ jobs:
- name: Build and Publish to R2 (Linux) - name: Build and Publish to R2 (Linux)
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -179,7 +179,7 @@ jobs:
- name: Build and Publish to R2 (Linux ARM64) - name: Build and Publish to R2 (Linux ARM64)
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
+14 -14
View File
@@ -15,12 +15,12 @@ jobs:
version: ${{ steps.version.outputs.version }} version: ${{ steps.version.outputs.version }}
steps: steps:
- name: Checkout git repo - name: Checkout git repo
uses: actions/checkout@v1 uses: actions/checkout@v6
- name: Install Node and PNPM - name: Install Node and PNPM
uses: pnpm/action-setup@v4.1.0 uses: pnpm/action-setup@v4
with: with:
version: 9 version: 10
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
@@ -115,16 +115,16 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [windows-latest, macos-latest, ubuntu-latest] os: [windows-latest, macos-26, ubuntu-latest]
steps: steps:
- name: Checkout git repo - name: Checkout git repo
uses: actions/checkout@v1 uses: actions/checkout@v6
- name: Install Node and PNPM - name: Install Node and PNPM
uses: pnpm/action-setup@v4.1.0 uses: pnpm/action-setup@v4
with: with:
version: 9 version: 10
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
@@ -146,7 +146,7 @@ jobs:
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -156,10 +156,10 @@ jobs:
on_retry_command: pnpm cache delete on_retry_command: pnpm cache delete
- name: Build and Publish releases (macOS) - name: Build and Publish releases (macOS)
if: matrix.os == 'macos-latest' if: matrix.os == 'macos-26'
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -172,7 +172,7 @@ jobs:
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -185,7 +185,7 @@ jobs:
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -199,7 +199,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout git repo - name: Checkout git repo
uses: actions/checkout@v1 uses: actions/checkout@v6
- name: Edit release with commits and title - name: Edit release with commits and title
shell: pwsh shell: pwsh
@@ -346,7 +346,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout git repo - name: Checkout git repo
uses: actions/checkout@v1 uses: actions/checkout@v6
- name: Delete existing prereleases - name: Delete existing prereleases
shell: pwsh shell: pwsh
+1 -2
View File
@@ -20,7 +20,7 @@ jobs:
packages: write packages: write
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Log in to the Container registry - name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with: with:
@@ -51,5 +51,4 @@ jobs:
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
platforms: | platforms: |
linux/amd64 linux/amd64
linux/arm/v7
linux/arm64/v8 linux/arm64/v8
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
packages: write packages: write
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Log in to the Container registry - name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with: with:
+5 -5
View File
@@ -12,12 +12,12 @@ jobs:
steps: steps:
- name: Checkout git repo - name: Checkout git repo
uses: actions/checkout@v1 uses: actions/checkout@v6
- name: Install Node and PNPM - name: Install Node and PNPM
uses: pnpm/action-setup@v4.1.0 uses: pnpm/action-setup@v4
with: with:
version: 9 version: 10
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
@@ -25,7 +25,7 @@ jobs:
- name: Build and Publish releases - name: Build and Publish releases
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -37,7 +37,7 @@ jobs:
- name: Build and Publish releases (arm64) - name: Build and Publish releases (arm64)
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
+6 -5
View File
@@ -8,24 +8,25 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [macos-latest] os: [macos-26]
steps: steps:
- name: Checkout git repo - name: Checkout git repo
uses: actions/checkout@v1 uses: actions/checkout@v6
- name: Install Node and PNPM - name: Install Node and PNPM
uses: pnpm/action-setup@v4.1.0 uses: pnpm/action-setup@v4
with: with:
version: 9 version: 10
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: Build and Publish releases - name: Build and Publish releases
env: env:
NODE_OPTIONS: --max-old-space-size=4096
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
+17 -13
View File
@@ -1,14 +1,17 @@
name: Publish (PR) name: Publish (PR)
on: on:
workflow_dispatch:
pull_request: pull_request:
branches: branches:
- development - development
paths: paths:
- 'src/**' - 'src/**'
- 'electron-builder*.yml'
jobs: jobs:
wait-for-lint: wait-for-lint:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Wait for Test workflow to complete - name: Wait for Test workflow to complete
@@ -22,27 +25,28 @@ jobs:
publish: publish:
needs: wait-for-lint needs: wait-for-lint
if: always() && (needs.wait-for-lint.result == 'success' || needs.wait-for-lint.result == 'skipped')
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [macos-latest, ubuntu-latest, windows-latest] os: [macos-26, ubuntu-latest, windows-latest]
steps: steps:
- name: Checkout git repo - name: Checkout git repo
uses: actions/checkout@v3 uses: actions/checkout@v6
- name: Install Node and PNPM - name: Install Node and PNPM
uses: pnpm/action-setup@v4.1.0 uses: pnpm/action-setup@v4
with: with:
version: 9 version: 10
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: Build for Windows - name: Build for Windows
if: ${{ matrix.os == 'windows-latest' }} if: ${{ matrix.os == 'windows-latest' }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -52,7 +56,7 @@ jobs:
- name: Build for Linux - name: Build for Linux
if: ${{ matrix.os == 'ubuntu-latest' }} if: ${{ matrix.os == 'ubuntu-latest' }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -61,8 +65,8 @@ jobs:
pnpm run package:linux:pr pnpm run package:linux:pr
- name: Build for MacOS - name: Build for MacOS
if: ${{ matrix.os == 'macos-latest' }} if: ${{ matrix.os == 'macos-26' }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -82,27 +86,27 @@ jobs:
zip -r dist/linux-binaries.zip dist/*.{AppImage,deb,rpm} zip -r dist/linux-binaries.zip dist/*.{AppImage,deb,rpm}
- name: Zip MacOS Binaries - name: Zip MacOS Binaries
if: ${{ matrix.os == 'macos-latest' }} if: ${{ matrix.os == 'macos-26' }}
run: | run: |
zip -r dist/macos-binaries.zip dist/*.dmg zip -r dist/macos-binaries.zip dist/*.dmg
- name: Upload Windows Binaries - name: Upload Windows Binaries
if: ${{ matrix.os == 'windows-latest' }} if: ${{ matrix.os == 'windows-latest' }}
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v7
with: with:
name: windows-binaries name: windows-binaries
path: dist/windows-binaries.zip path: dist/windows-binaries.zip
- name: Upload Linux Binaries - name: Upload Linux Binaries
if: ${{ matrix.os == 'ubuntu-latest' }} if: ${{ matrix.os == 'ubuntu-latest' }}
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v7
with: with:
name: linux-binaries name: linux-binaries
path: dist/linux-binaries.zip path: dist/linux-binaries.zip
- name: Upload MacOS Binaries - name: Upload MacOS Binaries
if: ${{ matrix.os == 'macos-latest' }} if: ${{ matrix.os == 'macos-26' }}
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v7
with: with:
name: macos-binaries name: macos-binaries
path: dist/macos-binaries.zip path: dist/macos-binaries.zip
+4 -4
View File
@@ -12,12 +12,12 @@ jobs:
steps: steps:
- name: Checkout git repo - name: Checkout git repo
uses: actions/checkout@v1 uses: actions/checkout@v6
- name: Install Node and PNPM - name: Install Node and PNPM
uses: pnpm/action-setup@v4.1.0 uses: pnpm/action-setup@v4
with: with:
version: 9 version: 10
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
@@ -25,7 +25,7 @@ jobs:
- name: Build and Publish releases - name: Build and Publish releases
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
+9 -9
View File
@@ -8,16 +8,16 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [windows-latest, macos-latest, ubuntu-latest] os: [windows-latest, macos-26, ubuntu-latest]
steps: steps:
- name: Checkout git repo - name: Checkout git repo
uses: actions/checkout@v1 uses: actions/checkout@v6
- name: Install Node and PNPM - name: Install Node and PNPM
uses: pnpm/action-setup@v4.1.0 uses: pnpm/action-setup@v4
with: with:
version: 9 version: 10
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
@@ -26,7 +26,7 @@ jobs:
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -36,10 +36,10 @@ jobs:
on_retry_command: pnpm cache delete on_retry_command: pnpm cache delete
- name: Build and Publish releases (macOS) - name: Build and Publish releases (macOS)
if: matrix.os == 'macos-latest' if: matrix.os == 'macos-26'
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -52,7 +52,7 @@ jobs:
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
@@ -65,7 +65,7 @@ jobs:
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: nick-invision/retry@v2.8.2 uses: nick-invision/retry@v3.0.2
with: with:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
+3 -3
View File
@@ -8,12 +8,12 @@ jobs:
steps: steps:
- name: Check out Git repository - name: Check out Git repository
uses: actions/checkout@v1 uses: actions/checkout@v6
- name: Install Node.js and PNPM - name: Install Node.js and PNPM
uses: pnpm/action-setup@v4.1.0 uses: pnpm/action-setup@v4
with: with:
version: 9 version: 10
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
-1
View File
@@ -1,2 +1 @@
legacy-peer-deps=true legacy-peer-deps=true
only-built-dependencies=electron,esbuild
+5 -5
View File
@@ -1,5 +1,5 @@
# --- Builder stage # --- Builder stage
FROM node:23-alpine as builder FROM node:23-alpine AS builder
WORKDIR /app WORKDIR /app
# Copy package.json first to cache node_modules # Copy package.json first to cache node_modules
@@ -14,13 +14,13 @@ COPY . .
RUN pnpm run build:web RUN pnpm run build:web
# --- Production stage # --- Production stage
FROM nginx:alpine-slim FROM nginxinc/nginx-unprivileged:alpine-slim
COPY --chown=nginx:nginx --from=builder /app/out/web /usr/share/nginx/html COPY --chown=nginx:nginx --from=builder /app/out/web /usr/share/nginx/html
COPY ./settings.js.template /etc/nginx/templates/settings.js.template COPY --chown=nginx:nginx ./settings.js.template /etc/nginx/templates/settings.js.template
COPY ng.conf.template /etc/nginx/templates/default.conf.template COPY --chown=nginx:nginx ng.conf.template /etc/nginx/templates/default.conf.template
ENV SERVER_LOCK=false SERVER_NAME="" SERVER_TYPE="" SERVER_URL="" ENV SERVER_LOCK=false SERVER_NAME="" SERVER_TYPE="" SERVER_URL="" REMOTE_URL=""
ENV LEGACY_AUTHENTICATION="" ANALYTICS_DISABLED="" PUBLIC_PATH="/" ENV LEGACY_AUTHENTICATION="" ANALYTICS_DISABLED="" PUBLIC_PATH="/"
EXPOSE 9180 EXPOSE 9180
+15 -2
View File
@@ -59,7 +59,11 @@ For media keys to work, you will be prompted to allow Feishin to be a Trusted Ac
#### Linux Notes #### Linux Notes
We provide a small install script to download the latest `.AppImage`, make it executable, and also download the icons required by Desktop Environments. Finally, it generates a `.desktop` file to add Feishin to your Application Launcher. Feishin is available in [Flathub](https://flathub.org/en/apps/org.jeffvli.feishin).
Alternatively, you can install it as an Appimage.
We provide a small install script to download the latest `.AppImage`, make it executable, and also download the icons required by Desktop Environments.
Finally, it generates a `.desktop` file to add Feishin to your Application Launcher.
Simply run the installer like this: Simply run the installer like this:
@@ -114,6 +118,7 @@ services:
- SERVER_LOCK=true # When true AND name/type/url are set, only username/password can be toggled - SERVER_LOCK=true # When true AND name/type/url are set, only username/password can be toggled
- SERVER_TYPE=jellyfin # the allowed types are: jellyfin, navidrome, subsonic. These values are case insensitive - SERVER_TYPE=jellyfin # the allowed types are: jellyfin, navidrome, subsonic. These values are case insensitive
- SERVER_URL= # http://address:port or https://address:port - SERVER_URL= # http://address:port or https://address:port
- REMOTE_URL= # http://address or https://address
- LEGACY_AUTHENTICATION=false # When SERVER_LOCK is true, sets the legacy (plaintext) authentication flag for Subsonic/OpenSubsonic servers - LEGACY_AUTHENTICATION=false # When SERVER_LOCK is true, sets the legacy (plaintext) authentication flag for Subsonic/OpenSubsonic servers
- ANALYTICS_DISABLED=true # Set to true to disable Umami analytics tracking - ANALYTICS_DISABLED=true # Set to true to disable Umami analytics tracking
ports: ports:
@@ -134,7 +139,11 @@ services:
4. _Optional_ - To hard code the server url, pass the following environment variables: `SERVER_NAME`, `SERVER_TYPE` (one of `jellyfin` or `navidrome` or `subsonic`), `SERVER_URL`. To prevent users from changing these settings, pass `SERVER_LOCK=true`. This can only be set if all three of the previous values are set. When `SERVER_LOCK=true`, you can also set `LEGACY_AUTHENTICATION=true` or `LEGACY_AUTHENTICATION=false` to configure the legacy authentication flag for the server (only applicable for Subsonic/OpenSubsonic servers). 4. _Optional_ - To hard code the server url, pass the following environment variables: `SERVER_NAME`, `SERVER_TYPE` (one of `jellyfin` or `navidrome` or `subsonic`), `SERVER_URL`. To prevent users from changing these settings, pass `SERVER_LOCK=true`. This can only be set if all three of the previous values are set. When `SERVER_LOCK=true`, you can also set `LEGACY_AUTHENTICATION=true` or `LEGACY_AUTHENTICATION=false` to configure the legacy authentication flag for the server (only applicable for Subsonic/OpenSubsonic servers).
5. _Optional_ - To disable Umami analytics tracking in the Docker/web version, set the environment variable `ANALYTICS_DISABLED=true`. When enabled, the analytics script will not be loaded and all tracking will be disabled. 5. _Optional_ - If your server uses a separate public-facing URL than what integrating applications use internally to communicate with your server, such as a separate Navidrome `ShareURL`, set `REMOTE_URL` to said public-facing URL.
6. _Optional_ - To disable Umami analytics tracking in the Docker/web version, set the environment variable `ANALYTICS_DISABLED=true`. When enabled, the analytics script will not be loaded and all tracking will be disabled.
7. _Optional_ - App settings (theme, language, sidebar options, etc.) can be overridden with environment variables on first run. The variables use the `FS_` prefix (e.g. `FS_GENERAL_THEME=defaultDark`, `FS_GENERAL_LANGUAGE=de`). See [the settings environment variable documentation](docs/ENV_SETTINGS.md) for the full list.
## FAQ ## FAQ
@@ -160,6 +169,10 @@ Feishin supports any music server that implements a [Navidrome](https://www.navi
- [Qm-Music](https://github.com/chenqimiao/qm-music) - [Qm-Music](https://github.com/chenqimiao/qm-music)
- More (?) - More (?)
- [Plex](https://www.plex.tv/media-server-downloads)
- [Feishin fork by lux032](https://github.com/lux032/feishin) - Plex is not natively supported. Use the fork by lux032 to use Plex with Feishin.
### I have the issue "The SUID sandbox helper binary was found, but is not configured correctly" on Linux ### I have the issue "The SUID sandbox helper binary was found, but is not configured correctly" on Linux
This happens when you have user (unprivileged) namespaces disabled (`sysctl kernel.unprivileged_userns_clone` returns 0). You can fix this by either enabling unprivileged namespaces, or by making the `chrome-sandbox` Setuid. This happens when you have user (unprivileged) namespaces disabled (`sysctl kernel.unprivileged_userns_clone` returns 0). You can fix this by either enabling unprivileged namespaces, or by making the `chrome-sandbox` Setuid.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 820 B

After

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 301 B

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 535 B

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 32 KiB

+1
View File
@@ -8,6 +8,7 @@ services:
- SERVER_LOCK=false # When true AND name/type/url are set, only username/password can be toggled - SERVER_LOCK=false # When true AND name/type/url are set, only username/password can be toggled
- SERVER_TYPE=jellyfin # the allowed types are: jellyfin, navidrome, subsonic. These values are case insensitive - SERVER_TYPE=jellyfin # the allowed types are: jellyfin, navidrome, subsonic. These values are case insensitive
- SERVER_URL=http://localhost:8096 # http://address:port or https://address:port - SERVER_URL=http://localhost:8096 # http://address:port or https://address:port
# - REMOTE_URL=http://share.localhost # Used for compatibility with external functionality, such as custom sharing URLs on Navidrome
- LEGACY_AUTHENTICATION=false # When SERVER_LOCK is true, sets the legacyauth flag for server authentication (true or false) - LEGACY_AUTHENTICATION=false # When SERVER_LOCK is true, sets the legacyauth flag for server authentication (true or false)
- ANALYTICS_DISABLED=false # Set to true to disable Umami analytics tracking - ANALYTICS_DISABLED=false # Set to true to disable Umami analytics tracking
ports: ports:
+129
View File
@@ -0,0 +1,129 @@
# Environment variables for settings (web / Docker)
These variables override app settings **on first run** when no persisted settings exist. They are injected via `settings.js` (from `settings.js.template`) and only apply to the **web** build.
**Format:** All values are strings; booleans use `true`/`false`, numbers are numeric strings. Leave unset or empty to use the default.
---
## General
| Setting | Default | Env variable | Available values / Description |
|-------------|---------|--------------|--------------------------------|
| `general.accent` | `rgb(53, 116, 252)` | `FS_GENERAL_ACCENT` | CSS `rgb(r, g, b)` string (e.g. `rgb(53, 116, 252)`). Invalid values are ignored. |
| `general.albumBackground` | `false` | `FS_GENERAL_ALBUM_BACKGROUND` | `true` / `false` — Show album background image. |
| `general.albumBackgroundBlur` | `3` | `FS_GENERAL_ALBUM_BACKGROUND_BLUR` | Blur amount for album background (number). |
| `general.artistBackground` | `true` | `FS_GENERAL_ARTIST_BACKGROUND` | `true` / `false` — Show artist background image. |
| `general.artistBackgroundBlur` | `3` | `FS_GENERAL_ARTIST_BACKGROUND_BLUR` | Blur amount for artist background (number). |
| `general.blurExplicitImages` | `false` | `FS_GENERAL_BLUR_EXPLICIT_IMAGES` | `true` / `false` — Blur explicit images. |
| `general.combinedLyricsAndVisualizer` | `false` | `FS_GENERAL_COMBINED_LYRICS_AND_VISUALIZER` | `true` / `false` — Combine lyrics and visualizer panel. |
| `general.enableGridMultiSelect` | `false` | `FS_GENERAL_ENABLE_GRID_MULTI_SELECT` | `true` / `false` — Enable multi-select in grid views. |
| `general.externalLinks` | `true` | `FS_GENERAL_EXTERNAL_LINKS` | `true` / `false` — Show external links in UI. |
| `general.followCurrentSong` | `true` | `FS_GENERAL_FOLLOW_CURRENT_SONG` | `true` / `false` — Follow current song in list. |
| `general.followSystemTheme` | `false` | `FS_GENERAL_FOLLOW_SYSTEM_THEME` | `true` / `false` — Use OS light/dark preference. |
| `general.homeFeature` | `true` | `FS_GENERAL_HOME_FEATURE` | `true` / `false` — Show home featured carousel. |
| `general.homeFeatureStyle` | `single` | `FS_GENERAL_HOME_FEATURE_STYLE` | `multiple` / `single` — Home featured carousel style. |
| `general.language` | `en` | `FS_GENERAL_LANGUAGE` | UI language code (e.g. `en`, `de`, `fr`). |
| `general.theme` | `defaultDark` | `FS_GENERAL_THEME` | One of: `ayuDark`, `ayuLight`, `catppuccinLatte`, `catppuccinMocha`, `defaultDark`, `defaultLight`, `dracula`, `githubDark`, `githubLight`, `glassyDark`, `gruvboxDark`, `gruvboxLight`, `highContrastDark`, `highContrastLight`, `materialDark`, `materialLight`, `monokai`, `nightOwl`, `nord`, `oneDark`, `rosePine`, `rosePineDawn`, `rosePineMoon`, `shadesOfPurple`, `solarizedDark`, `solarizedLight`, `tokyoNight`, `vscodeDarkPlus`, `vscodeLightPlus`. |
| `general.themeDark` | `defaultDark` | `FS_GENERAL_THEME_DARK` | Same as theme (used when system is dark). |
| `general.themeLight` | `defaultLight` | `FS_GENERAL_THEME_LIGHT` | Same as theme (used when system is light). |
| `general.lastfmApiKey` | *(empty)* | `FS_GENERAL_LASTFM_API_KEY` | Last.fm API key. |
| `general.lastFM` | `true` | `FS_GENERAL_LAST_FM` | `true` / `false` — Enable Last.fm. |
| `general.listenBrainz` | `true` | `FS_GENERAL_LISTEN_BRAINZ` | `true` / `false` — ListenBrainz links. |
| `general.musicBrainz` | `true` | `FS_GENERAL_MUSIC_BRAINZ` | `true` / `false` — MusicBrainz links. |
| `general.nativeAspectRatio` | `false` | `FS_GENERAL_NATIVE_ASPECT_RATIO` | `true` / `false` — Use native cover art aspect ratio. |
| `general.pathReplace` | *(empty)* | `FS_GENERAL_PATH_REPLACE` | Path pattern to replace (e.g. server path in Docker). |
| `general.pathReplaceWith` | *(empty)* | `FS_GENERAL_PATH_REPLACE_WITH` | Replacement path. |
| `general.playerbarOpenDrawer` | `false` | `FS_GENERAL_PLAYERBAR_OPEN_DRAWER` | `true` / `false` — Open queue/lyrics as drawer from player bar. |
| `general.primaryShade` | `6` | `FS_GENERAL_PRIMARY_SHADE` | Mantine primary shade 09 (number). |
| `general.qobuz` | `true` | `FS_GENERAL_QOBUZ` | `true` / `false` — Qobuz links. |
| `general.resume` | `true` | `FS_GENERAL_RESUME` | `true` / `false` — Resume playback on load. |
| `general.showLyricsInSidebar` | `true` | `FS_GENERAL_SHOW_LYRICS_IN_SIDEBAR` | `true` / `false` — Show lyrics in sidebar. |
| `general.showRatings` | `true` | `FS_GENERAL_SHOW_RATINGS` | `true` / `false` — Show star ratings. |
| `general.showVisualizerInSidebar` | `true` | `FS_GENERAL_SHOW_VISUALIZER_IN_SIDEBAR` | `true` / `false` — Show visualizer in sidebar. |
| `general.sidebarCollapsedNavigation` | `true` | `FS_GENERAL_SIDEBAR_COLLAPSED_NAVIGATION` | `true` / `false` — Start with collapsed sidebar nav. |
| `general.sidebarCollapseShared` | `false` | `FS_GENERAL_SIDEBAR_COLLAPSE_SHARED` | `true` / `false` — Share sidebar collapse state. |
| `general.sidebarPlaylistList` | `true` | `FS_GENERAL_SIDEBAR_PLAYLIST_LIST` | `true` / `false` — Show playlist list in sidebar. |
| `general.sidebarPlaylistSorting` | `false` | `FS_GENERAL_SIDEBAR_PLAYLIST_SORTING` | `true` / `false` — Enable playlist sorting in sidebar. |
| `general.sideQueueType` | `sideQueue` | `FS_GENERAL_SIDE_QUEUE_TYPE` | `sideDrawerQueue` / `sideQueue` — Side play queue style. |
| `general.sideQueueLayout` | `horizontal` | `FS_GENERAL_SIDE_QUEUE_LAYOUT` | `horizontal` / `vertical` — Attached side queue layout orientation. |
| `general.useThemeAccentColor` | `false` | `FS_GENERAL_USE_THEME_ACCENT_COLOR` | `true` / `false` — Use themes accent color instead of custom. |
| `general.useThemePrimaryShade` | `true` | `FS_GENERAL_USE_THEME_PRIMARY_SHADE` | `true` / `false` — Use themes primary shade. |
| `general.zoomFactor` | `100` | `FS_GENERAL_ZOOM_FACTOR` | UI zoom percentage (number). |
---
## Playback
| Setting path | Default | Env variable | Available values / Description |
|-------------|---------|--------------|--------------------------------|
| `playback.mediaSession` | `false` | `FS_PLAYBACK_MEDIA_SESSION` | `true` / `false` — Media Session API (e.g. browser/media keys). |
| `playback.webAudio` | `true` | `FS_PLAYBACK_WEB_AUDIO` | `true` / `false` — Use Web Audio for playback. |
| `playback.audioFadeOnStatusChange` | `true` | `FS_PLAYBACK_AUDIO_FADE_ON_STATUS_CHANGE` | `true` / `false` — Fade on play/pause. |
| `playback.preservePitch` | `true` | `FS_PLAYBACK_PRESERVE_PITCH` | `true` / `false` — Preserve pitch when changing speed. |
| `playback.scrobble.enabled` | `true` | `FS_PLAYBACK_SCROBBLE_ENABLED` | `true` / `false` — Enable scrobbling. |
| `playback.scrobble.notify` | `false` | `FS_PLAYBACK_SCROBBLE_NOTIFY` | `true` / `false` — Scrobble notifications. |
| `playback.scrobble.scrobbleAtDuration` | `240` | `FS_PLAYBACK_SCROBBLE_AT_DURATION` | Seconds of playback before scrobble. |
| `playback.scrobble.scrobbleAtPercentage` | `75` | `FS_PLAYBACK_SCROBBLE_AT_PERCENTAGE` | Percentage of track before scrobble. |
| `playback.transcode.enabled` | `false` | `FS_PLAYBACK_TRANSCODE_ENABLED` | `true` / `false` — Enable transcoding. |
---
## Discord
| Setting path | Default | Env variable | Available values / Description |
|-------------|---------|--------------|--------------------------------|
| `discord.enabled` | `false` | `FS_DISCORD_ENABLED` | `true` / `false` — Discord rich presence. |
| `discord.clientId` | *(built-in)* | `FS_DISCORD_CLIENT_ID` | Custom Discord application ID. |
| `discord.displayType` | `feishin` | `FS_DISCORD_DISPLAY_TYPE` | `artist` / `feishin` / `song`. |
| `discord.linkType` | `none` | `FS_DISCORD_LINK_TYPE` | `last_fm` / `musicbrainz` / `musicbrainz_last_fm` / `none`. |
| `discord.showAsListening` | `false` | `FS_DISCORD_SHOW_AS_LISTENING` | `true` / `false`. |
| `discord.showPaused` | `true` | `FS_DISCORD_SHOW_PAUSED` | `true` / `false` — Show paused state. |
| `discord.showServerImage` | `false` | `FS_DISCORD_SHOW_SERVER_IMAGE` | `true` / `false`. |
| `discord.showStateIcon` | `true` | `FS_DISCORD_SHOW_STATE_ICON` | `true` / `false`. |
---
## Lyrics
| Setting path | Default | Env variable | Available values / Description |
|-------------|---------|--------------|--------------------------------|
| `lyrics.fetch` | `true` | `FS_LYRICS_FETCH` | `true` / `false` — Fetch lyrics. |
| `lyrics.follow` | `true` | `FS_LYRICS_FOLLOW` | `true` / `false` — Follow current line. |
| `lyrics.delayMs` | `0` | `FS_LYRICS_DELAY_MS` | Sync delay in milliseconds. |
| `lyrics.preferLocalLyrics` | `true` | `FS_LYRICS_PREFER_LOCAL` | `true` / `false` — Prefer local lyric files. |
| `lyrics.showMatch` | `true` | `FS_LYRICS_SHOW_MATCH` | `true` / `false`. |
| `lyrics.showProvider` | `true` | `FS_LYRICS_SHOW_PROVIDER` | `true` / `false`. |
| `lyrics.enableAutoTranslation` | `false` | `FS_LYRICS_ENABLE_AUTO_TRANSLATION` | `true` / `false`. |
| `lyrics.translationApiKey` | *(empty)* | `FS_LYRICS_TRANSLATION_API_KEY` | API key for lyric translation. |
| `lyrics.translationTargetLanguage` | `en` | `FS_LYRICS_TRANSLATION_TARGET_LANGUAGE` | Target language code. |
| `lyrics.alignment` | `center` | `FS_LYRICS_ALIGNMENT` | `center` / `left` / `right`. |
---
## Auto DJ
| Setting path | Default | Env variable | Available values / Description |
|-------------|---------|--------------|--------------------------------|
| `autoDJ.enabled` | `false` | `FS_AUTO_DJ_ENABLED` | `true` / `false`. |
| `autoDJ.itemCount` | `5` | `FS_AUTO_DJ_ITEM_COUNT` | Number of items to add. |
| `autoDJ.timing` | `1` | `FS_AUTO_DJ_TIMING` | Timing value (number). |
---
## CSS
| Setting path | Default | Env variable | Available values / Description |
|-------------|---------|--------------|--------------------------------|
| `css.content` | *(empty)* | `FS_CSS_CONTENT` | Custom CSS string (sanitized like in-app custom CSS). Set `FS_CSS_ENABLED=true` to apply. |
| `css.enabled` | `false` | `FS_CSS_ENABLED` | `true` / `false` — Enable custom CSS. |
---
## Font
| Setting path | Default | Env variable | Available values / Description |
|-------------|---------|--------------|--------------------------------|
| `font.type` | `builtIn` | `FS_FONT_TYPE` | `builtIn` / `system` / `custom`. |
| `font.builtIn` | `Inter` | `FS_FONT_BUILT_IN` | Built-in font name. |
| `font.system` | *(empty)* | `FS_FONT_SYSTEM` | System font name (when type is `system`). |
+17 -8
View File
@@ -32,17 +32,23 @@ nsis:
mac: mac:
target: target:
target: default - target: dmg
arch: arch:
- arm64 - arm64
- x64 - x64
icon: assets/icons/icon.icns - target: zip
arch:
- arm64
- x64
icon: media/feishin.icon
type: distribution type: distribution
hardenedRuntime: true hardenedRuntime: false
entitlements: assets/entitlements.mac.plist identity: '-'
entitlementsInherit: assets/entitlements.mac.plist
gatekeeperAssess: false gatekeeperAssess: false
notarize: false notarize: false
extendInfo:
NSAudioCaptureUsageDescription: "System audio access is required for mpv visualizer capture in Feishin"
NSLocalNetworkUsageDescription: 'Local network is necessary for accessing servers hosted on the same system as Feishin'
dmg: dmg:
contents: [{ x: 130, y: 220 }, { x: 410, y: 220, type: link, path: /Applications }] contents: [{ x: 130, y: 220 }, { x: 410, y: 220, type: link, path: /Applications }]
@@ -56,6 +62,9 @@ linux:
icon: assets/icons/icon.png icon: assets/icons/icon.png
artifactName: ${productName}-${os}-${arch}.${ext} artifactName: ${productName}-${os}-${arch}.${ext}
toolsets:
appimage: '1.0.2'
npmRebuild: false npmRebuild: false
publish: publish:
+17 -8
View File
@@ -32,17 +32,23 @@ nsis:
mac: mac:
target: target:
target: default - target: dmg
arch: arch:
- arm64 - arm64
- x64 - x64
icon: assets/icons/icon.icns - target: zip
arch:
- arm64
- x64
icon: media/feishin.icon
type: distribution type: distribution
hardenedRuntime: true hardenedRuntime: false
entitlements: assets/entitlements.mac.plist identity: '-'
entitlementsInherit: assets/entitlements.mac.plist
gatekeeperAssess: false gatekeeperAssess: false
notarize: false notarize: false
extendInfo:
NSAudioCaptureUsageDescription: "System audio access is required for mpv visualizer capture in Feishin"
NSLocalNetworkUsageDescription: 'Local network is necessary for accessing servers hosted on the same system as Feishin'
dmg: dmg:
contents: [{ x: 130, y: 220 }, { x: 410, y: 220, type: link, path: /Applications }] contents: [{ x: 130, y: 220 }, { x: 410, y: 220, type: link, path: /Applications }]
@@ -56,6 +62,9 @@ linux:
icon: assets/icons/icon.png icon: assets/icons/icon.png
artifactName: ${productName}-${os}-${arch}.${ext} artifactName: ${productName}-${os}-${arch}.${ext}
toolsets:
appimage: '1.0.2'
npmRebuild: false npmRebuild: false
publish: publish:
provider: github provider: github
+18 -8
View File
@@ -32,17 +32,23 @@ nsis:
mac: mac:
target: target:
target: default - target: dmg
arch: arch:
- arm64 - arm64
- x64 - x64
icon: assets/icons/icon.icns - target: zip
arch:
- arm64
- x64
icon: media/feishin.icon
type: distribution type: distribution
hardenedRuntime: true hardenedRuntime: false
entitlements: assets/entitlements.mac.plist identity: '-'
entitlementsInherit: assets/entitlements.mac.plist
gatekeeperAssess: false gatekeeperAssess: false
notarize: false notarize: false
extendInfo:
NSAudioCaptureUsageDescription: 'System audio access is required for mpv visualizer capture in Feishin'
NSLocalNetworkUsageDescription: 'Local network is necessary for accessing servers hosted on the same system as Feishin'
dmg: dmg:
contents: [{ x: 130, y: 220 }, { x: 410, y: 220, type: link, path: /Applications }] contents: [{ x: 130, y: 220 }, { x: 410, y: 220, type: link, path: /Applications }]
@@ -56,7 +62,11 @@ linux:
icon: assets/icons/icon.png icon: assets/icons/icon.png
artifactName: ${productName}-${os}-${arch}.${ext} artifactName: ${productName}-${os}-${arch}.${ext}
toolsets:
appimage: '1.0.2'
npmRebuild: false npmRebuild: false
afterAllArtifactBuild: scripts/after-all-artifact-build.mjs
publish: publish:
provider: github provider: github
owner: jeffvli owner: jeffvli
+3 -2
View File
@@ -1,10 +1,11 @@
import react from '@vitejs/plugin-react';
import { externalizeDepsPlugin, UserConfig } from 'electron-vite'; import { externalizeDepsPlugin, UserConfig } from 'electron-vite';
import { resolve } from 'path'; import { resolve } from 'path';
import conditionalImportPlugin from 'vite-plugin-conditional-import'; import conditionalImportPlugin from 'vite-plugin-conditional-import';
import dynamicImportPlugin from 'vite-plugin-dynamic-import'; import dynamicImportPlugin from 'vite-plugin-dynamic-import';
import { ViteEjsPlugin } from 'vite-plugin-ejs'; import { ViteEjsPlugin } from 'vite-plugin-ejs';
import { createReactPlugin } from './vite.react-plugin';
const currentOSEnv = process.platform; const currentOSEnv = process.platform;
const electronRendererTarget = 'chrome87'; const electronRendererTarget = 'chrome87';
@@ -64,7 +65,7 @@ const config: UserConfig = {
localsConvention: 'camelCase', localsConvention: 'camelCase',
}, },
}, },
plugins: [react(), ViteEjsPlugin({ web: false })], plugins: [createReactPlugin(), ViteEjsPlugin({ web: false })],
resolve: { resolve: {
alias: { alias: {
'/@/i18n': resolve('src/i18n'), '/@/i18n': resolve('src/i18n'),
+1 -1
View File
@@ -25,7 +25,7 @@ export default tseslint.config(
'react-refresh': eslintPluginReactRefresh, 'react-refresh': eslintPluginReactRefresh,
}, },
rules: { rules: {
...eslintPluginReactHooks.configs.recommended.rules, ...eslintPluginReactHooks.configs['recommended-latest'].rules,
...eslintPluginReactRefresh.configs.vite.rules, ...eslintPluginReactRefresh.configs.vite.rules,
'@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-duplicate-enum-values': 'off', '@typescript-eslint/no-duplicate-enum-values': 'off',
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512"><g style="display:inline" transform="translate(-53.452 -43.352)scale(1.11813)"><circle cx="256" cy="240.312" r="21.5" style="opacity:1;fill:#000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.19597;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke;filter:url(#filter249)"/><path d="M220.85 277.951 183.5 315.6l36 36.1 20-19.7s5.856-6.2 16.5-6.2 16.5 6.2 16.5 6.2l20 19.7 36-36.1-37.35-37.649A51.5 51.5 0 0 1 256 291.812a51.5 51.5 0 0 1-35.15-13.86" style="opacity:1;fill:#000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter249)"/><path d="M256 145.4a25.7 25.7 0 0 0-18.229 7.551L66.97 323.47A25.42 25.42 0 0 0 59.5 341.5c0 14.083 11.417 25.5 25.5 25.5a25.42 25.42 0 0 0 18.031-7.469l103.895-103.597a51.5 51.5 0 0 1-2.426-15.621 51.5 51.5 0 0 1 51.5-51.5 51.5 51.5 0 0 1 51.5 51.5 51.5 51.5 0 0 1-2.426 15.62L408.97 359.532A25.42 25.42 0 0 0 427 367c14.083 0 25.5-11.417 25.5-25.5a25.42 25.42 0 0 0-7.469-18.031L274.23 152.95a25.7 25.7 0 0 0-18.229-7.55" style="display:inline;opacity:1;fill:#000;fill-opacity:1;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;paint-order:markers fill stroke;filter:url(#filter249)"/></g></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+202
View File
@@ -0,0 +1,202 @@
{
"fill-specializations" : [
{
"value" : {
"linear-gradient" : [
"display-p3:0.87416,0.87416,0.87416,1.00000",
"display-p3:0.99575,0.99575,0.99575,1.00000"
],
"orientation" : {
"start" : {
"x" : 0.5,
"y" : 1
},
"stop" : {
"x" : 0.5,
"y" : 0.3
}
}
}
},
{
"appearance" : "dark",
"value" : "system-dark"
}
],
"groups" : [
{
"blend-mode-specializations" : [
{
"appearance" : "tinted",
"value" : "normal"
}
],
"blur-material-specializations" : [
{
"value" : 0.7
},
{
"appearance" : "dark",
"value" : 0.7
},
{
"appearance" : "tinted",
"value" : null
}
],
"hidden" : false,
"layers" : [
{
"blend-mode-specializations" : [
{
"appearance" : "tinted",
"value" : "normal"
}
],
"fill-specializations" : [
{
"value" : {
"solid" : "extended-gray:0.00000,1.00000"
}
},
{
"appearance" : "dark",
"value" : {
"linear-gradient" : [
"display-p3:0.78674,0.78674,0.78674,1.00000",
"display-p3:0.87416,0.87416,0.87416,1.00000"
],
"orientation" : {
"start" : {
"x" : 0.5,
"y" : 1
},
"stop" : {
"x" : 0.5,
"y" : 0
}
}
}
},
{
"appearance" : "tinted",
"value" : {
"solid" : "gray:1.00000,1.00000"
}
}
],
"glass-specializations" : [
{
"value" : true
},
{
"appearance" : "dark",
"value" : true
},
{
"appearance" : "tinted",
"value" : true
}
],
"hidden" : false,
"image-name" : "feishin.svg",
"name" : "feishin",
"opacity-specializations" : [
{
"value" : 1
},
{
"appearance" : "tinted",
"value" : 1
}
],
"position" : {
"scale" : 0.79,
"translation-in-points" : [
18,
-2
]
}
}
],
"lighting-specializations" : [
{
"value" : "individual"
},
{
"appearance" : "tinted",
"value" : "combined"
}
],
"position" : {
"scale" : 2.2,
"translation-in-points" : [
0,
0
]
},
"shadow-specializations" : [
{
"value" : {
"kind" : "neutral",
"opacity" : 1
}
},
{
"appearance" : "dark",
"value" : {
"kind" : "layer-color",
"opacity" : 0.5
}
},
{
"appearance" : "tinted",
"value" : {
"kind" : "neutral",
"opacity" : 1
}
}
],
"specular-specializations" : [
{
"value" : false
},
{
"appearance" : "dark",
"value" : false
},
{
"appearance" : "tinted",
"value" : true
}
],
"translucency-specializations" : [
{
"value" : {
"enabled" : true,
"value" : 0.29
}
},
{
"appearance" : "dark",
"value" : {
"enabled" : false,
"value" : 0.29
}
},
{
"appearance" : "tinted",
"value" : {
"enabled" : true,
"value" : 0.5
}
}
]
}
],
"supported-platforms" : {
"squares" : [
"macOS"
]
}
}
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 214 KiB

BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

+104
View File
@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="512"
height="512"
viewBox="0 0 512 512"
version="1.1"
id="svg1"
xml:space="preserve"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1"><linearGradient
id="linearGradient1"><stop
style="stop-color:#dfdfdf;stop-opacity:1;"
offset="0"
id="stop1" /><stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop2" /></linearGradient><filter
style="color-interpolation-filters:sRGB"
id="filter249"
x="-0.61395349"
y="-0.61395349"
width="2.227907"
height="2.5069767"><feFlood
result="flood"
in="SourceGraphic"
flood-opacity="0.498039"
flood-color="rgb(0,0,0)"
id="feFlood247" /><feGaussianBlur
result="blur"
in="SourceGraphic"
stdDeviation="1.000000"
id="feGaussianBlur247" /><feOffset
result="offset"
in="blur"
dx="0.000000"
dy="2"
id="feOffset247" /><feComposite
result="comp1"
operator="in"
in="flood"
in2="offset"
id="feComposite248" /><feComposite
result="fbSourceGraphic"
operator="over"
in="SourceGraphic"
id="feComposite249"
in2="comp1" /><feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix122" /><feFlood
id="feFlood122"
result="flood"
in="fbSourceGraphic"
flood-opacity="0.196078"
flood-color="rgb(0,0,0)" /><feGaussianBlur
id="feGaussianBlur122"
result="blur"
in="fbSourceGraphic"
stdDeviation="10.000000" /><feOffset
id="feOffset122"
result="offset"
in="blur"
dx="0.000000"
dy="10.000000" /><feComposite
id="feComposite122"
result="comp1"
operator="in"
in="flood"
in2="offset" /><feComposite
id="feComposite123"
result="comp2"
operator="over"
in="fbSourceGraphic"
in2="comp1" /></filter><linearGradient
xlink:href="#linearGradient1"
id="linearGradient2"
x1="256"
y1="0"
x2="256"
y2="512"
gradientUnits="userSpaceOnUse" /></defs><g
id="layer1"
style="display:inline"><circle
style="display:inline;fill:url(#linearGradient2);stroke-width:25;stroke-linecap:round;stroke-linejoin:round;paint-order:markers fill stroke"
id="background"
cx="256"
cy="256"
r="256" /><circle
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.19597;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke;filter:url(#filter249)"
id="dot"
cx="256"
cy="240.31155"
r="21.5" /><path
id="bottom"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter249)"
d="M 220.84961,277.95117 183.5,315.59961 219.5,351.69922 239.5,332 c 0,0 5.85615,-6.19922 16.5,-6.19922 10.64385,0 16.5,6.19922 16.5,6.19922 l 20,19.69922 36,-36.09961 -37.34961,-37.64844 A 51.5,51.5 0 0 1 256,291.8125 51.5,51.5 0 0 1 220.84961,277.95117 Z" /><path
id="main"
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;paint-order:markers fill stroke;filter:url(#filter249)"
d="m 256,145.40039 c -7.11895,0 -13.56326,2.88552 -18.22852,7.55078 L 66.96875,323.46875 C 62.354158,328.08334 59.5,334.45837 59.5,341.5 c 0,14.08326 11.416739,25.5 25.5,25.5 7.04163,0 13.41666,-2.85416 18.03125,-7.46875 L 206.92578,255.93359 A 51.5,51.5 0 0 1 204.5,240.3125 a 51.5,51.5 0 0 1 51.5,-51.5 51.5,51.5 0 0 1 51.5,51.5 51.5,51.5 0 0 1 -2.42578,15.62109 L 408.96875,359.53125 C 413.58334,364.14585 419.95837,367 427,367 c 14.08326,0 25.5,-11.41674 25.5,-25.5 0,-7.04163 -2.85415,-13.41666 -7.46875,-18.03125 L 274.22852,152.95117 C 269.56326,148.2859 263.11895,145.40039 256,145.40039 Z" /></g></svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

+3
View File
@@ -1,5 +1,6 @@
server { server {
listen 9180; listen 9180;
listen [::]:9180;
sendfile on; sendfile on;
default_type application/octet-stream; default_type application/octet-stream;
@@ -19,9 +20,11 @@ server {
location ${PUBLIC_PATH}settings.js { location ${PUBLIC_PATH}settings.js {
alias /etc/nginx/conf.d/settings.js; alias /etc/nginx/conf.d/settings.js;
add_header Cache-Control "no-store";
} }
location ${PUBLIC_PATH}/settings.js { location ${PUBLIC_PATH}/settings.js {
alias /etc/nginx/conf.d/settings.js; alias /etc/nginx/conf.d/settings.js;
add_header Cache-Control "no-store";
} }
} }
-18321
View File
File diff suppressed because it is too large Load Diff
+79 -76
View File
@@ -1,6 +1,6 @@
{ {
"name": "feishin", "name": "feishin",
"version": "1.5.0", "version": "1.11.0",
"description": "A modern self-hosted music player.", "description": "A modern self-hosted music player.",
"keywords": [ "keywords": [
"subsonic", "subsonic",
@@ -31,36 +31,36 @@
"i18next": "i18next -c src/i18n/i18next-parser.config.js", "i18next": "i18next -c src/i18n/i18next-parser.config.js",
"postinstall": "electron-builder install-app-deps", "postinstall": "electron-builder install-app-deps",
"lint": "pnpm run typecheck && pnpm run lint-code && pnpm run lint-styles", "lint": "pnpm run typecheck && pnpm run lint-code && pnpm run lint-styles",
"lint:fix": "pnpm run lint-code:fix && pnpm run lint-styles:fix",
"lint-code": "eslint --max-warnings=0 --cache .", "lint-code": "eslint --max-warnings=0 --cache .",
"lint-code:fix": "eslint --cache --fix .", "lint-code:fix": "eslint --cache --fix .",
"lint-styles": "stylelint --max-warnings=0 'src/**/*.{css,scss}'", "lint-styles": "stylelint --max-warnings=0 'src/**/*.{css,scss}'",
"lint-styles:fix": "stylelint 'src/**/*.{css,scss}' --fix", "lint-styles:fix": "stylelint 'src/**/*.{css,scss}' --fix",
"lint:fix": "pnpm run lint-code:fix && pnpm run lint-styles:fix",
"package": "pnpm run build && electron-builder", "package": "pnpm run build && electron-builder",
"package:dev": "pnpm run build && electron-builder --dir", "package:dev": "pnpm run build && electron-builder --dir",
"package:linux": "pnpm run build && electron-builder --linux", "package:linux": "pnpm run build && electron-builder --linux",
"package:linux-arm64:pr": "pnpm run build && electron-builder --linux --arm64 --publish never",
"package:linux:pr": "pnpm run build && electron-builder --linux --publish never", "package:linux:pr": "pnpm run build && electron-builder --linux --publish never",
"package:linux-arm64:pr": "pnpm run build && electron-builder --linux --arm64 --publish never",
"package:mac": "pnpm run build && electron-builder --mac", "package:mac": "pnpm run build && electron-builder --mac",
"package:mac:pr": "pnpm run build && electron-builder --mac --publish never", "package:mac:pr": "pnpm run build && electron-builder --mac --publish never",
"package:win": "pnpm run build && electron-builder --win", "package:win": "pnpm run build && electron-builder --win",
"package:win-arm64:pr": "pnpm run build && electron-builder --win --arm64 --publish never",
"package:win:pr": "pnpm run build && electron-builder --win --publish never", "package:win:pr": "pnpm run build && electron-builder --win --publish never",
"package:win-arm64:pr": "pnpm run build && electron-builder --win --arm64 --publish never",
"publish:linux": "pnpm run build && electron-builder --publish always --linux", "publish:linux": "pnpm run build && electron-builder --publish always --linux",
"publish:linux:alpha": "pnpm run build && electron-builder --config electron-builder-alpha.yml --publish always --linux",
"publish:linux:beta": "pnpm run build && electron-builder --config electron-builder-beta.yml --publish always --linux",
"publish:linux-arm64": "pnpm run build && electron-builder --publish always --linux --arm64", "publish:linux-arm64": "pnpm run build && electron-builder --publish always --linux --arm64",
"publish:linux-arm64:alpha": "pnpm run build && electron-builder --config electron-builder-alpha.yml --publish always --linux --arm64", "publish:linux-arm64:alpha": "pnpm run build && electron-builder --config electron-builder-alpha.yml --publish always --linux --arm64",
"publish:linux-arm64:beta": "pnpm run build && electron-builder --config electron-builder-beta.yml --publish always --linux --arm64", "publish:linux-arm64:beta": "pnpm run build && electron-builder --config electron-builder-beta.yml --publish always --linux --arm64",
"publish:linux:alpha": "pnpm run build && electron-builder --config electron-builder-alpha.yml --publish always --linux",
"publish:linux:beta": "pnpm run build && electron-builder --config electron-builder-beta.yml --publish always --linux",
"publish:mac": "pnpm run build && electron-builder --publish always --mac", "publish:mac": "pnpm run build && electron-builder --publish always --mac",
"publish:mac:alpha": "pnpm run build && electron-builder --config electron-builder-alpha.yml --publish always --mac", "publish:mac:alpha": "pnpm run build && electron-builder --config electron-builder-alpha.yml --publish always --mac",
"publish:mac:beta": "pnpm run build && electron-builder --config electron-builder-beta.yml --publish always --mac", "publish:mac:beta": "pnpm run build && electron-builder --config electron-builder-beta.yml --publish always --mac",
"publish:win": "pnpm run build && electron-builder --publish always --win", "publish:win": "pnpm run build && electron-builder --publish always --win",
"publish:win:alpha": "pnpm run build && electron-builder --config electron-builder-alpha.yml --publish always --win",
"publish:win:beta": "pnpm run build && electron-builder --config electron-builder-beta.yml --publish always --win",
"publish:win-arm64": "pnpm run build && electron-builder --publish always --win --arm64", "publish:win-arm64": "pnpm run build && electron-builder --publish always --win --arm64",
"publish:win-arm64:alpha": "pnpm run build && electron-builder --config electron-builder-alpha.yml --publish always --win --arm64", "publish:win-arm64:alpha": "pnpm run build && electron-builder --config electron-builder-alpha.yml --publish always --win --arm64",
"publish:win-arm64:beta": "pnpm run build && electron-builder --config electron-builder-beta.yml --publish always --win --arm64", "publish:win-arm64:beta": "pnpm run build && electron-builder --config electron-builder-beta.yml --publish always --win --arm64",
"publish:win:alpha": "pnpm run build && electron-builder --config electron-builder-alpha.yml --publish always --win",
"publish:win:beta": "pnpm run build && electron-builder --config electron-builder-beta.yml --publish always --win",
"start": "electron-vite preview", "start": "electron-vite preview",
"typecheck": "pnpm run typecheck:node && pnpm run typecheck:web", "typecheck": "pnpm run typecheck:node && pnpm run typecheck:web",
"typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false", "typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
@@ -68,120 +68,123 @@
"version": "pnpm version --no-git-tag-version", "version": "pnpm version --no-git-tag-version",
"postversion": "node ./scripts/update-app-stream.mjs" "postversion": "node ./scripts/update-app-stream.mjs"
}, },
"resolutions": {
"react-router": "7.14.0",
"xml2js": "0.5.0"
},
"dependencies": { "dependencies": {
"@atlaskit/pragmatic-drag-and-drop": "1.7.7", "@atlaskit/pragmatic-drag-and-drop": "1.7.7",
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.2", "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.5",
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.1.0", "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.1.0",
"@electron-toolkit/preload": "^3.0.1", "@electron-toolkit/preload": "^3.0.2",
"@electron-toolkit/utils": "^4.0.0", "@electron-toolkit/utils": "^4.0.0",
"@mantine/colors-generator": "^8.3.8", "@mantine/colors-generator": "^9.1.1",
"@mantine/core": "^8.3.8", "@mantine/core": "^9.1.1",
"@mantine/dates": "^8.3.8", "@mantine/dates": "^9.1.1",
"@mantine/form": "^8.3.8", "@mantine/form": "^9.1.1",
"@mantine/hooks": "^8.3.8", "@mantine/hooks": "^9.1.1",
"@mantine/modals": "^8.3.8", "@mantine/modals": "^9.1.1",
"@mantine/notifications": "^8.3.8", "@mantine/notifications": "^9.1.1",
"@radix-ui/react-context-menu": "^2.2.16", "@radix-ui/react-context-menu": "^2.2.16",
"@tanstack/react-query": "^5.90.9", "@tanstack/react-query": "^5.96.2",
"@tanstack/react-query-devtools": "^5.90.2", "@tanstack/react-query-devtools": "^5.96.2",
"@tanstack/react-query-persist-client": "^5.90.11", "@tanstack/react-query-persist-client": "^5.96.2",
"@ts-rest/core": "^3.52.1", "@ts-rest/core": "^3.52.1",
"@wavesurfer/react": "^1.0.11", "@wavesurfer/react": "^1.0.12",
"@xhayper/discord-rpc": "^1.3.0", "@xhayper/discord-rpc": "^1.3.3",
"audiomotion-analyzer": "^4.5.1", "audiomotion-analyzer": "^4.5.4",
"axios": "^1.13.2", "axios": "^1.14.0",
"butterchurn": "^3.0.0-beta.5", "butterchurn": "3.0.0-beta.5",
"butterchurn-presets": "^3.0.0-beta.4", "butterchurn-presets": "3.0.0-beta.4",
"cheerio": "^1.1.2", "cheerio": "^1.2.0",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"cmdk": "^1.1.1", "cmdk": "^1.1.1",
"dayjs": "^1.11.19", "dayjs": "^1.11.20",
"dompurify": "^3.3.0", "dompurify": "^3.3.3",
"electron-debug": "^3.2.0", "electron-debug": "^3.2.0",
"electron-localshortcut": "^3.2.1", "electron-localshortcut": "^3.2.1",
"electron-log": "^5.4.3", "electron-log": "^5.4.3",
"electron-store": "^8.2.0", "electron-store": "^8.2.0",
"electron-updater": "^6.6.2", "electron-updater": "^6.8.3",
"fast-average-color": "^9.5.0", "fast-average-color": "9.5.0",
"fast-xml-parser": "^5.3.2", "fast-xml-parser": "^5.5.10",
"format-duration": "^3.0.2", "format-duration": "^3.0.2",
"fuse.js": "^7.1.0", "fuse.js": "^7.2.0",
"i18next": "^25.6.2", "i18next": "^25.10.10",
"icecast-metadata-stats": "^0.1.12", "icecast-metadata-stats": "^0.1.12",
"idb-keyval": "^6.2.2", "idb-keyval": "^6.2.2",
"immer": "^10.2.0", "immer": "^10.2.0",
"is-electron": "^2.2.2", "is-electron": "^2.2.2",
"lodash": "^4.17.21", "lodash": "^4.18.1",
"md5": "^2.3.0", "md5": "^2.3.0",
"motion": "^12.23.24", "motion": "^12.38.0",
"mpris-service": "^2.1.2", "mpris-service": "^2.1.2",
"nanoid": "^3.3.11", "nanoid": "^3.3.11",
"node-mpv": "github:jeffvli/Node-MPV#32b4d64395289ad710c41d481d2707a7acfc228f", "node-mpv": "github:jeffvli/Node-MPV#32b4d64395289ad710c41d481d2707a7acfc228f",
"nuqs": "^2.7.1", "overlayscrollbars": "^2.14.0",
"overlayscrollbars": "^2.11.1",
"overlayscrollbars-react": "^0.5.6", "overlayscrollbars-react": "^0.5.6",
"qs": "^6.14.1", "qs": "^6.15.0",
"react": "^19.1.0", "react": "^19.2.4",
"react-call": "^1.8.1", "react-call": "^1.8.2",
"react-dom": "^19.1.0", "react-dom": "^19.2.4",
"react-error-boundary": "^5.0.0", "react-error-boundary": "^5.0.0",
"react-i18next": "^16.3.3", "react-i18next": "^16.6.6",
"react-icons": "^5.5.0", "react-icons": "^5.6.0",
"react-image": "^4.1.0", "react-player": "^2.16.1",
"react-player": "^2.16.0", "react-router": "^7.14.0",
"react-router": "^7.9.6", "react-split-pane": "^3.2.0",
"react-split-pane": "^3.0.4",
"react-virtualized-auto-sizer": "^1.0.26", "react-virtualized-auto-sizer": "^1.0.26",
"react-window": "1.8.11", "react-window": "1.8.11",
"react-window-v2": "npm:react-window@^2.2.3", "react-window-v2": "npm:react-window@^2.2.7",
"semver": "^7.5.4", "semver": "^7.7.4",
"string-to-color": "^2.2.2", "string-to-color": "^2.2.2",
"wavesurfer.js": "^7.11.1", "wavesurfer.js": "^7.12.5",
"ws": "^8.18.2", "ws": "^8.20.0",
"zod": "^3.22.3", "zod": "^3.25.76",
"zustand": "^5.0.5" "zustand": "^5.0.12"
}, },
"devDependencies": { "devDependencies": {
"@electron-toolkit/eslint-config-prettier": "^3.0.0", "@electron-toolkit/eslint-config-prettier": "^3.0.0",
"@electron-toolkit/eslint-config-ts": "^3.0.0", "@electron-toolkit/eslint-config-ts": "^3.1.0",
"@electron-toolkit/tsconfig": "^2.0.0", "@electron-toolkit/tsconfig": "^2.0.0",
"@types/electron-localshortcut": "^3.1.0", "@types/electron-localshortcut": "^3.1.3",
"@types/lodash": "^4.17.18", "@types/lodash": "^4.17.24",
"@types/md5": "^2.3.5", "@types/md5": "^2.3.6",
"@types/node": "^24.10.1", "@types/node": "^24.12.2",
"@types/react": "^19.2.5", "@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"@types/react-window": "^1.8.8", "@types/react-window": "^1.8.8",
"@types/source-map-support": "^0.5.10", "@types/source-map-support": "^0.5.10",
"@types/ws": "^8.18.1", "@types/ws": "^8.18.1",
"@vitejs/plugin-react": "^5.1.1", "@vitejs/plugin-react": "^5.2.0",
"babel-plugin-react-compiler": "^1.0.0",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cross-env": "^10.1.0", "cross-env": "^10.1.0",
"electron": "^39.4.0", "electron": "^39.8.6",
"electron-builder": "^26.0.12", "electron-builder": "^26.8.2",
"electron-devtools-installer": "^4.0.0", "electron-devtools-installer": "^4.0.0",
"electron-vite": "^4.0.1", "electron-vite": "^4.0.1",
"eslint": "^9.24.0", "eslint": "^9.39.4",
"eslint-plugin-perfectionist": "^4.13.0", "eslint-plugin-perfectionist": "^4.15.1",
"eslint-plugin-prettier": "^5.4.0", "eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-react": "^7.37.5", "eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.4.24", "eslint-plugin-react-refresh": "^0.4.26",
"i18next-parser": "^9.3.0", "i18next-parser": "^9.4.0",
"postcss-preset-mantine": "^1.18.0", "postcss-preset-mantine": "^1.18.0",
"postcss-simple-vars": "^7.0.1", "postcss-simple-vars": "^7.0.1",
"prettier": "^3.6.2", "prettier": "^3.8.1",
"prettier-plugin-packagejson": "^2.5.19", "prettier-plugin-packagejson": "^2.5.22",
"stylelint": "^16.25.0", "stylelint": "^16.26.1",
"stylelint-config-css-modules": "^4.5.1", "stylelint-config-css-modules": "^4.6.0",
"stylelint-config-recess-order": "^7.4.0", "stylelint-config-recess-order": "^7.7.0",
"stylelint-config-standard": "^39.0.1", "stylelint-config-standard": "^39.0.1",
"typescript": "^5.8.3", "typescript": "^5.9.3",
"vite": "^7.2.2", "vite": "^7.3.1",
"vite-plugin-conditional-import": "^0.1.7", "vite-plugin-conditional-import": "^0.1.7",
"vite-plugin-dynamic-import": "^1.6.0", "vite-plugin-dynamic-import": "^1.6.0",
"vite-plugin-ejs": "^1.7.0", "vite-plugin-ejs": "^1.7.0",
"vite-plugin-pwa": "^1.1.0" "vite-plugin-pwa": "^1.2.0"
}, },
"pnpm": { "pnpm": {
"onlyBuiltDependencies": [ "onlyBuiltDependencies": [
+3082 -3061
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1,9 +1,9 @@
import react from '@vitejs/plugin-react';
import path from 'path'; import path from 'path';
import { defineConfig, normalizePath } from 'vite'; import { defineConfig, normalizePath } from 'vite';
import { ViteEjsPlugin } from 'vite-plugin-ejs'; import { ViteEjsPlugin } from 'vite-plugin-ejs';
import { version } from './package.json'; import { version } from './package.json';
import { createReactPlugin } from './vite.react-plugin';
export default defineConfig({ export default defineConfig({
build: { build: {
@@ -35,7 +35,7 @@ export default defineConfig({
}, },
}, },
plugins: [ plugins: [
react(), createReactPlugin(),
ViteEjsPlugin({ ViteEjsPlugin({
prod: process.env.NODE_ENV === 'production', prod: process.env.NODE_ENV === 'production',
root: normalizePath(path.resolve(__dirname, './src/remote')), root: normalizePath(path.resolve(__dirname, './src/remote')),
Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 32 KiB

+45
View File
@@ -0,0 +1,45 @@
import { execSync } from 'child_process';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
/**
* Electron-builder afterAllArtifactBuild hook
* Runs the app stream update script only for Linux builds
* Returns the metainfo file path to be included in published artifacts
*/
// This is not a typescript file, and is called by electron-builder, so we cannot use typescript features here.
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export default async function afterAllArtifactBuild(buildResult) {
// Check if this build includes Linux as a target
const isLinux = Array.from(buildResult.platformToTargets.keys()).some(
(platform) => platform.name === 'linux',
);
if (isLinux) {
const updateScriptPath = path.join(__dirname, 'update-app-stream.mjs');
const projectRoot = path.resolve(__dirname, '..');
const metainfoFile = path.resolve(projectRoot, 'org.jeffvli.feishin.metainfo.xml');
console.log('Running app stream update for Linux build...');
try {
execSync(`node ${updateScriptPath} --replace-if-version-missing`, {
cwd: projectRoot,
stdio: 'inherit',
});
// Return the metainfo file to be included in published artifacts
return [metainfoFile];
} catch (error) {
console.error('Failed to update app stream:', error.message);
throw error;
}
}
// Return empty array if not a Linux build
return [];
}
+32 -11
View File
@@ -3,30 +3,51 @@ import fs from 'fs';
import path from 'path'; import path from 'path';
const args = process.argv.slice(2); const args = process.argv.slice(2);
if (args.length > 3) {
console.error('Usage: node update-app-stream.js [package-file] [date] [metainfo-file]'); // Parse flags and positional arguments
const flags = args.filter((arg) => arg.startsWith('--'));
const positionalArgs = args.filter((arg) => !arg.startsWith('--'));
const replaceIfVersionMissing = flags.includes('--replace-if-version-missing');
if (positionalArgs.length > 3) {
console.error(
'Usage: node update-app-stream.js [package-file] [date] [metainfo-file] [--replace-if-version-missing]',
);
process.exit(1); process.exit(1);
} }
const packageFile = args[0] || path.resolve(process.cwd(), 'package.json'); const packageFile = positionalArgs[0] || path.resolve(process.cwd(), 'package.json');
const packageContent = fs.readFileSync(packageFile, 'utf8'); const packageContent = fs.readFileSync(packageFile, 'utf8');
const packageJson = JSON.parse(packageContent); const packageJson = JSON.parse(packageContent);
const version = packageJson.version; const version = packageJson.version;
const time = Math.floor((Date.parse(args[1]) || Date.now()) / 1000); const time = Math.floor((Date.parse(positionalArgs[1]) || Date.now()) / 1000);
const metainfoFile = args[2] || path.resolve(process.cwd(), 'org.jeffvli.feishin.metainfo.xml'); const metainfoFile =
positionalArgs[2] || path.resolve(process.cwd(), 'org.jeffvli.feishin.metainfo.xml');
const parser = new XMLParser({ ignoreAttributes: false }); const parser = new XMLParser({ ignoreAttributes: false });
const metainfoContent = fs.readFileSync(metainfoFile, 'utf8'); const metainfoContent = fs.readFileSync(metainfoFile, 'utf8');
const metainfo = parser.parse(metainfoContent); const metainfo = parser.parse(metainfoContent);
if (!metainfo.component.releases.release.find((release) => release['@_version'] === version)) { const newRelease = {
metainfo.component.releases.release.unshift({ '@_date': new Date(time * 1000).toISOString().split('T')[0],
'@_date': new Date(time * 1000).toISOString().split('T')[0], '@_type': version.includes('-') ? 'development' : 'stable',
'@_type': version.includes('-') ? 'development' : 'stable', '@_version': version,
'@_version': version, };
});
if (replaceIfVersionMissing) {
// Replace all releases with only the current version
metainfo.component.releases.release = [newRelease];
} else {
// Default behavior: add new release if it doesn't exist
const releaseExists =
metainfo.component.releases.release.findIndex(
(release) => release['@_version'] === version,
) !== -1;
if (!releaseExists) {
metainfo.component.releases.release.unshift(newRelease);
}
} }
const builder = new XMLBuilder({ format: true, ignoreAttributes: false, indentBy: ' ' }); const builder = new XMLBuilder({ format: true, ignoreAttributes: false, indentBy: ' ' });
+90 -1
View File
@@ -1 +1,90 @@
"use strict";window.SERVER_URL="${SERVER_URL}";window.SERVER_NAME="${SERVER_NAME}";window.SERVER_TYPE="${SERVER_TYPE}";window.SERVER_LOCK="${SERVER_LOCK}";window.LEGACY_AUTHENTICATION="${LEGACY_AUTHENTICATION}";window.ANALYTICS_DISABLED="${ANALYTICS_DISABLED}"; "use strict";
window.SERVER_URL = "${SERVER_URL}";
window.REMOTE_URL = "${REMOTE_URL}";
window.SERVER_NAME = "${SERVER_NAME}";
window.SERVER_TYPE = "${SERVER_TYPE}";
window.SERVER_LOCK = "${SERVER_LOCK}";
window.LEGACY_AUTHENTICATION = "${LEGACY_AUTHENTICATION}";
window.ANALYTICS_DISABLED = "${ANALYTICS_DISABLED}";
window.FS_GENERAL_ACCENT = "${FS_GENERAL_ACCENT}";
window.FS_GENERAL_ALBUM_BACKGROUND = "${FS_GENERAL_ALBUM_BACKGROUND}";
window.FS_GENERAL_ALBUM_BACKGROUND_BLUR = "${FS_GENERAL_ALBUM_BACKGROUND_BLUR}";
window.FS_GENERAL_ARTIST_BACKGROUND = "${FS_GENERAL_ARTIST_BACKGROUND}";
window.FS_GENERAL_ARTIST_BACKGROUND_BLUR = "${FS_GENERAL_ARTIST_BACKGROUND_BLUR}";
window.FS_GENERAL_BLUR_EXPLICIT_IMAGES = "${FS_GENERAL_BLUR_EXPLICIT_IMAGES}";
window.FS_GENERAL_COMBINED_LYRICS_AND_VISUALIZER = "${FS_GENERAL_COMBINED_LYRICS_AND_VISUALIZER}";
window.FS_GENERAL_ENABLE_GRID_MULTI_SELECT = "${FS_GENERAL_ENABLE_GRID_MULTI_SELECT}";
window.FS_GENERAL_EXTERNAL_LINKS = "${FS_GENERAL_EXTERNAL_LINKS}";
window.FS_GENERAL_FOLLOW_CURRENT_SONG = "${FS_GENERAL_FOLLOW_CURRENT_SONG}";
window.FS_GENERAL_FOLLOW_SYSTEM_THEME = "${FS_GENERAL_FOLLOW_SYSTEM_THEME}";
window.FS_GENERAL_HOME_FEATURE = "${FS_GENERAL_HOME_FEATURE}";
window.FS_GENERAL_HOME_FEATURE_STYLE = "${FS_GENERAL_HOME_FEATURE_STYLE}";
window.FS_GENERAL_LANGUAGE = "${FS_GENERAL_LANGUAGE}";
window.FS_GENERAL_LAST_FM = "${FS_GENERAL_LAST_FM}";
window.FS_GENERAL_LASTFM_API_KEY = "${FS_GENERAL_LASTFM_API_KEY}";
window.FS_GENERAL_LISTEN_BRAINZ = "${FS_GENERAL_LISTEN_BRAINZ}";
window.FS_GENERAL_MUSIC_BRAINZ = "${FS_GENERAL_MUSIC_BRAINZ}";
window.FS_GENERAL_NATIVE_ASPECT_RATIO = "${FS_GENERAL_NATIVE_ASPECT_RATIO}";
window.FS_GENERAL_PATH_REPLACE = "${FS_GENERAL_PATH_REPLACE}";
window.FS_GENERAL_PATH_REPLACE_WITH = "${FS_GENERAL_PATH_REPLACE_WITH}";
window.FS_GENERAL_PLAYERBAR_OPEN_DRAWER = "${FS_GENERAL_PLAYERBAR_OPEN_DRAWER}";
window.FS_GENERAL_PRIMARY_SHADE = "${FS_GENERAL_PRIMARY_SHADE}";
window.FS_GENERAL_QOBUZ = "${FS_GENERAL_QOBUZ}";
window.FS_GENERAL_RESUME = "${FS_GENERAL_RESUME}";
window.FS_GENERAL_SHOW_LYRICS_IN_SIDEBAR = "${FS_GENERAL_SHOW_LYRICS_IN_SIDEBAR}";
window.FS_GENERAL_SHOW_RATINGS = "${FS_GENERAL_SHOW_RATINGS}";
window.FS_GENERAL_SHOW_VISUALIZER_IN_SIDEBAR = "${FS_GENERAL_SHOW_VISUALIZER_IN_SIDEBAR}";
window.FS_GENERAL_SIDEBAR_COLLAPSED_NAVIGATION = "${FS_GENERAL_SIDEBAR_COLLAPSED_NAVIGATION}";
window.FS_GENERAL_SIDEBAR_COLLAPSE_SHARED = "${FS_GENERAL_SIDEBAR_COLLAPSE_SHARED}";
window.FS_GENERAL_SIDEBAR_PLAYLIST_LIST = "${FS_GENERAL_SIDEBAR_PLAYLIST_LIST}";
window.FS_GENERAL_SIDEBAR_PLAYLIST_SORTING = "${FS_GENERAL_SIDEBAR_PLAYLIST_SORTING}";
window.FS_GENERAL_SIDE_QUEUE_TYPE = "${FS_GENERAL_SIDE_QUEUE_TYPE}";
window.FS_GENERAL_SIDE_QUEUE_LAYOUT = "${FS_GENERAL_SIDE_QUEUE_LAYOUT}";
window.FS_GENERAL_THEME = "${FS_GENERAL_THEME}";
window.FS_GENERAL_THEME_DARK = "${FS_GENERAL_THEME_DARK}";
window.FS_GENERAL_THEME_LIGHT = "${FS_GENERAL_THEME_LIGHT}";
window.FS_GENERAL_USE_THEME_ACCENT_COLOR = "${FS_GENERAL_USE_THEME_ACCENT_COLOR}";
window.FS_GENERAL_USE_THEME_PRIMARY_SHADE = "${FS_GENERAL_USE_THEME_PRIMARY_SHADE}";
window.FS_GENERAL_ZOOM_FACTOR = "${FS_GENERAL_ZOOM_FACTOR}";
window.FS_PLAYBACK_MEDIA_SESSION = "${FS_PLAYBACK_MEDIA_SESSION}";
window.FS_PLAYBACK_WEB_AUDIO = "${FS_PLAYBACK_WEB_AUDIO}";
window.FS_PLAYBACK_AUDIO_FADE_ON_STATUS_CHANGE = "${FS_PLAYBACK_AUDIO_FADE_ON_STATUS_CHANGE}";
window.FS_PLAYBACK_PRESERVE_PITCH = "${FS_PLAYBACK_PRESERVE_PITCH}";
window.FS_PLAYBACK_SCROBBLE_ENABLED = "${FS_PLAYBACK_SCROBBLE_ENABLED}";
window.FS_PLAYBACK_SCROBBLE_NOTIFY = "${FS_PLAYBACK_SCROBBLE_NOTIFY}";
window.FS_PLAYBACK_SCROBBLE_AT_DURATION = "${FS_PLAYBACK_SCROBBLE_AT_DURATION}";
window.FS_PLAYBACK_SCROBBLE_AT_PERCENTAGE = "${FS_PLAYBACK_SCROBBLE_AT_PERCENTAGE}";
window.FS_PLAYBACK_TRANSCODE_ENABLED = "${FS_PLAYBACK_TRANSCODE_ENABLED}";
window.FS_DISCORD_ENABLED = "${FS_DISCORD_ENABLED}";
window.FS_DISCORD_CLIENT_ID = "${FS_DISCORD_CLIENT_ID}";
window.FS_DISCORD_DISPLAY_TYPE = "${FS_DISCORD_DISPLAY_TYPE}";
window.FS_DISCORD_LINK_TYPE = "${FS_DISCORD_LINK_TYPE}";
window.FS_DISCORD_SHOW_AS_LISTENING = "${FS_DISCORD_SHOW_AS_LISTENING}";
window.FS_DISCORD_SHOW_PAUSED = "${FS_DISCORD_SHOW_PAUSED}";
window.FS_DISCORD_SHOW_SERVER_IMAGE = "${FS_DISCORD_SHOW_SERVER_IMAGE}";
window.FS_DISCORD_SHOW_STATE_ICON = "${FS_DISCORD_SHOW_STATE_ICON}";
window.FS_LYRICS_FETCH = "${FS_LYRICS_FETCH}";
window.FS_LYRICS_FOLLOW = "${FS_LYRICS_FOLLOW}";
window.FS_LYRICS_DELAY_MS = "${FS_LYRICS_DELAY_MS}";
window.FS_LYRICS_PREFER_LOCAL = "${FS_LYRICS_PREFER_LOCAL}";
window.FS_LYRICS_SHOW_MATCH = "${FS_LYRICS_SHOW_MATCH}";
window.FS_LYRICS_SHOW_PROVIDER = "${FS_LYRICS_SHOW_PROVIDER}";
window.FS_LYRICS_ENABLE_AUTO_TRANSLATION = "${FS_LYRICS_ENABLE_AUTO_TRANSLATION}";
window.FS_LYRICS_TRANSLATION_API_KEY = "${FS_LYRICS_TRANSLATION_API_KEY}";
window.FS_LYRICS_TRANSLATION_TARGET_LANGUAGE = "${FS_LYRICS_TRANSLATION_TARGET_LANGUAGE}";
window.FS_LYRICS_ALIGNMENT = "${FS_LYRICS_ALIGNMENT}";
window.FS_AUTO_DJ_ENABLED = "${FS_AUTO_DJ_ENABLED}";
window.FS_AUTO_DJ_ITEM_COUNT = "${FS_AUTO_DJ_ITEM_COUNT}";
window.FS_AUTO_DJ_TIMING = "${FS_AUTO_DJ_TIMING}";
window.FS_CSS_CONTENT = "${FS_CSS_CONTENT}";
window.FS_CSS_ENABLED = "${FS_CSS_ENABLED}";
window.FS_FONT_TYPE = "${FS_FONT_TYPE}";
window.FS_FONT_BUILT_IN = "${FS_FONT_BUILT_IN}";
window.FS_FONT_SYSTEM = "${FS_FONT_SYSTEM}";
+7 -1
View File
@@ -21,7 +21,13 @@
"openIn": { "openIn": {
"lastfm": "فتح في Last.fm", "lastfm": "فتح في Last.fm",
"musicbrainz": "فتح في MusicBrainz" "musicbrainz": "فتح في MusicBrainz"
} },
"addOrRemoveFromSelection": "إضافة أو إزالة من الإختيارات",
"selectRangeOfItems": "اختر مجموعة من العناصر",
"goToCurrent": "الانتقال إلى العنصر الحالي",
"createRadioStation": "يخلق $t(entity.radioStation, {\"count\": 1})",
"deleteRadioStation": "يمسح $t(entity.radioStation, {\"count\": 1})",
"selectAll": "تحديد الكل"
}, },
"common": { "common": {
"action_zero": "عملية", "action_zero": "عملية",
+106 -22
View File
@@ -12,7 +12,7 @@
"search": "$t(common.search)", "search": "$t(common.search)",
"settings": "$t(common.setting, {\"count\": 2})", "settings": "$t(common.setting, {\"count\": 2})",
"tracks": "$t(entity.track, {\"count\": 2})", "tracks": "$t(entity.track, {\"count\": 2})",
"nowPlaying": "ara sona", "nowPlaying": "s'està reproduint",
"shared": "$t(entity.playlist, {\"count\": 2}) compartides", "shared": "$t(entity.playlist, {\"count\": 2}) compartides",
"favorites": "$t(entity.favorite, {\"count\": 2})", "favorites": "$t(entity.favorite, {\"count\": 2})",
"radio": "$t(entity.radioStation, {\"count\": 2})", "radio": "$t(entity.radioStation, {\"count\": 2})",
@@ -29,7 +29,11 @@
"topSongsFrom": "les millors cançons de {{title}}", "topSongsFrom": "les millors cançons de {{title}}",
"viewAll": "mostra-ho tot", "viewAll": "mostra-ho tot",
"groupingTypeAll": "tots els tipus de llançaments", "groupingTypeAll": "tots els tipus de llançaments",
"groupingTypePrimary": "tipus principals de llançament" "groupingTypePrimary": "tipus principals de llançament",
"favoriteSongs": "Cançons preferides",
"topSongsCommunity": "comunitat",
"topSongsPersonal": "personal",
"favoriteSongsFrom": "cançons preferides de {{title}}"
}, },
"albumArtistList": { "albumArtistList": {
"title": "$t(entity.albumArtist, {\"count\": 2})" "title": "$t(entity.albumArtist, {\"count\": 2})"
@@ -135,7 +139,9 @@
"lyricOffset": "demora de la lletra (ms)", "lyricOffset": "demora de la lletra (ms)",
"showLyricMatch": "mosta coincidències de lletres", "showLyricMatch": "mosta coincidències de lletres",
"showLyricProvider": "mostra el proveïdor de la lletra", "showLyricProvider": "mostra el proveïdor de la lletra",
"lyricGap": "espera entre lletres" "lyricGap": "espera entre lletres",
"lyricOpacityNonActive": "Opacitat de la lletra inactiva",
"lyricScaleNonActive": "Escala de la lletra inactiva"
}, },
"lyrics": "lletres", "lyrics": "lletres",
"visualizer": "visualitzador", "visualizer": "visualitzador",
@@ -200,6 +206,11 @@
"collections": { "collections": {
"overrideExisting": "sobreescriu existents", "overrideExisting": "sobreescriu existents",
"saveAsCollection": "desa com a col·lecció" "saveAsCollection": "desa com a col·lecció"
},
"releasenotes": {
"commitsSinceStable": "commits des de {{stable}}",
"noNewCommits": "no hi ha hagut commits en aquest període",
"noStableReleaseToCompare": "no hi ha actualitzacions disponibles amb les quals comparar"
} }
}, },
"common": { "common": {
@@ -292,6 +303,7 @@
"forward": "endavant", "forward": "endavant",
"manage": "gestiona", "manage": "gestiona",
"mbid": "ID de MusicBrainz", "mbid": "ID de MusicBrainz",
"grouping": "agrupament",
"noResultsFromQuery": "la petició no ha produït resultats", "noResultsFromQuery": "la petició no ha produït resultats",
"path": "ruta", "path": "ruta",
"playerMustBePaused": "cal pausar el reproductor", "playerMustBePaused": "cal pausar el reproductor",
@@ -326,7 +338,9 @@
"mood": "estat d'ànim", "mood": "estat d'ànim",
"filter_single": "senzill", "filter_single": "senzill",
"filter_multiple": "multi", "filter_multiple": "multi",
"rename": "reanomena" "rename": "reanomena",
"newVersionAvailable": "hi ha una nova versió disponible",
"numberOfResults": "{{numberOfResults}} resultats"
}, },
"entity": { "entity": {
"album_one": "àlbum", "album_one": "àlbum",
@@ -395,7 +409,8 @@
"input_skipDuplicates": "salta't els duplicats", "input_skipDuplicates": "salta't els duplicats",
"success": "s'ha afegit $t(entity.trackWithCount, {\"count\": {{message}} }) a $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} })", "success": "s'ha afegit $t(entity.trackWithCount, {\"count\": {{message}} }) a $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} })",
"create": "crea $t(entity.playlist, {\"count\": 1}) {{playlist}}", "create": "crea $t(entity.playlist, {\"count\": 1}) {{playlist}}",
"searchOrCreate": "cerca $t(entity.playlist, {\"count\": 2}) o escriu per crear-ne una de nova" "searchOrCreate": "cerca $t(entity.playlist, {\"count\": 2}) o escriu per crear-ne una de nova",
"noneAdded": "no s'han afegit pistes a la $t(entity.playlist, {\"count\": 1}) '{{playlist}}'"
}, },
"createPlaylist": { "createPlaylist": {
"input_description": "$t(common.description)", "input_description": "$t(common.description)",
@@ -413,8 +428,7 @@
"editPlaylist": { "editPlaylist": {
"success": "$t(entity.playlist, {\"count\": 1}) s'ha actualitzat amb èxit", "success": "$t(entity.playlist, {\"count\": 1}) s'ha actualitzat amb èxit",
"title": "editar la $t(entity.playlist, {\"count\": 1})", "title": "editar la $t(entity.playlist, {\"count\": 1})",
"publicJellyfinNote": "Per algun motiu, Jellyfin no exposa si una llista de reproducció és pública o no. Si voleu que es mantingui pública, seleccioneu la següent entrada", "publicJellyfinNote": "Per algun motiu, Jellyfin no exposa si una llista de reproducció és pública o no. Si voleu que es mantingui pública, seleccioneu la següent entrada"
"editNote": "es recomana no editar manualment les llistes de reproducció grans. segur que accepteu el risc de perdre dades si sobreescriviu la llista de reproducció existent?"
}, },
"lyricSearch": { "lyricSearch": {
"input_artist": "$t(entity.artist, {\"count\": 1})", "input_artist": "$t(entity.artist, {\"count\": 1})",
@@ -445,7 +459,9 @@
"setExpiration": "estableix expiració", "setExpiration": "estableix expiració",
"success": "s'ha copiat l'enllaç de compartició al porta-retalls (o feu clic aquí per obrir-lo)", "success": "s'ha copiat l'enllaç de compartició al porta-retalls (o feu clic aquí per obrir-lo)",
"expireInvalid": "la data d'expiració ha de ser al futur", "expireInvalid": "la data d'expiració ha de ser al futur",
"createFailed": "no s'ha pogut crear el recurs compartit (està habilitat, l'ús compartit?)" "createFailed": "no s'ha pogut crear el recurs compartit (està habilitat, l'ús compartit?)",
"copyToClipboard": "Copiar al porta-retalls: Ctrl+C, Enter",
"successMustClick": "Compartició creada correctament. Feu clic aquí per obrir-la."
}, },
"updateServer": { "updateServer": {
"success": "s'ha actualitzat el servidor amb èxit", "success": "s'ha actualitzat el servidor amb èxit",
@@ -494,6 +510,9 @@
"export": "exporta la lletra", "export": "exporta la lletra",
"input_synced": "exporta la lletra sincronitzada", "input_synced": "exporta la lletra sincronitzada",
"input_offset": "$t(setting.lyricOffset)" "input_offset": "$t(setting.lyricOffset)"
},
"editRadioStation": {
"success": "Emissora de ràdio actualitzada amb èxit"
} }
}, },
"action": { "action": {
@@ -510,7 +529,10 @@
"goToPage": "anar a la pàgina", "goToPage": "anar a la pàgina",
"openIn": { "openIn": {
"lastfm": "Obrir a Last.fm", "lastfm": "Obrir a Last.fm",
"musicbrainz": "Obrir a MusicBrainz" "musicbrainz": "Obrir a MusicBrainz",
"listenbrainz": "Obre a ListenBrainz",
"qobuz": "Obre a Qobuz",
"spotify": "Obre a Spotify"
}, },
"deselectAll": "deselecciona-ho tot", "deselectAll": "deselecciona-ho tot",
"viewPlaylists": "veure $t(entity.playlist, {\"count\": 2})", "viewPlaylists": "veure $t(entity.playlist, {\"count\": 2})",
@@ -534,7 +556,8 @@
"addOrRemoveFromSelection": "afegeix o elimina de la selecció", "addOrRemoveFromSelection": "afegeix o elimina de la selecció",
"selectRangeOfItems": "selecciona un interval d'elements", "selectRangeOfItems": "selecciona un interval d'elements",
"selectAll": "selecciona-ho tot", "selectAll": "selecciona-ho tot",
"openApplicationDirectory": "obre el directori de l'aplicació" "openApplicationDirectory": "obre el directori de l'aplicació",
"goToCurrent": "anar a l'element actual"
}, },
"setting": { "setting": {
"language_description": "estableix l'idioma de l'aplicació ($t(common.restartRequired))", "language_description": "estableix l'idioma de l'aplicació ($t(common.restartRequired))",
@@ -559,7 +582,7 @@
"sidePlayQueueStyle_optionAttached": "unida", "sidePlayQueueStyle_optionAttached": "unida",
"sidePlayQueueStyle_optionDetached": "separada", "sidePlayQueueStyle_optionDetached": "separada",
"audioDevice": "dispositiu d'àudio", "audioDevice": "dispositiu d'àudio",
"audioDevice_description": "seleccioneu el dispositiu d'àudio que voleu utilitzar per a la reproducció (només pel reproductor web)", "audioDevice_description": "seleccioneu el dispositiu d'àudio que voleu utilitzar per a la reproducció",
"audioPlayer": "reproductor d'àudio", "audioPlayer": "reproductor d'àudio",
"audioPlayer_description": "seleccioneu el reproductor d'àudio que voleu utilitzar per a la reproducció", "audioPlayer_description": "seleccioneu el reproductor d'àudio que voleu utilitzar per a la reproducció",
"sidebarConfiguration_description": "selecciona els elements i l'ordre en què apareixen a la barra lateral", "sidebarConfiguration_description": "selecciona els elements i l'ordre en què apareixen a la barra lateral",
@@ -584,7 +607,7 @@
"artistConfiguration": "configuració de la pàgina de l'artista de l'àlbum", "artistConfiguration": "configuració de la pàgina de l'artista de l'àlbum",
"artistConfiguration_description": "configura quins elements es mostren i el seu ordre de la pàgina de l'artista de l'àlbum", "artistConfiguration_description": "configura quins elements es mostren i el seu ordre de la pàgina de l'artista de l'àlbum",
"audioExclusiveMode": "mode d'àudio exclusiu", "audioExclusiveMode": "mode d'àudio exclusiu",
"audioExclusiveMode_description": "activa el mode d'àudio exclusiu. En aquest mode, el sistema normalment estarà bloquejat i només mpv podrà emetre àudio", "audioExclusiveMode_description": "activa el mode d'àudio exclusiu. En aquest mode, el sistema normalment estarà bloquejat i només mpv podrà emetre àudio. El sistema visualitzador de captura d'àudio no funcionarà mentre això estigui activat",
"buttonSize": "mida dels botons de la barra de reproducció", "buttonSize": "mida dels botons de la barra de reproducció",
"buttonSize_description": "la mida dels botons de la barra de reproducció", "buttonSize_description": "la mida dels botons de la barra de reproducció",
"clearCache": "neteja la memòria del navegador", "clearCache": "neteja la memòria del navegador",
@@ -605,9 +628,9 @@
"customFontPath_description": "estableix la ruta a una font personalitzada per utilitzar-la a l'aplicació", "customFontPath_description": "estableix la ruta a una font personalitzada per utilitzar-la a l'aplicació",
"discordApplicationId": "id d'aplicació de {{discord}}", "discordApplicationId": "id d'aplicació de {{discord}}",
"discordApplicationId_description": "l'id d'aplicació per l'estat d'activitat de {{discord}} (per defecte, {{defaultId}})", "discordApplicationId_description": "l'id d'aplicació per l'estat d'activitat de {{discord}} (per defecte, {{defaultId}})",
"discordPausedStatus": "mosta l'estat d'activitat quan està en pausa", "discordPausedStatus": "mostra l'estat d'activitat quan està en pausa",
"discordPausedStatus_description": "si està activat, l'estat es mostrarà quan el reproductor estigui pausat", "discordPausedStatus_description": "si està activat, l'estat es mostrarà quan el reproductor estigui pausat",
"discordIdleStatus": "mosta l'estat d'activitat en inactivitat", "discordIdleStatus": "mosta l'estat d'activitat quan està inactiu",
"discordIdleStatus_description": "si està activat, s'actualitzarà l'estat mentre el reproductor estigui inactiu", "discordIdleStatus_description": "si està activat, s'actualitzarà l'estat mentre el reproductor estigui inactiu",
"discordListening": "mosta l'estat com escoltant", "discordListening": "mosta l'estat com escoltant",
"discordListening_description": "mosta l'estat com escoltant en comptes de jugant", "discordListening_description": "mosta l'estat com escoltant en comptes de jugant",
@@ -779,7 +802,7 @@
"releaseChannel_optionLatest": "última versió", "releaseChannel_optionLatest": "última versió",
"releaseChannel_optionBeta": "beta", "releaseChannel_optionBeta": "beta",
"releaseChannel": "canal de versions", "releaseChannel": "canal de versions",
"releaseChannel_description": "tria entre versions estables i versions beta per les actualitzacions automàtiques", "releaseChannel_description": "trieu entre versions estables i beta o alfa (diàries) per les actualitzacions automàtiques",
"mediaSession": "activa Media Session", "mediaSession": "activa Media Session",
"mediaSession_description": "activa la integració amb Media Session per mostrar els controls multimèdia i les metadades a l'indicador de volum del sistema i la pantalla de bloqueig", "mediaSession_description": "activa la integració amb Media Session per mostrar els controls multimèdia i les metadades a l'indicador de volum del sistema i la pantalla de bloqueig",
"crossfadeStyle": "estil de fosa encadenada", "crossfadeStyle": "estil de fosa encadenada",
@@ -878,7 +901,44 @@
"sidebarPlaylistSorting": "ordenació de llistes de reproducció de la barra lateral", "sidebarPlaylistSorting": "ordenació de llistes de reproducció de la barra lateral",
"sidebarPlaylistListFilterRegex_description": "amaga les llistes de reproducció de la barra lateral que coincideixin amb aquesta expressió regular", "sidebarPlaylistListFilterRegex_description": "amaga les llistes de reproducció de la barra lateral que coincideixin amb aquesta expressió regular",
"sidebarPlaylistListFilterRegex_placeholder": "ex. ^Mescla diària.*", "sidebarPlaylistListFilterRegex_placeholder": "ex. ^Mescla diària.*",
"sidebarPlaylistListFilterRegex": "regex pel filtre de llistes" "sidebarPlaylistListFilterRegex": "regex pel filtre de llistes",
"analyticsEnable": "envia analítiques basades en l'ús",
"analyticsEnable_description": "s'envien dades d'ús anonimitzades al desenvolupar per ajudar a millorar l'aplicació",
"automaticUpdates": "actualitzacions automàtiques",
"automaticUpdates_description": "cerca i instal·la actualitzacions automàticament",
"releaseChannel_optionAlpha": "alfa (diària)",
"blurExplicitImages": "desenfoca imatges explícites",
"blurExplicitImages_description": "les caràtules d'àlbums i cançons marcades com a explícites quedaran desenfocades",
"discordStateIcon": "mostra la icona de reproducció",
"discordStateIcon_description": "mostra una petita icona de reproducció a l'estat d'activitat. l'icona de pausa es mostra quan \"mostra l'estat d'activitat quan està en pausa\" està activat",
"autosave": "desa automàticament la cua de reproducció",
"autosave_description": "activa el desament automàtic de la cua de reproducció al teu servidor. això només és possible quan s'utilitza Navidrome/Subsonic i no es pot tenir una cua de reproducció mixta.",
"autosaveCount": "freqüència de desament de cua de reproducció automàtica",
"autosaveCount_description": "quants canvis de pista abans que es desi la cua. 1 (mínim) significa cada canvi de cançó",
"useThemePrimaryShade": "utilitza l'ombra primària del tema",
"useThemePrimaryShade_description": "utilitza el to primari definit al tema seleccionat per a les variants de color primari",
"primaryShade": "ombra primària",
"primaryShade_description": "substitueix el to primari (09) utilitzat per a botons, enllaços i altres elements de color primari",
"playerItemConfiguration_description": "configurar quins elements es mostren i en quin ordre al reproductor de pantalla completa",
"playerItemConfiguration": "configuració d'elements del jugador",
"listenbrainz_description": "mostra enllaços a ListenBrainz a les pàgines d'artista/àlbum",
"listenbrainz": "mostra enllaços a ListenBrainz",
"qobuz_description": "mostra enllaços a Qobuz a les pàgines d'artista/àlbum",
"qobuz": "mostra enllaços a Qobuz",
"spotify_description": "mostra enllaços a Spotify a les pàgines d'artista/àlbum",
"spotify": "mostra enllaços a Spotify",
"nativeSpotify_description": "obre amb Spotify en lloc del vostre navegador",
"nativeSpotify": "fes servir Spotify",
"playerbarWaveformStretch": "extensió de la forma d'ona",
"playerbarWaveformStretch_description": "estén la forma d'ona per omplir l'espai disponible",
"sidePlayQueueLayout": "disposició de la cua de reproducció lateral",
"sidePlayQueueLayout_description": "estableix la disposició de la cua de reproducció lateral adjunta",
"sidePlayQueueLayout_optionHorizontal": "horitzontal",
"sidePlayQueueLayout_optionVertical": "vertical",
"waveformLoadingDelay": "demora de càrrega de la forma d'ona",
"waveformLoadingDelay_description": "demora en segons abans de carregar la forma d'ona. incrementeu aquest valor si patiu interrupcions en fer servir el reproductor web.",
"preventSuspendOnPlayback_description": "evita que l'aplicació quedi suspesa mentre es reprodueix música",
"preventSuspendOnPlayback": "evita la suspensió durant la reproducció"
}, },
"table": { "table": {
"column": { "column": {
@@ -978,12 +1038,14 @@
"image": "imatge", "image": "imatge",
"sampleRate": "$t(common.sampleRate)", "sampleRate": "$t(common.sampleRate)",
"composer": "compositor", "composer": "compositor",
"titleArtist": "$t(common.title) (artista)" "titleArtist": "$t(common.title) (artista)",
"albumGroup": "grup d'àlbums"
}, },
"view": { "view": {
"table": "taula", "table": "taula",
"grid": "quadrícula", "grid": "quadrícula",
"list": "llista" "list": "llista",
"detail": "detall"
} }
} }
}, },
@@ -1031,7 +1093,9 @@
"path": "ruta", "path": "ruta",
"songCount": "nombre de cançons", "songCount": "nombre de cançons",
"explicitStatus": "$t(common.explicitStatus)", "explicitStatus": "$t(common.explicitStatus)",
"sortName": "ordena per nom" "sortName": "ordena per nom",
"matchAnd": "i",
"matchOr": "o"
}, },
"player": { "player": {
"muted": "silenciat", "muted": "silenciat",
@@ -1072,7 +1136,17 @@
"restoreQueueFromServer": "restaura la cua del servidor", "restoreQueueFromServer": "restaura la cua del servidor",
"saveQueueToServer": "desa la cua al servidor", "saveQueueToServer": "desa la cua al servidor",
"artistRadio": "ràdio de l'artista", "artistRadio": "ràdio de l'artista",
"trackRadio": "ràdio de la pista" "trackRadio": "ràdio de la pista",
"sleepTimer": "temporitzador d'adormir",
"sleepTimer_endOfSong": "final de la cançó actual",
"sleepTimer_minutes": "{{count}} min",
"sleepTimer_hours": "{{count}} h",
"sleepTimer_custom": "personalitzat",
"sleepTimer_off": "apagat",
"sleepTimer_timeRemaining": "queden {{time}}",
"sleepTimer_setCustom": "configura el temporitzador",
"sleepTimer_cancel": "cancel·la el temporitzador",
"albumRadio": "ràdio d'àlbums"
}, },
"error": { "error": {
"credentialsRequired": "credencials requerides", "credentialsRequired": "credencials requerides",
@@ -1103,7 +1177,10 @@
"saveQueueFailed": "error en desar la cua", "saveQueueFailed": "error en desar la cua",
"settingsSyncError": "hi ha discrepàncies entre la configuració del renderitzador i el procés principal. reinicieu l'aplicació per aplicar els canvis", "settingsSyncError": "hi ha discrepàncies entre la configuració del renderitzador i el procés principal. reinicieu l'aplicació per aplicar els canvis",
"noNetwork": "servidor no disponible", "noNetwork": "servidor no disponible",
"noNetworkDescription": "no s'ha pogut connectar amb el servidor" "noNetworkDescription": "no s'ha pogut connectar amb el servidor",
"invalidJson": "JSON invàlid",
"serverLockSingleServer": "només es permet un servidor quan el servidor està bloquejat",
"playbackPausedDueToError": "la reproducció s'ha pausat a causa d'un error"
}, },
"releaseType": { "releaseType": {
"primary": { "primary": {
@@ -1311,6 +1388,13 @@
} }
}, },
"pasteGradient": "enganxa degradat", "pasteGradient": "enganxa degradat",
"pasteGradientPlaceholder": "enganxa el degradat JSON aquí..." "pasteGradientPlaceholder": "enganxa el degradat JSON aquí...",
"systemAudioConsentAllow": "permetre",
"systemAudioConsentBody": "el visualitzador necessita accés a l'àudio del sistema per funcionar",
"systemAudioConsentDecline": "denega",
"systemAudioConsentTitle": "Voleu permetre accés al sistema d'àudio?",
"systemAudioCaptureFailed": "No s'ha pogut iniciar la captura: {{message}}",
"systemAudioNoAudioTrack": "No s'ha tornat cap pista d'àudio. Comproveu que la captura d'àudio estigui activada quan se sol·liciti.",
"systemAudioExclusiveModeNotSupported": "El visualitzador no està disponible amb el mode d'àudio exclusiu activat. Desactiveu-lo a la configuració d'MPV i torneu-ho a intentar."
} }
} }
+90 -18
View File
@@ -38,7 +38,17 @@
"restoreQueueFromServer": "obnovit frontu ze serveru", "restoreQueueFromServer": "obnovit frontu ze serveru",
"saveQueueToServer": "uložit frontu na server", "saveQueueToServer": "uložit frontu na server",
"artistRadio": "rádio umělce", "artistRadio": "rádio umělce",
"trackRadio": "rádio skladby" "trackRadio": "rádio skladby",
"sleepTimer": "časovač spánku",
"sleepTimer_endOfSong": "konec aktuální skladby",
"sleepTimer_minutes": "{{count}} min.",
"sleepTimer_hours": "{{count}} hod.",
"sleepTimer_custom": "vlastní",
"sleepTimer_off": "vypnuto",
"sleepTimer_timeRemaining": "zbývá {{time}}",
"sleepTimer_setCustom": "nastavit časovač",
"sleepTimer_cancel": "zrušit časovač",
"albumRadio": "rádio alba"
}, },
"setting": { "setting": {
"crossfadeStyle_description": "vyberte způsob prolnutí u přehrávače zvuku", "crossfadeStyle_description": "vyberte způsob prolnutí u přehrávače zvuku",
@@ -46,7 +56,7 @@
"hotkey_skipBackward": "přeskočení zpět", "hotkey_skipBackward": "přeskočení zpět",
"replayGainMode_description": "úprava zesílení hlasitosti podle hodnot {{ReplayGain}} uložených v metadatech souborů", "replayGainMode_description": "úprava zesílení hlasitosti podle hodnot {{ReplayGain}} uložených v metadatech souborů",
"volumeWheelStep_description": "počet procent, o které má být hlasitost posunuta při přejetí kolečkem myši na posuvníku hlasitosti", "volumeWheelStep_description": "počet procent, o které má být hlasitost posunuta při přejetí kolečkem myši na posuvníku hlasitosti",
"audioDevice_description": "vyberte zvukové zařízení k přehrávání (pouze webový přehrávač)", "audioDevice_description": "vyberte zvukové zařízení k přehrávání",
"theme_description": "nastavení motivu použitého v aplikaci", "theme_description": "nastavení motivu použitého v aplikaci",
"hotkey_playbackPause": "pozastavení", "hotkey_playbackPause": "pozastavení",
"replayGainFallback": "fallback {{ReplayGain}}", "replayGainFallback": "fallback {{ReplayGain}}",
@@ -75,7 +85,7 @@
"hotkey_zoomIn": "přiblížení", "hotkey_zoomIn": "přiblížení",
"scrobble_description": "scrobblovat přehrání na váš multimediální server", "scrobble_description": "scrobblovat přehrání na váš multimediální server",
"hotkey_browserForward": "vpřed v prohlížeči", "hotkey_browserForward": "vpřed v prohlížeči",
"audioExclusiveMode_description": "zapnout režim výhradního výstupu. V tomto režimu bude obvykle v systému schopný přehrávat zvuk pouze přehrávač mpv", "audioExclusiveMode_description": "zapnout režim výhradního výstupu. v tomto režimu bude obvykle v systému schopný přehrávat zvuk pouze přehrávač mpv. záznam systémového zvuku ve vizualizéru nebude fungovat",
"discordUpdateInterval": "interval aktualizací {{discord}} rich presence", "discordUpdateInterval": "interval aktualizací {{discord}} rich presence",
"themeLight": "motiv (světlý)", "themeLight": "motiv (světlý)",
"fontType_optionBuiltIn": "vestavěné písmo", "fontType_optionBuiltIn": "vestavěné písmo",
@@ -261,7 +271,7 @@
"neteaseTranslation_description": "Pokud je povoleno, načte a zobrazí přeložené texty ze služby NetEase, pokud jsou dostupné", "neteaseTranslation_description": "Pokud je povoleno, načte a zobrazí přeložené texty ze služby NetEase, pokud jsou dostupné",
"preferLocalLyrics": "preferovat místní texty", "preferLocalLyrics": "preferovat místní texty",
"preferLocalLyrics_description": "preferovat místní texty před vzdálenými, pokud jsou dostupné", "preferLocalLyrics_description": "preferovat místní texty před vzdálenými, pokud jsou dostupné",
"discordPausedStatus": "zobrazit rich presence při pozastavení", "discordPausedStatus": "zobrazit stav při pozastavení",
"discordPausedStatus_description": "pokud je povoleno, bude při pozastavení přehrávače zobrazen stav", "discordPausedStatus_description": "pokud je povoleno, bude při pozastavení přehrávače zobrazen stav",
"preservePitch": "zachovat výšku", "preservePitch": "zachovat výšku",
"preservePitch_description": "zachová výšku při úpravě rychlosti přehrávání", "preservePitch_description": "zachová výšku při úpravě rychlosti přehrávání",
@@ -385,7 +395,41 @@
"sidebarPlaylistListFilterRegex_description": "v postranní liště skrýt seznamy skladeb, které odpovídají tomuto regulárnímu výrazu", "sidebarPlaylistListFilterRegex_description": "v postranní liště skrýt seznamy skladeb, které odpovídají tomuto regulárnímu výrazu",
"sidebarPlaylistListFilterRegex_placeholder": "např. ^Denní mix.*", "sidebarPlaylistListFilterRegex_placeholder": "např. ^Denní mix.*",
"sidebarPlaylistListFilterRegex": "regulární výraz filtru seznamů skladeb", "sidebarPlaylistListFilterRegex": "regulární výraz filtru seznamů skladeb",
"releaseChannel_optionAlpha": "alpha (noční)" "releaseChannel_optionAlpha": "alpha (noční)",
"analyticsEnable": "Posílat analytiku založenou na využití",
"analyticsEnable_description": "Anonymizovaná data o používání jsou odesílána vývojáři za účelem zlepšení aplikace",
"automaticUpdates": "Automatické aktualizace",
"automaticUpdates_description": "Kontrolovat a automaticky instalovat aktualizace",
"discordStateIcon": "zobrazit ikonu přehrávání",
"discordStateIcon_description": "zobrazit malou ikonu přehrávání ve stavu na Discordu. ikona pozastavení bude zobrazena vždy, když je povolena možnost „Zobrazit stav při pozastavení“",
"useThemePrimaryShade": "použít primární odstín motivu",
"useThemePrimaryShade_description": "použít primární odstín definovaný ve zvoleném motivu pro primární varianty barev",
"primaryShade": "primární odstín",
"primaryShade_description": "přepsat primární odstín (09) používaný pro tlačítka, odkazy a další prvky obarvené primární barvou",
"playerItemConfiguration_description": "nastavit, které položky budou zobrazeny a v jakém pořadí, v celoobrazovkovém přehrávači",
"playerItemConfiguration": "nastavení položek přehrávače",
"autosave": "automaticky ukládat frontu přehrávání",
"autosave_description": "zapnout automatické ukládání fronty přehrávání na server. toto je možné pouze při použití Navidrome/Subsonic a není možné mít kombinovanou frontu přehrávání.",
"autosaveCount": "četnost automatického ukládání fronty přehrávání",
"autosaveCount_description": "kolik změn skladeb se může provést před uložením fronty. 1 (minimum) znamená při každé změně skladby",
"spotify_description": "na stránkách umělců a alb zobrazit odkazy na Spotify",
"spotify": "zobrazit odkazy na Spotify",
"nativeSpotify_description": "otevřít v aplikaci Spotify namísto vašeho prohlížeče",
"nativeSpotify": "použít aplikaci Spotify",
"listenbrainz_description": "na stránkách umělců a alb zobrazit odkazy na ListenBrainz",
"listenbrainz": "zobrazit odkazy na ListenBrainz",
"qobuz_description": "na stránkách umělců a alb zobrazit odkazy na Qobuz",
"qobuz": "zobrazit odkazy na Qobuz",
"sidePlayQueueLayout": "rozložení postranní fronty přehrávání",
"sidePlayQueueLayout_description": "nastaví rozložení postranní lišty přehrávání",
"sidePlayQueueLayout_optionHorizontal": "na šířku",
"sidePlayQueueLayout_optionVertical": "na výšku",
"waveformLoadingDelay": "zpoždění načítání vlnové křivky",
"waveformLoadingDelay_description": "zpoždění v sekundách před načtením vlnové křivky. zvyšte, pokud jste během používání webového přehrávače zaznamenali záseky.",
"playerbarWaveformStretch": "natáhnutí vlnové křivky",
"playerbarWaveformStretch_description": "natáhně vlnovou křivku tak, aby vyplnila dostupný prostor",
"preventSuspendOnPlayback_description": "zabránit aplikaci v uspání během přehrávání hudby",
"preventSuspendOnPlayback": "zabránit uspání při přehrávání"
}, },
"action": { "action": {
"editPlaylist": "upravit $t(entity.playlist, {\"count\": 1})", "editPlaylist": "upravit $t(entity.playlist, {\"count\": 1})",
@@ -407,7 +451,10 @@
"removeFromFavorites": "odebrat z $t(entity.favorite, {\"count\": 2})", "removeFromFavorites": "odebrat z $t(entity.favorite, {\"count\": 2})",
"openIn": { "openIn": {
"lastfm": "Otevřít v Last.fm", "lastfm": "Otevřít v Last.fm",
"musicbrainz": "Otevřít v MusicBrainz" "musicbrainz": "Otevřít v MusicBrainz",
"spotify": "Otevřít na Spotify",
"listenbrainz": "Otevřít ve službě ListenBrainz",
"qobuz": "Otevřít ve službě Qobuz"
}, },
"moveToNext": "přesunout na další", "moveToNext": "přesunout na další",
"downloadStarted": "spuštěno stahování {{count}} položek", "downloadStarted": "spuštěno stahování {{count}} položek",
@@ -425,7 +472,8 @@
"openApplicationDirectory": "otevřít adresář aplikace", "openApplicationDirectory": "otevřít adresář aplikace",
"addOrRemoveFromSelection": "přidat nebo odebrat z výběru", "addOrRemoveFromSelection": "přidat nebo odebrat z výběru",
"selectRangeOfItems": "vyberte rozsah položek", "selectRangeOfItems": "vyberte rozsah položek",
"selectAll": "vybrat vše" "selectAll": "vybrat vše",
"goToCurrent": "přejít na aktuální položku"
}, },
"common": { "common": {
"backward": "zpátky", "backward": "zpátky",
@@ -551,14 +599,18 @@
"example": "příklad", "example": "příklad",
"filter_single": "jeden", "filter_single": "jeden",
"filter_multiple": "několik", "filter_multiple": "několik",
"rename": "přejmenovat" "rename": "přejmenovat",
"newVersionAvailable": "je dostupná nová verze",
"numberOfResults": "{{numberOfResults}} výsledků",
"grouping": "seskupování"
}, },
"table": { "table": {
"config": { "config": {
"view": { "view": {
"table": "tabulka", "table": "tabulka",
"list": "seznam", "list": "seznam",
"grid": "mřížka" "grid": "mřížka",
"detail": "podrobnosti"
}, },
"general": { "general": {
"displayType": "typ zobrazení", "displayType": "typ zobrazení",
@@ -627,7 +679,8 @@
"bitDepth": "$t(common.bitDepth)", "bitDepth": "$t(common.bitDepth)",
"sampleRate": "$t(common.sampleRate)", "sampleRate": "$t(common.sampleRate)",
"composer": "skladatel", "composer": "skladatel",
"titleArtist": "$t(common.title) (umělec)" "titleArtist": "$t(common.title) (umělec)",
"albumGroup": "skupina alb"
} }
}, },
"column": { "column": {
@@ -689,7 +742,10 @@
"saveQueueFailed": "nepodařilo se uložit frontu", "saveQueueFailed": "nepodařilo se uložit frontu",
"settingsSyncError": "byly zjištěny nesrovnalosti mezi nastavením v rendereru a hlavním procesem. restartujte aplikaci, aby se změny projevily", "settingsSyncError": "byly zjištěny nesrovnalosti mezi nastavením v rendereru a hlavním procesem. restartujte aplikaci, aby se změny projevily",
"noNetwork": "server je nedostupný", "noNetwork": "server je nedostupný",
"noNetworkDescription": "k tomuto serveru se nepodařilo připojit" "noNetworkDescription": "k tomuto serveru se nepodařilo připojit",
"invalidJson": "neplatný JSON",
"serverLockSingleServer": "při uzamčení serveru je povolen pouze jeden server",
"playbackPausedDueToError": "přehrávání bylo pozastaveno z důvodu chyby"
}, },
"filter": { "filter": {
"mostPlayed": "nejvíce přehráváno", "mostPlayed": "nejvíce přehráváno",
@@ -735,7 +791,9 @@
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
"trackNumber": "skladba", "trackNumber": "skladba",
"explicitStatus": "$t(common.explicitStatus)", "explicitStatus": "$t(common.explicitStatus)",
"sortName": "název v řazení" "sortName": "název v řazení",
"matchAnd": "a",
"matchOr": "nebo"
}, },
"page": { "page": {
"sidebar": { "sidebar": {
@@ -771,7 +829,9 @@
"lyricGap": "mezera textů", "lyricGap": "mezera textů",
"dynamicImageBlur": "velikost rozostření obrázku", "dynamicImageBlur": "velikost rozostření obrázku",
"dynamicIsImage": "povolit obrázek na pozadí", "dynamicIsImage": "povolit obrázek na pozadí",
"lyricOffset": "posunutí textů (ms)" "lyricOffset": "posunutí textů (ms)",
"lyricOpacityNonActive": "neprůhlednost neaktivních textů",
"lyricScaleNonActive": "velikost neaktivních textů"
}, },
"upNext": "další", "upNext": "další",
"lyrics": "texty", "lyrics": "texty",
@@ -987,7 +1047,8 @@
"input_skipDuplicates": "přeskočit duplicity", "input_skipDuplicates": "přeskočit duplicity",
"input_playlists": "$t(entity.playlist, {\"count\": 2})", "input_playlists": "$t(entity.playlist, {\"count\": 2})",
"create": "vytvořit $t(entity.playlist, {\"count\": 1}) {{playlist}}", "create": "vytvořit $t(entity.playlist, {\"count\": 1}) {{playlist}}",
"searchOrCreate": "vyhledejte $t(entity.playlist, {\"count\": 2}) nebo pište pro vytvoření nového" "searchOrCreate": "vyhledejte $t(entity.playlist, {\"count\": 2}) nebo pište pro vytvoření nového",
"noneAdded": "do $t(entity.playlist, {\"count\": 1}) '{{playlist}}' nebyly přidány žádné skladby"
}, },
"updateServer": { "updateServer": {
"title": "upravit server", "title": "upravit server",
@@ -1010,8 +1071,7 @@
"editPlaylist": { "editPlaylist": {
"title": "upravit $t(entity.playlist, {\"count\": 1})", "title": "upravit $t(entity.playlist, {\"count\": 1})",
"success": "$t(entity.playlist, {\"count\": 1}) úspěšně aktualizován", "success": "$t(entity.playlist, {\"count\": 1}) úspěšně aktualizován",
"publicJellyfinNote": "Jellyfin z nějakého důvodu neukazuje, zda je seznam skladeb veřejný, nebo ne. Pokud si přejete, aby zůstal veřejný, zvolte prosím následující vstup", "publicJellyfinNote": "Jellyfin z nějakého důvodu neukazuje, zda je seznam skladeb veřejný, nebo ne. Pokud si přejete, aby zůstal veřejný, zvolte prosím následující vstup"
"editNote": "ruční úpravy velkých seznamů skladeb nejsou doporučeny. opravdu přijímáte riziko ztráty dat, které může vzniknout přepsáním existujícího seznamu skladeb?"
}, },
"shareItem": { "shareItem": {
"allowDownloading": "umožnit stahování", "allowDownloading": "umožnit stahování",
@@ -1019,7 +1079,9 @@
"description": "popis", "description": "popis",
"expireInvalid": "čas vypršení musí být v budoucnosti", "expireInvalid": "čas vypršení musí být v budoucnosti",
"setExpiration": "nastavit vypršení", "setExpiration": "nastavit vypršení",
"createFailed": "nepodařilo se vytvořit sdílení (je sdílení povoleno?)" "createFailed": "nepodařilo se vytvořit sdílení (je sdílení povoleno?)",
"copyToClipboard": "Zkopírovat do schránky: Ctrl+C, Enter",
"successMustClick": "sdílení úspěšně vytvořeno. klikněte sem pro otevření"
}, },
"privateMode": { "privateMode": {
"enabled": "soukromý režim povolen, stav přehrávání je nyní skryt před externími integracemi", "enabled": "soukromý režim povolen, stav přehrávání je nyní skryt před externími integracemi",
@@ -1055,6 +1117,9 @@
"export": "exportovat texty", "export": "exportovat texty",
"input_synced": "exportovat synchronizované texty", "input_synced": "exportovat synchronizované texty",
"input_offset": "$t(setting.lyricOffset)" "input_offset": "$t(setting.lyricOffset)"
},
"editRadioStation": {
"success": "stanice rádia úspěšně upravena"
} }
}, },
"entity": { "entity": {
@@ -1323,6 +1388,13 @@
} }
}, },
"pasteGradient": "Vložit přechod", "pasteGradient": "Vložit přechod",
"pasteGradientPlaceholder": "Sem vložte JSON přechodu…" "pasteGradientPlaceholder": "Sem vložte JSON přechodu…",
"systemAudioConsentAllow": "Povolit",
"systemAudioConsentBody": "Vizualizér potřebuje pro svou činnost přístup k systémovému zvuku",
"systemAudioConsentTitle": "Povolit přístup k systémovému zvuku?",
"systemAudioCaptureFailed": "Nepodařilo se spustit zachytávání: {{message}}",
"systemAudioNoAudioTrack": "Nebyla zachycena žádná zvuková stopa. Ujistěte se, že jste při výzvě povolili zachytávání zvuku.",
"systemAudioConsentDecline": "Zamítnout",
"systemAudioExclusiveModeNotSupported": "Vizualizér není dostupný při zapnutém režimu výhradního výstupu zvuku. Zakažte Režim výhradního výstupu zvuku v nastavení MPV a zkuste to znovu."
} }
} }
-1
View File
@@ -359,7 +359,6 @@
}, },
"editPlaylist": { "editPlaylist": {
"publicJellyfinNote": "Jellyfin viser af en eller anden grund ikke, om en playliste er offentlig eller ej. Hvis du ønsker, at den forbliver offentlig, skal du have følgende felt markeret", "publicJellyfinNote": "Jellyfin viser af en eller anden grund ikke, om en playliste er offentlig eller ej. Hvis du ønsker, at den forbliver offentlig, skal du have følgende felt markeret",
"editNote": "manuelle ændringer anbefales ikke for store playlister. er du sikker på, at du accepterer risikoen for datatab ved at overskrive den eksisterende playliste?",
"success": "$t(entity.playlist, {\"count\": 1}) opdateret", "success": "$t(entity.playlist, {\"count\": 1}) opdateret",
"title": "rediger $t(entity.playlist, {\"count\": 1})" "title": "rediger $t(entity.playlist, {\"count\": 1})"
}, },
+286 -38
View File
@@ -19,7 +19,10 @@
"removeFromFavorites": "Aus $t(entity.favorite, {\"count\": 2}) entfernen", "removeFromFavorites": "Aus $t(entity.favorite, {\"count\": 2}) entfernen",
"openIn": { "openIn": {
"lastfm": "Auf Last.fm öffnen", "lastfm": "Auf Last.fm öffnen",
"musicbrainz": "Auf MusicBrainz öffnen" "musicbrainz": "Auf MusicBrainz öffnen",
"listenbrainz": "In ListenBrainz öffnen",
"qobuz": "In Qobuz öffnen",
"spotify": "In Spotify öffnen"
}, },
"moveToNext": "Als nächstes", "moveToNext": "Als nächstes",
"downloadStarted": "Download von {{count}} Elementen gestartet", "downloadStarted": "Download von {{count}} Elementen gestartet",
@@ -34,7 +37,11 @@
"deleteRadioStation": "$t(entity.radioStation, {\"count\": 1}) löschen", "deleteRadioStation": "$t(entity.radioStation, {\"count\": 1}) löschen",
"selectAll": "alle auswählen", "selectAll": "alle auswählen",
"openApplicationDirectory": "Anwendungsverzeichnis öffnen", "openApplicationDirectory": "Anwendungsverzeichnis öffnen",
"addOrRemoveFromSelection": "Zur Auswahl hinzufügen oder entfernen" "addOrRemoveFromSelection": "Zur Auswahl hinzufügen oder entfernen",
"selectRangeOfItems": "Wählen sie eine Reihe von Elementen",
"holdToMoveToTop": "Halten um nach oben zu bewegen",
"holdToMoveToBottom": "Halten um nach unten zu bewegen",
"goToCurrent": "Zu aktuellem Eintrag wechseln"
}, },
"common": { "common": {
"backward": "zurück", "backward": "zurück",
@@ -120,6 +127,7 @@
"preview": "Vorschau", "preview": "Vorschau",
"reload": "Neu Laden", "reload": "Neu Laden",
"mbid": "MusicBrainz ID", "mbid": "MusicBrainz ID",
"grouping": "gruppierung",
"close": "schließen", "close": "schließen",
"share": "Teilen", "share": "Teilen",
"translation": "Übersetzung", "translation": "Übersetzung",
@@ -152,7 +160,14 @@
"releaseType": "Veröffentlichungsformat", "releaseType": "Veröffentlichungsformat",
"view": "Betrachten", "view": "Betrachten",
"countSelected": "{{count}} ausgewählt", "countSelected": "{{count}} ausgewählt",
"mood": "Stimmung" "mood": "Stimmung",
"example": "Beispiel",
"rename": "Umbenennen",
"filter_single": "einzeln",
"filter_multiple": "mehrfach",
"retry": "Wiederholen",
"newVersionAvailable": "Eine neue Version ist verfügbar",
"numberOfResults": "{{numberOfResults}} Ergebnisse"
}, },
"error": { "error": {
"remotePortWarning": "Starten Sie den Server neu, um den neuen Port anzuwenden", "remotePortWarning": "Starten Sie den Server neu, um den neuen Port anzuwenden",
@@ -182,7 +197,11 @@
"saveQueueFailed": "Wiedergabeliste konnte nicht gespeichert werden", "saveQueueFailed": "Wiedergabeliste konnte nicht gespeichert werden",
"multipleServerSaveQueueError": "die Wiedergabeliste enthält einen oder mehrere Titel, die nicht vom aktuellen Server stammen. dies wird nicht unterstützt", "multipleServerSaveQueueError": "die Wiedergabeliste enthält einen oder mehrere Titel, die nicht vom aktuellen Server stammen. dies wird nicht unterstützt",
"noNetwork": "Server nicht verfügbar", "noNetwork": "Server nicht verfügbar",
"noNetworkDescription": "Verbindung zum Server konnte nicht hergestellt werden" "noNetworkDescription": "Verbindung zum Server konnte nicht hergestellt werden",
"invalidJson": "JSON ungültig",
"serverLockSingleServer": "Nur ein Server ist erlaubt, wenn der Server gesperrt ist",
"settingsSyncError": "Es wurden Unstimmigkeiten zwischen den Einstellungen im Renderer und dem Hauptprozess gefunden. Starte die Anwendung neu, um die Änderungen zu übernehmen",
"playbackPausedDueToError": "Die Wiedergabe wurde aufgrund eines Fehlers pausiert"
}, },
"filter": { "filter": {
"mostPlayed": "Meistgespielt", "mostPlayed": "Meistgespielt",
@@ -223,11 +242,13 @@
"criticRating": "Kritikerbewertung", "criticRating": "Kritikerbewertung",
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
"trackNumber": "Track", "trackNumber": "Track",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel,{\"count\":2})",
"owner": "$t(common.owner)", "owner": "$t(common.owner)",
"genre": "$t(entity.genre, {\"count\": 1})", "genre": "$t(entity.genre, {\"count\": 1})",
"artist": "$t(entity.artist, {\"count\": 1})", "artist": "$t(entity.artist, {\"count\": 1})",
"explicitStatus": "$t(common.explicitStatus)" "explicitStatus": "$t(common.explicitStatus)",
"matchAnd": "und",
"matchOr": "oder"
}, },
"form": { "form": {
"deletePlaylist": { "deletePlaylist": {
@@ -252,11 +273,14 @@
"input_name": "Servername", "input_name": "Servername",
"success": "Server erfolgreich hinzugefügt", "success": "Server erfolgreich hinzugefügt",
"input_savePassword": "Passwort speichern", "input_savePassword": "Passwort speichern",
"ignoreSsl": "SSL ignorieren $t(common.restartRequired)", "ignoreSsl": "SSL ignorieren ($t(common.restartRequired))",
"ignoreCors": "CORS ignorieren $t(common.restartRequired)", "ignoreCors": "CORS ignorieren ($t(common.restartRequired))",
"error_savePassword": "Beim Speichern des Passworts ist ein Fehler aufgetreten", "error_savePassword": "Beim Speichern des Passworts ist ein Fehler aufgetreten",
"input_preferInstantMix": "Instant-Mix bevorzugen", "input_preferInstantMix": "Instant-Mix bevorzugen",
"input_preferInstantMixDescription": "nur Instant-Mix verwenden, um ähnliche Songs zu erhalten. Nützlich bei Verwendung von Plugins, die in dieses Verhalten eingreifen" "input_preferInstantMixDescription": "nur Instant-Mix verwenden, um ähnliche Songs zu erhalten. Nützlich bei Verwendung von Plugins, die in dieses Verhalten eingreifen",
"input_preferRemoteUrl": "öffentliche URL bevorzugen",
"input_remoteUrl": "öffentliche URL",
"input_remoteUrlPlaceholder": "Optional: öffentliche URL für externe Funktionen"
}, },
"addToPlaylist": { "addToPlaylist": {
"success": "$t(entity.trackWithCount, {\"count\": {{message}} }) zu $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} }) hinzugefügt", "success": "$t(entity.trackWithCount, {\"count\": {{message}} }) zu $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} }) hinzugefügt",
@@ -282,8 +306,7 @@
"editPlaylist": { "editPlaylist": {
"title": "Bearbeite $t(entity.playlist, {\"count\": 1})", "title": "Bearbeite $t(entity.playlist, {\"count\": 1})",
"success": "$t(entity.playlist, {\"count\": 1}) erfolgreich aktualisiert", "success": "$t(entity.playlist, {\"count\": 1}) erfolgreich aktualisiert",
"publicJellyfinNote": "Jellyfin legt aus irgendwelchen Gründen nicht offen ob eine Playlist öffentlich ist oder nicht. Wenn du möchtest, dass sie öffentlich bleibt, wähle bitte diese Option aus", "publicJellyfinNote": "Jellyfin legt aus irgendwelchen Gründen nicht offen ob eine Wiedergabeliste öffentlich ist oder nicht. Wenn du möchtest, dass sie öffentlich bleibt, wähle bitte diese Option aus"
"editNote": "Manuelles Bearbeiten wird für große Wiedergabelisten nicht empfohlen. Bist Du sicher, dass Du die aktuelle Wiedergabeliste unter dem Risiko von Datenverlust überschrieben möchtest?"
}, },
"lyricSearch": { "lyricSearch": {
"title": "Songtext Suche", "title": "Songtext Suche",
@@ -296,7 +319,9 @@
"expireInvalid": "Ablaufdatum muss in der Zukunft liegen", "expireInvalid": "Ablaufdatum muss in der Zukunft liegen",
"allowDownloading": "Herunterladen zulassen", "allowDownloading": "Herunterladen zulassen",
"success": "Link in die Zwischenablage kopiert (oder hier klicken, um zu öffnen)", "success": "Link in die Zwischenablage kopiert (oder hier klicken, um zu öffnen)",
"createFailed": "fehler beim Teilen (Ist Teilen aktiviert?)" "createFailed": "fehler beim Teilen (Ist Teilen aktiviert?)",
"copyToClipboard": "In Zwischenablage kopieren: Strg+C, Enter",
"successMustClick": "Freigabe erfolgreich erstellt. Hier klicken um diese zu öffnen"
}, },
"privateMode": { "privateMode": {
"enabled": "Privatmodus aktiviert, Wiedergabe-Status wird externen Quellen nicht preisgegeben", "enabled": "Privatmodus aktiviert, Wiedergabe-Status wird externen Quellen nicht preisgegeben",
@@ -329,7 +354,12 @@
"input_streamUrl": "Stream URL" "input_streamUrl": "Stream URL"
}, },
"lyricsExport": { "lyricsExport": {
"input_offset": "$t(setting.lyricOffset)" "input_offset": "$t(setting.lyricOffset)",
"export": "Songtexte exportieren",
"input_synced": "Synchronisierte Songtexte exportieren"
},
"editRadioStation": {
"success": "Radiosender erfolgreich aktualisiert"
} }
}, },
"entity": { "entity": {
@@ -378,7 +408,8 @@
"view": { "view": {
"table": "Tabelle", "table": "Tabelle",
"grid": "Raster", "grid": "Raster",
"list": "Liste" "list": "Liste",
"detail": "Detail"
}, },
"general": { "general": {
"tableColumns": "Tabellenspalten", "tableColumns": "Tabellenspalten",
@@ -397,7 +428,20 @@
"size_large": "groß", "size_large": "groß",
"pagination": "Seitenzahlen", "pagination": "Seitenzahlen",
"pagination_itemsPerPage": "Elemente pro Seite", "pagination_itemsPerPage": "Elemente pro Seite",
"pagination_infinite": "unendlich" "pagination_infinite": "unendlich",
"moveUp": "nach oben",
"moveDown": "nach unten",
"pinToLeft": "links anheften",
"pinToRight": "rechts anheften",
"itemGap": "Item Abstand (px)",
"itemSize": "Item Größe (px)",
"itemsPerRow": "Items pro Zeile",
"pagination_paginate": "paginiert",
"alternateRowColors": "Zeilenfarben abwechseln",
"horizontalBorders": "Zeilenbegrenzungen",
"rowHoverHighlight": "Zeilenhervorhebungen beim hovern",
"showHeader": "Spaltenüberschrift anzeigen",
"verticalBorders": "Spaltenbegrenzungen"
}, },
"label": { "label": {
"dateAdded": "Hinzugefügt am", "dateAdded": "Hinzugefügt am",
@@ -409,13 +453,13 @@
"albumArtist": "$t(entity.albumArtist, {\"count\": 1})", "albumArtist": "$t(entity.albumArtist, {\"count\": 1})",
"artist": "$t(entity.artist, {\"count\": 1})", "artist": "$t(entity.artist, {\"count\": 1})",
"favorite": "$t(common.favorite)", "favorite": "$t(common.favorite)",
"actions": "$t(common.action_other)", "actions": "$t(common.action,{\"count\":2})",
"genre": "$t(entity.genre, {\"count\": 1})", "genre": "$t(entity.genre, {\"count\": 1})",
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
"size": "$t(common.size)", "size": "$t(common.size)",
"bpm": "$t(common.bpm)", "bpm": "$t(common.bpm)",
"titleCombined": "$t(common.title) (kombiniert)", "titleCombined": "$t(common.title) (kombiniert)",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel,{\"count\":2})",
"duration": "$t(common.duration)", "duration": "$t(common.duration)",
"note": "$t(common.note)", "note": "$t(common.note)",
"owner": "$t(common.owner)", "owner": "$t(common.owner)",
@@ -432,7 +476,9 @@
"image": "Bild", "image": "Bild",
"sampleRate": "$t(common.sampleRate)", "sampleRate": "$t(common.sampleRate)",
"songCount": "$t(entity.track, {\"count\": 2})", "songCount": "$t(entity.track, {\"count\": 2})",
"genreBadge": "$t(entity.genre, {\"count\": 1}) (Abzeichen)" "genreBadge": "$t(entity.genre, {\"count\": 1}) (Abzeichen)",
"composer": "Komponist",
"titleArtist": "$t(common.title) (Interpret)"
} }
}, },
"column": { "column": {
@@ -450,7 +496,7 @@
"rating": "Bewertung", "rating": "Bewertung",
"albumCount": "$t(entity.album, {\"count\": 2})", "albumCount": "$t(entity.album, {\"count\": 2})",
"artist": "$t(entity.artist, {\"count\": 1})", "artist": "$t(entity.artist, {\"count\": 1})",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel,{\"count\":2})",
"comment": "Kommentar", "comment": "Kommentar",
"dateAdded": "hinzugefügt am", "dateAdded": "hinzugefügt am",
"playCount": "Abgespielt", "playCount": "Abgespielt",
@@ -597,7 +643,8 @@
"transcoding": "Transcoding", "transcoding": "Transcoding",
"logger": "Logger", "logger": "Logger",
"playerFilters": "Player-Filter", "playerFilters": "Player-Filter",
"remote": "Fernsteuerung" "remote": "Fernsteuerung",
"lyricsDisplay": "Songtexte Anzeige"
}, },
"albumArtistList": { "albumArtistList": {
"title": "$t(entity.albumArtist, {\"count\": 2})" "title": "$t(entity.albumArtist, {\"count\": 2})"
@@ -633,7 +680,9 @@
"groupingTypeAll": "alle Veröffentlichungsformate", "groupingTypeAll": "alle Veröffentlichungsformate",
"groupingTypePrimary": "primäre Veröffentlichungsformate", "groupingTypePrimary": "primäre Veröffentlichungsformate",
"favoriteSongs": "Lieblingssongs", "favoriteSongs": "Lieblingssongs",
"favoriteSongsFrom": "Liebslingssongs von {{title}}" "favoriteSongsFrom": "Liebslingssongs von {{title}}",
"topSongsCommunity": "Community",
"topSongsPersonal": "Persönlich"
}, },
"manageServers": { "manageServers": {
"title": "Servers verwalten", "title": "Servers verwalten",
@@ -665,7 +714,13 @@
"privateMode": "(Privater Modus)" "privateMode": "(Privater Modus)"
}, },
"collections": { "collections": {
"saveAsCollection": "Als Sammlung speichern" "saveAsCollection": "Als Sammlung speichern",
"overrideExisting": "Bestehende überschreiben"
},
"releasenotes": {
"commitsSinceStable": "Commits seit {{stable}}",
"noStableReleaseToCompare": "Kein stable Relase zum vergleichen verfügbar",
"noNewCommits": "keine neuen Beiträge in diesem Bereich"
} }
}, },
"player": { "player": {
@@ -692,7 +747,7 @@
"queue_moveToBottom": "Ausgewählte nach oben verschieben", "queue_moveToBottom": "Ausgewählte nach oben verschieben",
"shuffle_off": "Zufallswiedergabe deaktiviert", "shuffle_off": "Zufallswiedergabe deaktiviert",
"stop": "stopp", "stop": "stopp",
"toggleFullscreenPlayer": "vollbildmodus", "toggleFullscreenPlayer": "Vollbildmodus",
"skip_back": "zurückspulen", "skip_back": "zurückspulen",
"pause": "Pause", "pause": "Pause",
"unfavorite": "Aus Favoriten entfernen", "unfavorite": "Aus Favoriten entfernen",
@@ -705,10 +760,22 @@
"holdToShuffle": "Halten für Zufallswiedergabe", "holdToShuffle": "Halten für Zufallswiedergabe",
"restoreQueueFromServer": "Wiedergabeliste von Server wiederherstellen", "restoreQueueFromServer": "Wiedergabeliste von Server wiederherstellen",
"saveQueueToServer": "Wiedergabeliste auf Server speichern", "saveQueueToServer": "Wiedergabeliste auf Server speichern",
"lyrics": "Songtexte" "lyrics": "Songtexte",
"artistRadio": "Künstler Radio",
"sleepTimer_endOfSong": "Ende des aktuellen Liedes",
"sleepTimer_off": "aus",
"sleepTimer_timeRemaining": "{{time}} verbleibend",
"sleepTimer_cancel": "Timer abbrechen",
"sleepTimer_setCustom": "Timer stellen",
"sleepTimer": "Sleep Timer",
"sleepTimer_custom": "Benutzerdefiniert",
"sleepTimer_hours": "{{count}} std",
"sleepTimer_minutes": "{{count}} Min",
"trackRadio": "Song Radio",
"albumRadio": "Album Radio"
}, },
"setting": { "setting": {
"audioDevice_description": "wählen Sie das Audiogerät aus, das für die Wiedergabe verwendet werden soll (nur Webplayer)", "audioDevice_description": "das für die Wiedergabe zu verwendende Audiogerät auswählen",
"audioExclusiveMode": "Audio-Exklusivmodus", "audioExclusiveMode": "Audio-Exklusivmodus",
"audioDevice": "Audiogerät", "audioDevice": "Audiogerät",
"accentColor": "Akzentfarbe", "accentColor": "Akzentfarbe",
@@ -726,7 +793,7 @@
"crossfadeDuration": "Dauer der Überblendung", "crossfadeDuration": "Dauer der Überblendung",
"discordIdleStatus": "rich presence status im Leerlauf", "discordIdleStatus": "rich presence status im Leerlauf",
"audioPlayer": "Audio-Player", "audioPlayer": "Audio-Player",
"discordApplicationId": "{{discord}} Anwendungs ID", "discordApplicationId": "{{discord}} Anwendungs-ID",
"customFontPath_description": "Legt den Pfad zur benutzerdefinierten Schriftart fest, welche für die Anwendung verwendet werden soll", "customFontPath_description": "Legt den Pfad zur benutzerdefinierten Schriftart fest, welche für die Anwendung verwendet werden soll",
"remotePort_description": "Legt den Port des Fernsteuerungsserver fest", "remotePort_description": "Legt den Port des Fernsteuerungsserver fest",
"hotkey_skipBackward": "rückwärts springen", "hotkey_skipBackward": "rückwärts springen",
@@ -801,8 +868,8 @@
"fontType_description": "Die integrierte Schriftart wählt eine der von feishin bereitgestellten Schriftarten aus. Mit der Systemschriftart können Sie jede von Ihrem Betriebssystem bereitgestellte Schriftart auswählen. Benutzerdefiniert erlaubt es eine eigene Schriftart bereitzustellen", "fontType_description": "Die integrierte Schriftart wählt eine der von feishin bereitgestellten Schriftarten aus. Mit der Systemschriftart können Sie jede von Ihrem Betriebssystem bereitgestellte Schriftart auswählen. Benutzerdefiniert erlaubt es eine eigene Schriftart bereitzustellen",
"playButtonBehavior": "Verhalten der Wiedergabetaste", "playButtonBehavior": "Verhalten der Wiedergabetaste",
"volumeWheelStep": "Lautstärkeänderung mit Mausrad", "volumeWheelStep": "Lautstärkeänderung mit Mausrad",
"sidebarPlaylistList_description": "Ein- oder Ausblenden der Playlisten-Liste in der Seitenleiste", "sidebarPlaylistList_description": "Ein- oder Ausblenden der Wiedergabelisten in der Seitenleiste",
"sidebarPlaylistSorting_description": "sortiere Playlists in der Seitenleiste per Drag & Drop anstelle der standardmäßigen Serverreihenfolge", "sidebarPlaylistSorting_description": "sortiere Wiedergabelisten in der Seitenleiste per Drag & Drop anstelle der standardmäßigen Serverreihenfolge",
"sidePlayQueueStyle_description": "legt den Stil der Wiedergabeliste in der Seitenleiste fest", "sidePlayQueueStyle_description": "legt den Stil der Wiedergabeliste in der Seitenleiste fest",
"replayGainMode": "{{ReplayGain}} Modus", "replayGainMode": "{{ReplayGain}} Modus",
"playbackStyle_optionNormal": "Normal", "playbackStyle_optionNormal": "Normal",
@@ -817,7 +884,7 @@
"useSystemTheme_description": "Folgt dem hellen oder dunklen Erscheinungsbild des Systems", "useSystemTheme_description": "Folgt dem hellen oder dunklen Erscheinungsbild des Systems",
"playButtonBehavior_optionAddNext": "$t(player.addNext)", "playButtonBehavior_optionAddNext": "$t(player.addNext)",
"lyricFetch_description": "Songtexte aus verschiedenen Internetquellen abrufen", "lyricFetch_description": "Songtexte aus verschiedenen Internetquellen abrufen",
"lyricFetchProvider_description": "Wählen Sie die Anbieter aus, von denen Sie Liedtexte abrufen möchten. Die Reihenfolge der Anbieter ist die Reihenfolge, in der sie abgefragt werden", "lyricFetchProvider_description": "Wähle den Anbieter zum Abrufen von Songtexten aus",
"globalMediaHotkeys_description": "aktivieren oder deaktivieren Sie die Verwendung der Medien-Kurzbefehle Ihres Systems zur Steuerung der Wiedergabe", "globalMediaHotkeys_description": "aktivieren oder deaktivieren Sie die Verwendung der Medien-Kurzbefehle Ihres Systems zur Steuerung der Wiedergabe",
"hotkey_zoomOut": "Herauszoomen", "hotkey_zoomOut": "Herauszoomen",
"hotkey_unfavoriteCurrentSong": "$t(common.currentSong) aus Favoriten entfernen", "hotkey_unfavoriteCurrentSong": "$t(common.currentSong) aus Favoriten entfernen",
@@ -826,10 +893,10 @@
"remoteUsername": "Benutzername des Fernsteuerungsserver", "remoteUsername": "Benutzername des Fernsteuerungsserver",
"hotkey_browserBack": "Browser zurück", "hotkey_browserBack": "Browser zurück",
"showSkipButton": "Schaltflächen zum Überspringen anzeigen", "showSkipButton": "Schaltflächen zum Überspringen anzeigen",
"sidebarPlaylistList": "Seitenleiste Playlisten-Liste", "sidebarPlaylistList": "Wiedergabelisten in Seitenleiste",
"sidebarPlaylistSorting": "Playlist-Sortierung in der Seitenleiste", "sidebarPlaylistSorting": "Wiedergabelisten-Sortierung in der Seitenleiste",
"minimizeToTray": "Zur Taskleiste minimieren", "minimizeToTray": "Zur Taskleiste minimieren",
"skipPlaylistPage": "Playlisten-Seite überspringen", "skipPlaylistPage": "Wiedergabeliste-Seite überspringen",
"themeDark": "Erscheinungsbild (dunkel)", "themeDark": "Erscheinungsbild (dunkel)",
"sidebarCollapsedNavigation": "Navigation in der Seitenleiste (komprimiert)", "sidebarCollapsedNavigation": "Navigation in der Seitenleiste (komprimiert)",
"gaplessAudio_optionWeak": "schwach (empfohlen)", "gaplessAudio_optionWeak": "schwach (empfohlen)",
@@ -856,7 +923,7 @@
"sidePlayQueueStyle_optionDetached": "lösgelöst", "sidePlayQueueStyle_optionDetached": "lösgelöst",
"windowBarStyle_description": "Legt das Erscheinungsbild des Fensterrahmens fest", "windowBarStyle_description": "Legt das Erscheinungsbild des Fensterrahmens fest",
"hotkey_toggleCurrentSongFavorite": "$t(common.currentSong) zu Favoriten hinzufügen", "hotkey_toggleCurrentSongFavorite": "$t(common.currentSong) zu Favoriten hinzufügen",
"clearQueryCache_description": "\"Weiches\" Zurücksetzen. Dies wird Playlisten, Musik-Metadaten und gespeicherte Liedtexte zurücksetzen, Zugangsinformationen und zwischengespeicherte Bilder werden behalten", "clearQueryCache_description": "\"Weiches\" Zurücksetzen. Dies wird Wiedergabelisten, Musik-Metadaten und gespeicherte Songtexte zurücksetzen, Zugangsinformationen und zwischengespeicherte Bilder werden behalten",
"discordRichPresence_description": "Aktiviert den Wiedergabestatus in {{discord}} Rich Presence. Angezeigte Bilder sind: {{icon}}, {{playing}}, und {{paused}}", "discordRichPresence_description": "Aktiviert den Wiedergabestatus in {{discord}} Rich Presence. Angezeigte Bilder sind: {{icon}}, {{playing}}, und {{paused}}",
"clearCache": "Browser-Zwischenspeicher löschen", "clearCache": "Browser-Zwischenspeicher löschen",
"clearQueryCache": "feishins Zwischenspeicher leeren", "clearQueryCache": "feishins Zwischenspeicher leeren",
@@ -873,7 +940,7 @@
"discordListening_description": "Status als hört zu statt als spielt anzeigen", "discordListening_description": "Status als hört zu statt als spielt anzeigen",
"lastfm": "zeige last.fm links", "lastfm": "zeige last.fm links",
"lastfm_description": "zeige links zu Last.fm auf dem Künstler/Album-Seiten", "lastfm_description": "zeige links zu Last.fm auf dem Künstler/Album-Seiten",
"musicbrainz": "Zeig MusicBrainz links", "musicbrainz": "Zeige MusicBrainz links",
"customCssEnable": "benutzerdefiniertes CSS aktivieren", "customCssEnable": "benutzerdefiniertes CSS aktivieren",
"albumBackground_description": "fügt ein Hintergrundbild für die Albumseiten hinzu, welche das Albumcover zeigen", "albumBackground_description": "fügt ein Hintergrundbild für die Albumseiten hinzu, welche das Albumcover zeigen",
"albumBackgroundBlur": "Größe der Album-Bildunschärfe", "albumBackgroundBlur": "Größe der Album-Bildunschärfe",
@@ -946,7 +1013,7 @@
"transcodeFormat": "Format für Umwandlung", "transcodeFormat": "Format für Umwandlung",
"startMinimized_description": "Startet die Anwendung im Info-Bereich", "startMinimized_description": "Startet die Anwendung im Info-Bereich",
"startMinimized": "Im Info-Bereich starten", "startMinimized": "Im Info-Bereich starten",
"mediaSession_description": "Aktiviert die Windows Media Session-Integration, zeigt Mediensteuerelemente und Metadaten im Systemlautstärke-Overlay und auf dem Sperrbildschirm an (nur Windows)", "mediaSession_description": "aktiviert die Media Session Integration. Dies ermöglicht die Steuerung und Anzeige der Medien in der Systemlautstärkeoption und auf dem Sperrbildschirm",
"mediaSession": "Media Session aktivieren", "mediaSession": "Media Session aktivieren",
"artistBackgroundBlur": "Unschärfegrad für Künstlerhintergründe", "artistBackgroundBlur": "Unschärfegrad für Künstlerhintergründe",
"artistBackgroundBlur_description": "Legt den Grad der Unschärfe fest, der auf das Hintergrundbild des Künstlers angewendet wird", "artistBackgroundBlur_description": "Legt den Grad der Unschärfe fest, der auf das Hintergrundbild des Künstlers angewendet wird",
@@ -954,11 +1021,11 @@
"contextMenu_description": "Legt die Einträge fest, die im Rechtsklick-Menü angezeigt werden sollen. Abgewählte Einträge werden ausgeblendet", "contextMenu_description": "Legt die Einträge fest, die im Rechtsklick-Menü angezeigt werden sollen. Abgewählte Einträge werden ausgeblendet",
"crossfadeStyle": "Art der Überblende", "crossfadeStyle": "Art der Überblende",
"customCss_description": "Benutzerdefinierter CSS-Inhalt. Hinweis: Inhalte und Remote-URLs sind nicht zulässige Eigenschaften. Unten siehst du eine Vorschau deines Inhalts. Aufgrund von Bereinigung werden womöglich zusätzliche, nicht von dir definierte Felder angezeigt", "customCss_description": "Benutzerdefinierter CSS-Inhalt. Hinweis: Inhalte und Remote-URLs sind nicht zulässige Eigenschaften. Unten siehst du eine Vorschau deines Inhalts. Aufgrund von Bereinigung werden womöglich zusätzliche, nicht von dir definierte Felder angezeigt",
"customCssNotice": "Warnung: Obwohl eine gewisse Bereinigung erfolgt (url() und content: sind nicht zulässig), kann die Verwendung von benutzerdefiniertem CSS dennoch Risiken mit sich bringen, da dadurch die Benutzeroberfläche verändert wird", "customCssNotice": "Warnung: Obwohl eine gewisse Bereinigung erfolgt (nicht zulässig sind z. B. \"url()\" und \"content:\"), kann ein benutzerdefiniertes CSS Risiken mit sich bringen, da die Benutzeroberfläche dadurch verändert wird",
"releaseChannel_optionBeta": "Beta", "releaseChannel_optionBeta": "Beta",
"releaseChannel_optionLatest": "Stabil", "releaseChannel_optionLatest": "Stabil",
"releaseChannel": "Veröffentlichungskanal", "releaseChannel": "Veröffentlichungskanal",
"releaseChannel_description": "Zwischen stabilen und beta Veröffentlichungen für automatische Aktualisierungen wählen", "releaseChannel_description": "zwischen stabilen, Beta- oder Alpha-Versionen (Nightly) für automatische Updates wählen",
"discordDisplayType_artistname": "Künstlername(n)", "discordDisplayType_artistname": "Künstlername(n)",
"discordDisplayType_description": "Ändert den aktuellen Titel im Zuhör-Status", "discordDisplayType_description": "Ändert den aktuellen Titel im Zuhör-Status",
"discordDisplayType_songname": "Songtitel", "discordDisplayType_songname": "Songtitel",
@@ -990,7 +1057,81 @@
"imageResolution": "Bildauflösung", "imageResolution": "Bildauflösung",
"imageResolution_optionTable": "Tabelle", "imageResolution_optionTable": "Tabelle",
"imageResolution_optionSidebar": "Seitenleiste", "imageResolution_optionSidebar": "Seitenleiste",
"preservePitch": "Tonhöhe erhalten" "preservePitch": "Tonhöhe erhalten",
"analyticsEnable": "Nutzungsbasierte Analyse senden",
"automaticUpdates": "Automatische Updates",
"automaticUpdates_description": "Updates automatisch suchen und installieren",
"releaseChannel_optionAlpha": "Alpha (nightly)",
"useThemeAccentColor": "Akzentfarbe des Themas nutzen",
"analyticsEnable_description": "Anonymisierte Nutzungsdaten werden an den Entwickler gesendet, um die Anwendung zu verbessern",
"artistReleaseTypeConfiguration_description": "Konfigurieren, welche Release-Typen und in welcher Reihenfolge diese auf der Album-Künstlerseite angezeigt werden",
"homeConfiguration_description": "Konfigurieren, welche Elemente und in welcher Reihenfolge diese auf der Startseite angezeigt werden",
"passwordStore_description": "Verwendeter Passwort/Geheimnis Speicher. Sollten Probleme beim Speichern von Passwörtern auftreten, wähle eine andere Methode",
"passwordStore": "Passwort/Geheimnis Speicher",
"audioFadeOnStatusChange_description": "ermöglicht Ein- und Ausblenden, wenn sich der Wiedergabe-/Pause-Status ändert",
"audioFadeOnStatusChange": "Audio Ein-/Ausblenden bei Statusveränderung",
"showRatings_description": "Aktiviere die Anzeige einer Bewertung in Sternen",
"showRatings": "Zeige Sternebewertungen",
"blurExplicitImages": "Explizite Bilder unkenntlich machen",
"blurExplicitImages_description": "Album- und Song-Cover, die als explizit gekennzeichnet sind, werden unscharf dargestellt",
"enableGridMultiSelect": "Raster-Mehrfachauswahl aktivieren",
"enableGridMultiSelect_description": "Wenn aktiviert, können in Rasteransichten mehrere Elemente ausgewählt werden. Wenn deaktiviert, führt ein Klick auf Rasterelement-Bilder zur Artikelseite",
"playerbarOpenDrawer_description": "Ermöglicht das Anklicken der Playerleiste, um den Vollbild-Player zu öffnen",
"playerbarOpenDrawer": "Playerleiste Vollbild-Umschalter",
"playerbarSlider": "Playerleiste-Schieberegler",
"playerbarSlider_description": "Die Wellenform Darstellung wird nicht empfohlen, wenn eine langsame oder tarifierte Internetverbindung genutzt wird",
"playerbarSliderType_optionSlider": "Schieberegler",
"playerbarSliderType_optionWaveform": "Wellenform",
"playerbarWaveformAlign": "Wellenform ausrichten",
"playerbarWaveformBarWidth": "Breite der Wellenform Leiste",
"playerbarWaveformGap": "Wellenform Lücke",
"playerbarWaveformRadius": "Wellenform Radius",
"artistRadioCount": "Interpreten/Song Radio Länge",
"artistRadioCount_description": "legt die Anzahl der Songs fest, die beim Interpreten-Radio und Song-Radio abgerufen werden",
"sidebarPlaylistListFilterRegex_description": "versteckt Wiedergabelisten in der Seitenleiste, die diesem regulären Ausdruck entsprechen",
"sidebarPlaylistListFilterRegex_placeholder": "z.B. ^Täglicher Mix.*",
"sidebarPlaylistListFilterRegex": "Wiedergabelisten Regex-Filter",
"showVisualizerInSidebar_description": "Ein Panel wird zur Player-Seitenleiste hinzugefügt, das den Visualizer anzeigt",
"showVisualizerInSidebar": "Visualizer in Seitenleiste anzeigen",
"combinedLyricsAndVisualizer_description": "Songtexte und Visualizer im selben Panel anzeigen",
"combinedLyricsAndVisualizer": "Songtexte und Visualizer geimeinsam in der Seitenleiste anzeigen",
"mpvExtraParameters_description": "zusätzliche Argumente die an mpv übergeben werden sollen",
"mpvExtraParameters_help": "Eins pro Zeile",
"pathReplace": "Dateipfad-Ersetzung",
"pathReplace_description": "Ersetze den Standard Dateipfad des Servers",
"pathReplace_optionRemovePrefix": "Präfix entfernen",
"pathReplace_optionAddPrefix": "Präfix hinzufügen",
"imageResolution_description": "Die Auflösung für die in der App verwendeten Bilder. Bei einem Wert von 0 wird die originale Bildauflösung verwendet",
"preservePitch_description": "Behält beim Anpassen der Wiedergabegeschwindigkeit die Tonhöhe bei",
"preventSleepOnPlayback_description": "Verhindert das Abschalten des Displays während der Musikwiedergabe",
"preventSleepOnPlayback": "Verhindert den Energiesparmodus während der Musikwiedergabe",
"trayEnabled_description": "Tray-Symbol anzeigen/verbergen. Bei Deaktivierung werden auch Minimieren/Beenden zum Tray deaktiviert",
"queryBuilder": "Abfrage-Editor",
"queryBuilderCustomFields_inputLabel": "Label",
"queryBuilderCustomFields_description": "Füge benutzerdefinierte Felder für den Abfrage-Editor hinzu",
"autosave": "Automatisch aktuelle Wiedergabeliste speichern",
"autosave_description": "Aktiviere die automatische Speicherung der aktuellen Wiedergabe auf dem Server. Diese Funktion ist nur bei Navidrome/Subsonic Servern verfügbar und es darf sich nicht um eine gemischte Wiedergabeliste handeln.",
"autosaveCount": "Häufigkeit der automatischen Speicherung bei Wiedergabelisten",
"autosaveCount_description": "Wieviele Lieder gespielt werden, bevor die Wiedergabeliste gespeichert wird. 1 (Minimum) bedeutet die Speicherung nach jedem gespielten Lied",
"useThemeAccentColor_description": "Verwendet die Primärfarbe des gewählten Themas anstatt einer ausgewählten Akzentfarbe",
"useThemePrimaryShade": "Primärschatten des Themas nutzen",
"useThemePrimaryShade_description": "Verwendet den Primärschatten des ausgewählten Themas als primäre Farbvarianten",
"primaryShade": "Primärschatten",
"listenbrainz": "ListenBrainz Links anzeigen",
"listenbrainz_description": "Zeige Links zu ListenBrainz auf den Interpreten/Alben Seiten",
"mpvExtraParameters": "Zusätzliche mpv Parameter",
"qobuz": "Qobuz Links anzeigen",
"spotify": "Spotify Links anzeigen",
"nativeSpotify": "Spotify App benutzen",
"qobuz_description": "Zeige Links zu Qobuz auf den Interpreten/Alben Seiten",
"spotify_description": "Zeige Links zu Spotify auf den Interpreten/Alben Seiten",
"artistReleaseTypeConfiguration": "Interpreten Release Typ Einstellung",
"discordStateIcon": "Play Icon anzeigen",
"homeFeatureStyle_optionSingle": "Einzeln",
"nativeSpotify_description": "in der Spotify App statt im Browser öffnen",
"imageResolution_optionFullScreenPlayer": "Wiedergabe im Vollbildmodus",
"sidePlayQueueLayout_optionHorizontal": "horizontal",
"sidePlayQueueLayout_optionVertical": "vertikal"
}, },
"dragDropZone": { "dragDropZone": {
"error_oneFileOnly": "Bitte wähle nur 1 Datei", "error_oneFileOnly": "Bitte wähle nur 1 Datei",
@@ -1050,5 +1191,112 @@
"secondShort": "Sek", "secondShort": "Sek",
"hourShort": "Std", "hourShort": "Std",
"dayShort": "Tag" "dayShort": "Tag"
},
"visualizer": {
"options": {
"weightingFilter": {
"z": "Z",
"d": "D",
"c": "C",
"none": "Keine",
"a": "A",
"b": "B"
},
"frequencyScale": {
"linear": "Lineare Skala",
"log": "Log Skala",
"mel": "Mel Skala",
"bark": "Bark-Skala",
"none": "Keine"
},
"gradient": {
"classic": "Klassisch",
"prism": "Prisma",
"rainbow": "Regenbogen",
"steelblue": "Stahlblau",
"orangered": "Orange-Rot"
},
"channelLayout": {
"dualHorizontal": "Dual-Horizontal",
"dualVertical": "Dual-Vertikal"
}
},
"minimumFrequency": "Minimale Frequenz",
"minimumDecibels": "Minimale Dezibel",
"visualizerType": "Visualizer Art",
"cyclePresets": "Vorlagen durchrotieren",
"cycleTime": "Abspieldauer je Vorlage (Sekunden)",
"includeAllPresets": "Alle Vorlagen verwenden",
"ignoredPresets": "Ignorierte Vorlagen",
"selectedPresets": "Ausgewählte Vorlagen",
"randomizeNextPreset": "Nächste Vorlage zufällig wählen",
"blendTime": "Übergangsdauer",
"presets": "Vorlage",
"selectPreset": "Vorlage auswählen",
"applyPreset": "Vorlage anwenden",
"saveAsPreset": "Als Vorlage speichern",
"updatePreset": "Vorlage aktualisieren",
"copyConfiguration": "Konfiguration kopieren",
"pasteConfiguration": "Konfiguration einfügen",
"pasteConfigurationPlaceholder": "JSON Konfiguration hier einfügen...",
"pasteFromClipboard": "Aus Zwischenablage einfügen",
"applyConfiguration": "Konfiguration anwenden",
"configCopied": "Konfiguration in Zwischenablage kopiert",
"configCopyFailed": "Konfiguration konnte nicht kopiert werden",
"configPasted": "Konfiguration erfolgreich angewandt",
"configPasteFailed": "Konfiguration konnte nicht angewandt werden. Bitte Format überprüfen.",
"configPasteReadFailed": "Zwischenablage konnte nicht ausgelesen werden",
"presetName": "Vorlagen Name",
"presetNamePlaceholder": "Name der Vorlage eingeben",
"general": "Allgemein",
"mode": "Modus",
"mode1To8": "Modus 1 - 8",
"mode10": "Modus 10",
"lineWidth": "Linienbreite",
"channelLayout": "Kanallayout",
"maxFPS": "Max FPS",
"opacity": "Deckkraft",
"customGradients": "Benutzerdefinierter Farbverlauf",
"addCustomGradient": "Benutzerdefinierten Gradienten hinzufügen",
"gradientName": "Name Farbverlauf",
"gradientNamePlaceholder": "Name Farbverlauf",
"vertical": "Vertikal",
"horizontal": "Horizontal",
"addColor": "Farbe hinzufügen",
"position": "Position",
"level": "Ebene",
"remove": "Entfernen",
"pasteGradient": "Gradient einfügen",
"pasteGradientPlaceholder": "Gradient JSON hier einfügen...",
"custom": "Benutzerdefiniert",
"builtIn": "Eingebaut",
"colors": "Farben",
"colorMode": "Farbmodus",
"gradient": "Farbverlauf",
"gradientLeft": "Farberverlauf links",
"gradientRight": "Farbverlauf rechts",
"fft": "FFT",
"fftSize": "FFT Größe",
"smoothing": "Glätten",
"frequencyRangeAndScaling": "Frequenzbereich und Skalierung",
"maximumFrequency": "Maximale Frequenz",
"sensitivity": "Empfindlichkeit",
"weightingFilter": "Gewichtungsfilter",
"maximumDecibels": "Maximale Dezibel",
"linearAmplitude": "Linearer Ausschlag",
"linearBoost": "Linearer Boost",
"radialSpectrum": "Radiales Spektrum",
"radial": "Radial",
"radialInvert": "Radial invertiert",
"radius": "Radius",
"miscellaneousSettings": "Verschiedene Einstellungen",
"ansiBands": "ANSI Bänder",
"lowResolution": "Niedrige Auflösung",
"showFPS": "FPS anzeigen",
"fadePeaks": "Spitzen abblenden",
"showPeaks": "Spitzen anzeigen",
"systemAudioConsentAllow": "Erlauben",
"systemAudioConsentDecline": "Ablehnen",
"frequencyScale": "Frequenzskala"
} }
} }
Executable → Regular
+63 -5
View File
@@ -5,6 +5,7 @@
"addOrRemoveFromSelection": "add or remove from selection", "addOrRemoveFromSelection": "add or remove from selection",
"selectRangeOfItems": "select a range of items", "selectRangeOfItems": "select a range of items",
"clearQueue": "clear queue", "clearQueue": "clear queue",
"goToCurrent": "go to current item",
"createPlaylist": "create $t(entity.playlist, {\"count\": 1})", "createPlaylist": "create $t(entity.playlist, {\"count\": 1})",
"createRadioStation": "create $t(entity.radioStation, {\"count\": 1})", "createRadioStation": "create $t(entity.radioStation, {\"count\": 1})",
"deletePlaylist": "delete $t(entity.playlist, {\"count\": 1})", "deletePlaylist": "delete $t(entity.playlist, {\"count\": 1})",
@@ -36,7 +37,10 @@
"openApplicationDirectory": "open application directory", "openApplicationDirectory": "open application directory",
"openIn": { "openIn": {
"lastfm": "Open in Last.fm", "lastfm": "Open in Last.fm",
"musicbrainz": "Open in MusicBrainz" "listenbrainz": "Open in ListenBrainz",
"musicbrainz": "Open in MusicBrainz",
"qobuz": "Open in Qobuz",
"spotify": "Open in Spotify"
} }
}, },
"common": { "common": {
@@ -105,11 +109,13 @@
"minimize": "minimize", "minimize": "minimize",
"modified": "modified", "modified": "modified",
"mbid": "MusicBrainz ID", "mbid": "MusicBrainz ID",
"grouping": "grouping",
"mood": "mood", "mood": "mood",
"name": "name", "name": "name",
"no": "no", "no": "no",
"none": "none", "none": "none",
"noResultsFromQuery": "the query returned no results", "noResultsFromQuery": "the query returned no results",
"numberOfResults": "{{numberOfResults}} results",
"noFilters": "no filters configured", "noFilters": "no filters configured",
"note": "note", "note": "note",
"ok": "ok", "ok": "ok",
@@ -159,7 +165,8 @@
"clean": "clean", "clean": "clean",
"gridRows": "grid rows", "gridRows": "grid rows",
"tableColumns": "table columns", "tableColumns": "table columns",
"itemsMore": "{{count}} more" "itemsMore": "{{count}} more",
"newVersionAvailable": "a new version is available"
}, },
"entity": { "entity": {
"album_one": "album", "album_one": "album",
@@ -211,6 +218,7 @@
"credentialsRequired": "credentials required", "credentialsRequired": "credentials required",
"endpointNotImplementedError": "endpoint {{endpoint}} is not implemented for {{serverType}}", "endpointNotImplementedError": "endpoint {{endpoint}} is not implemented for {{serverType}}",
"genericError": "an error occurred", "genericError": "an error occurred",
"invalidJson": "invalid JSON",
"invalidServer": "invalid server", "invalidServer": "invalid server",
"localFontAccessDenied": "access denied to local fonts", "localFontAccessDenied": "access denied to local fonts",
"loginRateError": "too many login attempts, please try again in a few seconds", "loginRateError": "too many login attempts, please try again in a few seconds",
@@ -222,11 +230,13 @@
"notificationDenied": "permissions for notifications were denied. this setting has no effect", "notificationDenied": "permissions for notifications were denied. this setting has no effect",
"openError": "could not open file", "openError": "could not open file",
"playbackError": "an error occurred when trying to play the media", "playbackError": "an error occurred when trying to play the media",
"playbackPausedDueToError": "playback was paused due to an error",
"remoteDisableError": "an error occurred when trying to $t(common.disable) the remote server", "remoteDisableError": "an error occurred when trying to $t(common.disable) the remote server",
"remoteEnableError": "an error occurred when trying to $t(common.enable) the remote server", "remoteEnableError": "an error occurred when trying to $t(common.enable) the remote server",
"remotePortError": "an error occurred when trying to set the remote server port", "remotePortError": "an error occurred when trying to set the remote server port",
"remotePortWarning": "restart the server to apply the new port", "remotePortWarning": "restart the server to apply the new port",
"saveQueueFailed": "failed to save queue", "saveQueueFailed": "failed to save queue",
"serverLockSingleServer": "only one server is allowed when server is locked",
"serverNotSelectedError": "no server selected", "serverNotSelectedError": "no server selected",
"serverRequired": "server required", "serverRequired": "server required",
"sessionExpiredError": "your session has expired", "sessionExpiredError": "your session has expired",
@@ -236,6 +246,8 @@
"filter": { "filter": {
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
"albumArtist": "$t(entity.albumArtist, {\"count\": 1})", "albumArtist": "$t(entity.albumArtist, {\"count\": 1})",
"matchAnd": "and",
"matchOr": "or",
"albumCount": "$t(entity.album, {\"count\": 2}) count", "albumCount": "$t(entity.album, {\"count\": 2}) count",
"artist": "$t(entity.artist, {\"count\": 1})", "artist": "$t(entity.artist, {\"count\": 1})",
"biography": "biography", "biography": "biography",
@@ -335,6 +347,7 @@
"input_skipDuplicates": "skip duplicates", "input_skipDuplicates": "skip duplicates",
"searchOrCreate": "search $t(entity.playlist, {\"count\": 2}) or type to create a new one", "searchOrCreate": "search $t(entity.playlist, {\"count\": 2}) or type to create a new one",
"success": "added $t(entity.trackWithCount, {\"count\": {{message}} }) to $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} })", "success": "added $t(entity.trackWithCount, {\"count\": {{message}} }) to $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} })",
"noneAdded": "no tracks were added to $t(entity.playlist, {\"count\": 1}) '{{playlist}}'",
"title": "add to $t(entity.playlist, {\"count\": 1})" "title": "add to $t(entity.playlist, {\"count\": 1})"
}, },
"createPlaylist": { "createPlaylist": {
@@ -352,6 +365,9 @@
"input_name": "name", "input_name": "name",
"input_streamUrl": "stream url" "input_streamUrl": "stream url"
}, },
"editRadioStation": {
"success": "radio station updated successfully"
},
"deletePlaylist": { "deletePlaylist": {
"input_confirm": "type the name of the $t(entity.playlist, {\"count\": 1}) to confirm", "input_confirm": "type the name of the $t(entity.playlist, {\"count\": 1}) to confirm",
"success": "$t(entity.playlist, {\"count\": 1}) deleted successfully", "success": "$t(entity.playlist, {\"count\": 1}) deleted successfully",
@@ -359,7 +375,6 @@
}, },
"editPlaylist": { "editPlaylist": {
"publicJellyfinNote": "Jellyfin for some reason does not expose whether a playlist is public or not. If you wish for this to remain public, please have the following input selected", "publicJellyfinNote": "Jellyfin for some reason does not expose whether a playlist is public or not. If you wish for this to remain public, please have the following input selected",
"editNote": "manual edits are not recommended for large playlists. are you sure you accept the risk of data loss incurred by overwriting the existing playlist?",
"success": "$t(entity.playlist, {\"count\": 1}) updated successfully", "success": "$t(entity.playlist, {\"count\": 1}) updated successfully",
"title": "edit $t(entity.playlist, {\"count\": 1})" "title": "edit $t(entity.playlist, {\"count\": 1})"
}, },
@@ -387,9 +402,11 @@
}, },
"shareItem": { "shareItem": {
"allowDownloading": "allow downloading", "allowDownloading": "allow downloading",
"copyToClipboard": "Copy to clipboard: Ctrl+C, Enter",
"description": "description", "description": "description",
"setExpiration": "set expiration", "setExpiration": "set expiration",
"success": "share link copied to clipboard (or click here to open)", "success": "share link copied to clipboard (or click here to open)",
"successMustClick": "share created successfully. click here to open",
"expireInvalid": "expiration must be in the future", "expireInvalid": "expiration must be in the future",
"createFailed": "failed to create share (is sharing enabled?)" "createFailed": "failed to create share (is sharing enabled?)"
}, },
@@ -524,6 +541,8 @@
"lyricOffset": "lyrics offset (ms)", "lyricOffset": "lyrics offset (ms)",
"lyricGap": "lyric gap", "lyricGap": "lyric gap",
"lyricSize": "lyric size", "lyricSize": "lyric size",
"lyricOpacityNonActive": "non-active lyric opacity",
"lyricScaleNonActive": "non-active lyric scale",
"opacity": "opacity", "opacity": "opacity",
"showLyricMatch": "show lyric match", "showLyricMatch": "show lyric match",
"showLyricProvider": "show lyric provider", "showLyricProvider": "show lyric provider",
@@ -631,6 +650,7 @@
"addNext": "next", "addNext": "next",
"addLastShuffled": "last (shuffled)", "addLastShuffled": "last (shuffled)",
"addNextShuffled": "next (shuffled)", "addNextShuffled": "next (shuffled)",
"albumRadio": "album radio",
"artistRadio": "artist radio", "artistRadio": "artist radio",
"holdToShuffle": "hold to shuffle", "holdToShuffle": "hold to shuffle",
"favorite": "favorite", "favorite": "favorite",
@@ -712,10 +732,18 @@
"autoDJ_itemCount_description": "the number of items attempted to be added to the queue when auto DJ is enabled", "autoDJ_itemCount_description": "the number of items attempted to be added to the queue when auto DJ is enabled",
"autoDJ_timing": "timing", "autoDJ_timing": "timing",
"autoDJ_timing_description": "the number of songs remaining in the queue before auto DJ is triggered", "autoDJ_timing_description": "the number of songs remaining in the queue before auto DJ is triggered",
"autosave": "automatically save play queue",
"autosave_description": "enable automatically saving the play queue to your server. this is only possible when using Navidrome/Subsonic, and you cannot have a mixed play queue.",
"autosaveCount": "automatic play queue save frequency",
"autosaveCount_description": "how many track changes before the queue is saved. 1 (minimum) means every song change",
"accentColor_description": "sets the accent color for the application", "accentColor_description": "sets the accent color for the application",
"accentColor": "accent color", "accentColor": "accent color",
"useThemeAccentColor": "use theme accent color", "useThemeAccentColor": "use theme accent color",
"useThemeAccentColor_description": "use the primary color defined in the selected theme instead of the custom accent color", "useThemeAccentColor_description": "use the primary color defined in the selected theme instead of the custom accent color",
"useThemePrimaryShade": "use theme primary shade",
"useThemePrimaryShade_description": "use the primary shade defined in the selected theme for primary color variants",
"primaryShade": "primary shade",
"primaryShade_description": "override the primary shade (09) used for buttons, links, and other primary-colored elements",
"albumBackground_description": "adds a background image for album pages containing the album art", "albumBackground_description": "adds a background image for album pages containing the album art",
"albumBackground": "album background image", "albumBackground": "album background image",
"albumBackgroundBlur_description": "adjusts the amount of blur applied to the album background image", "albumBackgroundBlur_description": "adjusts the amount of blur applied to the album background image",
@@ -734,9 +762,9 @@
"artistConfiguration_description": "configure what items are shown, and in what order, on the album artist page", "artistConfiguration_description": "configure what items are shown, and in what order, on the album artist page",
"artistReleaseTypeConfiguration": "artist release type configuration", "artistReleaseTypeConfiguration": "artist release type configuration",
"artistReleaseTypeConfiguration_description": "configure what release types are shown, and in what order, on the album artist page", "artistReleaseTypeConfiguration_description": "configure what release types are shown, and in what order, on the album artist page",
"audioDevice_description": "select the audio device to use for playback (web player only)", "audioDevice_description": "select the audio device to use for playback",
"audioDevice": "audio device", "audioDevice": "audio device",
"audioExclusiveMode_description": "enable exclusive output mode. In this mode, the system is usually locked out, and only mpv will be able to output audio", "audioExclusiveMode_description": "enable exclusive output mode. in this mode, the system is usually locked out, and only mpv will be able to output audio. visualizer system audio capture will not work while this is enabled",
"audioExclusiveMode": "audio exclusive mode", "audioExclusiveMode": "audio exclusive mode",
"audioPlayer_description": "select the audio player to use for playback", "audioPlayer_description": "select the audio player to use for playback",
"audioPlayer": "audio player", "audioPlayer": "audio player",
@@ -788,6 +816,8 @@
"discordRichPresence_description": "enable playback status in {{discord}} rich presence. Image keys are: {{icon}}, {{playing}}, and {{paused}}", "discordRichPresence_description": "enable playback status in {{discord}} rich presence. Image keys are: {{icon}}, {{playing}}, and {{paused}}",
"discordServeImage": "serve {{discord}} images from server", "discordServeImage": "serve {{discord}} images from server",
"discordServeImage_description": "share cover art for {{discord}} rich presence from server itself, only available for Jellyfin and Navidrome. {{discord}} uses a bot to fetch images, so your server must be reachable from the public internet", "discordServeImage_description": "share cover art for {{discord}} rich presence from server itself, only available for Jellyfin and Navidrome. {{discord}} uses a bot to fetch images, so your server must be reachable from the public internet",
"discordStateIcon": "show playing icon",
"discordStateIcon_description": "show a small playing icon in the rich presence status. the paused icon is always shown when \"Show rich presence when paused\" is enabled",
"discordUpdateInterval": "{{discord}} rich presence update interval", "discordUpdateInterval": "{{discord}} rich presence update interval",
"discordUpdateInterval_description": "the time in seconds between each update (minimum 15 seconds)", "discordUpdateInterval_description": "the time in seconds between each update (minimum 15 seconds)",
"enableAutoTranslation_description": "enable translation automatically when lyrics are loaded", "enableAutoTranslation_description": "enable translation automatically when lyrics are loaded",
@@ -877,6 +907,8 @@
"language_description": "sets the language for the application ($t(common.restartRequired))", "language_description": "sets the language for the application ($t(common.restartRequired))",
"lastfm_description": "show links to Last.fm on artist/album pages", "lastfm_description": "show links to Last.fm on artist/album pages",
"lastfm": "show last.fm links", "lastfm": "show last.fm links",
"listenbrainz_description": "show links to ListenBrainz on artist/album pages",
"listenbrainz": "show ListenBrainz links",
"lastfmApiKey_description": "the API key for {{lastfm}}. required for cover art", "lastfmApiKey_description": "the API key for {{lastfm}}. required for cover art",
"lastfmApiKey": "{{lastfm}} API key", "lastfmApiKey": "{{lastfm}} API key",
"lyricFetch_description": "fetch lyrics from various internet sources", "lyricFetch_description": "fetch lyrics from various internet sources",
@@ -904,6 +936,12 @@
"mpvExtraParameters_help": "one per line", "mpvExtraParameters_help": "one per line",
"musicbrainz_description": "show links to MusicBrainz on artist/album pages, where MusicBrainz ID exists", "musicbrainz_description": "show links to MusicBrainz on artist/album pages, where MusicBrainz ID exists",
"musicbrainz": "show MusicBrainz links", "musicbrainz": "show MusicBrainz links",
"qobuz_description": "show links to Qobuz on artist/album pages",
"qobuz": "show Qobuz links",
"spotify_description": "show links to Spotify on artist/album pages",
"spotify": "show Spotify links",
"nativeSpotify_description": "open in the Spotify app instead of your browser",
"nativeSpotify": "use Spotify app",
"neteaseTranslation_description": "When enabled, fetches and displays translated lyrics from NetEase if available", "neteaseTranslation_description": "When enabled, fetches and displays translated lyrics from NetEase if available",
"neteaseTranslation": "Enable NetEase translations", "neteaseTranslation": "Enable NetEase translations",
"notify": "enable song notifications", "notify": "enable song notifications",
@@ -948,6 +986,8 @@
"playerbarWaveformBarWidth": "waveform bar width", "playerbarWaveformBarWidth": "waveform bar width",
"playerbarWaveformGap": "waveform gap", "playerbarWaveformGap": "waveform gap",
"playerbarWaveformRadius": "waveform radius", "playerbarWaveformRadius": "waveform radius",
"playerbarWaveformStretch": "waveform stretch",
"playerbarWaveformStretch_description": "stretches the waveform to fill the available space",
"preferLocalLyrics_description": "prefer local lyrics over remote lyrics when available", "preferLocalLyrics_description": "prefer local lyrics over remote lyrics when available",
"preferLocalLyrics": "prefer local lyrics", "preferLocalLyrics": "prefer local lyrics",
"showLyricsInSidebar_description": "a panel will be added to the attached play queue that displays the lyrics", "showLyricsInSidebar_description": "a panel will be added to the attached play queue that displays the lyrics",
@@ -968,6 +1008,8 @@
"audioFadeOnStatusChange_description": "enables fade out and fade in when play/pause status changes", "audioFadeOnStatusChange_description": "enables fade out and fade in when play/pause status changes",
"preventSleepOnPlayback_description": "prevent the display from sleeping while music is playing", "preventSleepOnPlayback_description": "prevent the display from sleeping while music is playing",
"preventSleepOnPlayback": "prevent sleep on playback", "preventSleepOnPlayback": "prevent sleep on playback",
"preventSuspendOnPlayback_description": "prevent the application from suspending while music is playing",
"preventSuspendOnPlayback": "prevent suspend on playback",
"remotePassword_description": "sets the password for the remote control server. These credentials are by default transferred insecurely, so you should use a unique password that you do not care about", "remotePassword_description": "sets the password for the remote control server. These credentials are by default transferred insecurely, so you should use a unique password that you do not care about",
"remotePassword": "remote control server password", "remotePassword": "remote control server password",
"remotePort_description": "sets the port for the remote control server", "remotePort_description": "sets the port for the remote control server",
@@ -999,6 +1041,8 @@
"sidebarCollapsedNavigation": "sidebar (collapsed) navigation", "sidebarCollapsedNavigation": "sidebar (collapsed) navigation",
"sidebarConfiguration_description": "select the items and order in which they appear in the sidebar", "sidebarConfiguration_description": "select the items and order in which they appear in the sidebar",
"sidebarConfiguration": "sidebar configuration", "sidebarConfiguration": "sidebar configuration",
"playerItemConfiguration_description": "configure what items are shown, and in what order, on the fullscreen player",
"playerItemConfiguration": "player item configuration",
"sidebarPlaylistList_description": "show or hide the playlist list in the sidebar", "sidebarPlaylistList_description": "show or hide the playlist list in the sidebar",
"sidebarPlaylistList": "sidebar playlist list", "sidebarPlaylistList": "sidebar playlist list",
"sidebarPlaylistSorting_description": "allows manual playlist sorting in the sidebar using drag and drop instead of the default server order", "sidebarPlaylistSorting_description": "allows manual playlist sorting in the sidebar using drag and drop instead of the default server order",
@@ -1009,6 +1053,10 @@
"sidePlayQueueStyle_description": "sets the style of the side play queue", "sidePlayQueueStyle_description": "sets the style of the side play queue",
"sidePlayQueueStyle_optionAttached": "attached", "sidePlayQueueStyle_optionAttached": "attached",
"sidePlayQueueStyle_optionDetached": "detached", "sidePlayQueueStyle_optionDetached": "detached",
"sidePlayQueueLayout": "side play queue layout",
"sidePlayQueueLayout_description": "sets the layout of the attached side play queue",
"sidePlayQueueLayout_optionHorizontal": "horizontal",
"sidePlayQueueLayout_optionVertical": "vertical",
"mediaSession_description": "enables Media Session integration, displaying media controls and metadata in the system volume overlay and lock screen", "mediaSession_description": "enables Media Session integration, displaying media controls and metadata in the system volume overlay and lock screen",
"mediaSession": "enable media session", "mediaSession": "enable media session",
"sidePlayQueueStyle": "side play queue style", "sidePlayQueueStyle": "side play queue style",
@@ -1044,6 +1092,8 @@
"volumeWheelStep": "volume wheel step", "volumeWheelStep": "volume wheel step",
"volumeWidth_description": "the width of the volume slider", "volumeWidth_description": "the width of the volume slider",
"volumeWidth": "volume slider width", "volumeWidth": "volume slider width",
"waveformLoadingDelay": "waveform loading delay",
"waveformLoadingDelay_description": "delay in seconds before loading waveform. increase this value if you are experiencing stutters when using the web player.",
"webAudio_description": "use web audio. this enables advanced features like replaygain. disable if you experience otherwise", "webAudio_description": "use web audio. this enables advanced features like replaygain. disable if you experience otherwise",
"webAudio": "use web audio", "webAudio": "use web audio",
"windowBarStyle_description": "select the style of the window bar", "windowBarStyle_description": "select the style of the window bar",
@@ -1122,6 +1172,7 @@
"label": { "label": {
"actions": "$t(common.action, {\"count\": 2})", "actions": "$t(common.action, {\"count\": 2})",
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
"albumGroup": "album group",
"albumCount": "$t(entity.album, {\"count\": 2})", "albumCount": "$t(entity.album, {\"count\": 2})",
"albumArtist": "$t(entity.albumArtist, {\"count\": 1})", "albumArtist": "$t(entity.albumArtist, {\"count\": 1})",
"artist": "$t(entity.artist, {\"count\": 1})", "artist": "$t(entity.artist, {\"count\": 1})",
@@ -1170,6 +1221,13 @@
"mainText": "drop a file here" "mainText": "drop a file here"
}, },
"visualizer": { "visualizer": {
"systemAudioConsentAllow": "Allow",
"systemAudioConsentBody": "The visualizer requires access to the system audio to work",
"systemAudioConsentDecline": "Deny",
"systemAudioConsentTitle": "Allow access to system audio?",
"systemAudioCaptureFailed": "Could not start capture: {{message}}",
"systemAudioNoAudioTrack": "No audio track was returned. Ensure audio capture is enabled when prompted.",
"systemAudioExclusiveModeNotSupported": "Visualizer is unavailable while audio exclusive mode is enabled. Disable Audio Exclusive Mode in MPV settings and try again.",
"visualizerType": "Visualizer Type", "visualizerType": "Visualizer Type",
"cyclePresets": "Cycle Presets", "cyclePresets": "Cycle Presets",
"cycleTime": "Cycle Time (seconds)", "cycleTime": "Cycle Time (seconds)",
+113 -41
View File
@@ -32,20 +32,30 @@
"playSimilarSongs": "Reproducir canciones similares", "playSimilarSongs": "Reproducir canciones similares",
"viewQueue": "ver cola", "viewQueue": "ver cola",
"addLastShuffled": "Al final (mezclado)", "addLastShuffled": "Al final (mezclado)",
"addNextShuffled": "Al siguiente (mezclado)", "addNextShuffled": "Siguiente (mezclado)",
"holdToShuffle": "Mantener para mezclar", "holdToShuffle": "Mantener para mezclar",
"lyrics": "Letras", "lyrics": "Letras",
"restoreQueueFromServer": "Restaurar cola del servidor", "restoreQueueFromServer": "Restaurar cola del servidor",
"saveQueueToServer": "Guardar cola en el servidor", "saveQueueToServer": "Guardar cola en el servidor",
"artistRadio": "Radio de artista", "artistRadio": "Radio de artista",
"trackRadio": "Radio de pista" "trackRadio": "Radio de pista",
"sleepTimer_minutes": "{{count}} min",
"sleepTimer_hours": "{{count}} h",
"sleepTimer_custom": "Personalizado",
"sleepTimer_setCustom": "Configurar temporizador",
"sleepTimer_cancel": "Cancelar temporizador",
"sleepTimer_timeRemaining": "{{time}} restante",
"sleepTimer_off": "Apagado",
"sleepTimer_endOfSong": "Fin de la canción actual",
"sleepTimer": "Temporizador de apagado",
"albumRadio": "Radio del álbum"
}, },
"setting": { "setting": {
"crossfadeStyle_description": "selecciona el estilo de crossfade a usar por el reproductor de audio", "crossfadeStyle_description": "selecciona el estilo de crossfade a usar por el reproductor de audio",
"remotePort_description": "establece el puerto para el control remoto del servidor", "remotePort_description": "establece el puerto para el control remoto del servidor",
"hotkey_skipBackward": "retroceder", "hotkey_skipBackward": "retroceder",
"replayGainMode_description": "ajusta el volumen de ganancia acorde a los valores de {{ReplayGain}} almacenados en los metadatos del archivo", "replayGainMode_description": "ajusta el volumen de ganancia acorde a los valores de {{ReplayGain}} almacenados en los metadatos del archivo",
"audioDevice_description": "selecciona el dispositivo de audio a usar durante la reproducción (solo reproductor web)", "audioDevice_description": "selecciona el dispositivo de audio a usar durante la reproducción",
"theme_description": "establece el tema a usar por la aplicación", "theme_description": "establece el tema a usar por la aplicación",
"hotkey_playbackPause": "pausa", "hotkey_playbackPause": "pausa",
"replayGainFallback": "{{ReplayGain}} alternativa", "replayGainFallback": "{{ReplayGain}} alternativa",
@@ -73,7 +83,7 @@
"replayGainClipping": "recortar {{ReplayGain}}", "replayGainClipping": "recortar {{ReplayGain}}",
"hotkey_zoomIn": "ampliar", "hotkey_zoomIn": "ampliar",
"scrobble_description": "hace scrobble de las reproducciones en tu servidor de medios", "scrobble_description": "hace scrobble de las reproducciones en tu servidor de medios",
"audioExclusiveMode_description": "activa el modo de audio exclusivo. En este modo, el sistema es normalmente bloqueado, y solo se permitirá mpv en la salida de audio", "audioExclusiveMode_description": "activa el modo de audio exclusivo. En este modo, el sistema es normalmente bloqueado, y solo se permitirá mpv en la salida de audio. El sistema visualizador de captura de audio no funcionará mientras esto esté activado",
"discordUpdateInterval": "intervalo de actualización del estado de actividad de {{discord}}", "discordUpdateInterval": "intervalo de actualización del estado de actividad de {{discord}}",
"themeLight": "tema (claro)", "themeLight": "tema (claro)",
"fontType_optionBuiltIn": "fuente incorporada", "fontType_optionBuiltIn": "fuente incorporada",
@@ -159,7 +169,7 @@
"customFontPath": "ruta de fuente personalizada", "customFontPath": "ruta de fuente personalizada",
"followLyric": "seguir la letra actual", "followLyric": "seguir la letra actual",
"crossfadeDuration": "duración del crossfade", "crossfadeDuration": "duración del crossfade",
"discordIdleStatus": "mostrar el estado inactivo en el estado de actividad", "discordIdleStatus": "mostrar estado inactivo en el estado de actividad",
"sidePlayQueueStyle_optionDetached": "separada", "sidePlayQueueStyle_optionDetached": "separada",
"audioPlayer": "reproductor de audio", "audioPlayer": "reproductor de audio",
"hotkey_zoomOut": "reducir", "hotkey_zoomOut": "reducir",
@@ -206,7 +216,7 @@
"passwordStore": "contraseñas/almacenamiento secreto", "passwordStore": "contraseñas/almacenamiento secreto",
"homeConfiguration": "Configuración de la página de inicio", "homeConfiguration": "Configuración de la página de inicio",
"mpvExtraParameters_help": "Uno por línea", "mpvExtraParameters_help": "Uno por línea",
"externalLinks_description": "Permite mostrar enlaces externos (Last.fm, MusicBrainz) en las páginas del artista/álbum", "externalLinks_description": "Permite mostrar enlaces externos (Last.fm, MusicBrainz) en las páginas de artistas/álbumes",
"homeConfiguration_description": "Configura qué elementos son mostrados y en qué orden en la página de inicio", "homeConfiguration_description": "Configura qué elementos son mostrados y en qué orden en la página de inicio",
"clearCacheSuccess": "Caché limpiada correctamente", "clearCacheSuccess": "Caché limpiada correctamente",
"externalLinks": "Mostrar enlaces externos", "externalLinks": "Mostrar enlaces externos",
@@ -233,13 +243,13 @@
"transcodeFormat": "formato a transcodificar", "transcodeFormat": "formato a transcodificar",
"transcodeFormat_description": "selecciona el formato a transcodificar. dejar vacío para que el servidor decida", "transcodeFormat_description": "selecciona el formato a transcodificar. dejar vacío para que el servidor decida",
"albumBackground": "imagen de fondo del álbum", "albumBackground": "imagen de fondo del álbum",
"albumBackground_description": "Añade una imagen de fondo a las páginas del álbum que contienen la carátula del álbum", "albumBackground_description": "Añade una imagen de fondo a las páginas de álbumes que contienen la carátula del álbum",
"albumBackgroundBlur": "Tamaño de desenfoque de la imagen de fondo del álbum", "albumBackgroundBlur": "Tamaño de desenfoque de la imagen de fondo del álbum",
"albumBackgroundBlur_description": "Ajusta la cantidad de desenfoque aplicado a la imagen de fondo del álbum", "albumBackgroundBlur_description": "Ajusta la cantidad de desenfoque aplicado a la imagen de fondo del álbum",
"playerbarOpenDrawer": "Cambiar la barra del reproductor a pantalla completa", "playerbarOpenDrawer": "Cambiar la barra del reproductor a pantalla completa",
"playerbarOpenDrawer_description": "Permite hacer clic en la barra del reproductor para abrir el reproductor a pantalla completa", "playerbarOpenDrawer_description": "Permite hacer clic en la barra del reproductor para abrir el reproductor a pantalla completa",
"artistConfiguration": "Configuración de la página del artista del álbum", "artistConfiguration": "Configuración de la página de artistas del álbum",
"artistConfiguration_description": "Configura qué elementos se muestran y en qué orden en la página del artista del álbum", "artistConfiguration_description": "Configura qué elementos se muestran y en qué orden en la página de artistas del álbum",
"playButtonBehavior_optionPlayShuffled": "$t(player.shuffle)", "playButtonBehavior_optionPlayShuffled": "$t(player.shuffle)",
"trayEnabled": "Mostrar en el área de notificación", "trayEnabled": "Mostrar en el área de notificación",
"trayEnabled_description": "muestra/oculta el icono/menú del área de notificación. si está deshabilitado, también deshabilita minimizar/salir a la bandeja", "trayEnabled_description": "muestra/oculta el icono/menú del área de notificación. si está deshabilitado, también deshabilita minimizar/salir a la bandeja",
@@ -283,7 +293,7 @@
"releaseChannel_optionBeta": "Beta", "releaseChannel_optionBeta": "Beta",
"releaseChannel": "Canal de lanzamiento", "releaseChannel": "Canal de lanzamiento",
"releaseChannel_description": "Elige entre lanzamientos estables, beta, o alpha (nightly) para las actualizaciones automáticas", "releaseChannel_description": "Elige entre lanzamientos estables, beta, o alpha (nightly) para las actualizaciones automáticas",
"artistBackground_description": "Añade una imagen de fondo para las páginas de artista que contienen el arte del artista", "artistBackground_description": "Añade una imagen de fondo para las páginas de artistas que contienen el arte de los artistas",
"mediaSession": "Activar sesión de medios", "mediaSession": "Activar sesión de medios",
"mediaSession_description": "Activa la integración de la sesión de medios, mostrando los controles de medios y los metadatos en la superposición del volumen del sistema y en la pantalla de bloqueo", "mediaSession_description": "Activa la integración de la sesión de medios, mostrando los controles de medios y los metadatos en la superposición del volumen del sistema y en la pantalla de bloqueo",
"exportImportSettings_control_description": "Exporta e importa la configuración a través de JSON", "exportImportSettings_control_description": "Exporta e importa la configuración a través de JSON",
@@ -318,8 +328,8 @@
"playerbarWaveformRadius": "Radio de la forma de onda", "playerbarWaveformRadius": "Radio de la forma de onda",
"showLyricsInSidebar_description": "Se añadirá un panel a la cola de reproducción acoplada que muestra las letras", "showLyricsInSidebar_description": "Se añadirá un panel a la cola de reproducción acoplada que muestra las letras",
"showLyricsInSidebar": "Mostrar letras en la barra lateral del reproductor", "showLyricsInSidebar": "Mostrar letras en la barra lateral del reproductor",
"showVisualizerInSidebar_description": "Se añadirá un panel a la barra lateral de reproducción que muestra el visualizador", "showVisualizerInSidebar_description": "Se añadirá un panel a la barra lateral del reproductor que muestra el visualizador",
"showVisualizerInSidebar": "Mostrar visualizador en la barra lateral de reproducción", "showVisualizerInSidebar": "Mostrar visualizador en la barra lateral del reproductor",
"queryBuilder": "Generador de consultas", "queryBuilder": "Generador de consultas",
"queryBuilderCustomFields_inputTag": "Etiqueta", "queryBuilderCustomFields_inputTag": "Etiqueta",
"queryBuilderCustomFields": "Campos personalizados", "queryBuilderCustomFields": "Campos personalizados",
@@ -360,7 +370,7 @@
"combinedLyricsAndVisualizer_description": "Combina letras y visualizador en el mismo panel", "combinedLyricsAndVisualizer_description": "Combina letras y visualizador en el mismo panel",
"combinedLyricsAndVisualizer": "Combinar letras y visualizador en la barra lateral del reproductor", "combinedLyricsAndVisualizer": "Combinar letras y visualizador en la barra lateral del reproductor",
"artistReleaseTypeConfiguration": "Configuración de tipo de lanzamiento de artista", "artistReleaseTypeConfiguration": "Configuración de tipo de lanzamiento de artista",
"artistReleaseTypeConfiguration_description": "Configura qué tipos de lanzamiento son mostrados, y en qué orden, en la página del artista del álbum", "artistReleaseTypeConfiguration_description": "Configura qué tipos de lanzamiento son mostrados, y en qué orden, en la página de artistas del álbum",
"mpvExtraParameters": "Parámetros adicionales de MPV", "mpvExtraParameters": "Parámetros adicionales de MPV",
"mpvExtraParameters_description": "Argumentos adicionales a pasar a MPV", "mpvExtraParameters_description": "Argumentos adicionales a pasar a MPV",
"hotkey_listPlayDefault": "Reproducir lista", "hotkey_listPlayDefault": "Reproducir lista",
@@ -385,7 +395,41 @@
"sidebarPlaylistListFilterRegex_placeholder": "p. ej. ^Mezcla diaria.*", "sidebarPlaylistListFilterRegex_placeholder": "p. ej. ^Mezcla diaria.*",
"blurExplicitImages": "Desenfocar imágenes explícitas", "blurExplicitImages": "Desenfocar imágenes explícitas",
"blurExplicitImages_description": "El álbum y la carátula de la canción etiquetados como explícitos serán desenfocados", "blurExplicitImages_description": "El álbum y la carátula de la canción etiquetados como explícitos serán desenfocados",
"releaseChannel_optionAlpha": "Alpha (nightly)" "releaseChannel_optionAlpha": "Alpha (nightly)",
"analyticsEnable": "Enviar analíticas basadas en el uso",
"analyticsEnable_description": "Se envían datos de uso anonimizados al desarrollador para ayudar a mejorar la aplicación",
"automaticUpdates": "Actualizaciones automáticas",
"automaticUpdates_description": "Busca e instala actualizaciones automáticamente",
"discordStateIcon": "Mostrar icono de reproducción",
"discordStateIcon_description": "Muestra un icono pequeño de reproducción en el estado de actividad. El icono de pausa se muestra siempre cuando \"Mostrar estado de actividad cuando esté en pausa\" esté activado",
"playerItemConfiguration": "Configuración de elementos del reproductor",
"playerItemConfiguration_description": "Configura qué elementos se muestran, y en qué orden, en el reproductor a pantalla completa",
"primaryShade": "Tono principal",
"useThemePrimaryShade": "Usar tono principal del tema",
"useThemePrimaryShade_description": "Usa el tono principal definido en el tema seleccionado para las variantes de color primario",
"primaryShade_description": "Sobreescribe el tono principal (0-9) usado para los botones, enlaces, y otros elementos de colores primarios",
"autosave": "Guardar automáticamente la cola de reproducción",
"autosaveCount": "Frecuencia de guardado automática de la cola de reproducción",
"autosave_description": "Permite guardar automáticamente la cola de reproducción en tu servidor. Esto solo es posible cuando se usa Navidrome/Subsonic, y no puedes tener una cola de reproducción mezclada.",
"autosaveCount_description": "Cuántas pistas cambian antes de que la cola sea guardada. 1 (mínimo) quiere decir que todas las canciones cambian",
"spotify_description": "Muestra enlaces a Spotify en las páginas de artistas/álbumes",
"spotify": "Mostrar enlaces de Spotify",
"nativeSpotify_description": "Abre en la aplicación de Spotify en lugar de tu navegador",
"nativeSpotify": "Usar la aplicación de Spotify",
"listenbrainz": "Mostrar enlaces a ListenBrainz",
"listenbrainz_description": "Muestra enlaces a ListenBrainz en las páginas de artistas/álbumes",
"qobuz_description": "Muestra enlaces a Qobuz en las páginas de artistas/álbumes",
"qobuz": "Mostrar enlaces a Qobuz",
"sidePlayQueueLayout_optionHorizontal": "Horizontal",
"sidePlayQueueLayout_optionVertical": "Vertical",
"sidePlayQueueLayout": "Diseño de la cola de reproducción lateral",
"sidePlayQueueLayout_description": "Establece el diseño de la cola de reproducción lateral adjunta",
"waveformLoadingDelay": "Retraso de carga de la forma de onda",
"waveformLoadingDelay_description": "Retraso en segundos antes de cargar la forma de onda. Incrementa este valor si estás experimentando tartamudeos al usar el reproductor web.",
"playerbarWaveformStretch": "Estiramiento de la forma de onda",
"playerbarWaveformStretch_description": "Estira la forma de onda para rellenar el espacio disponible",
"preventSuspendOnPlayback": "Evitar la suspensión durante la reproducción",
"preventSuspendOnPlayback_description": "Evita que la aplicación se suspenda mientras se reproduce música"
}, },
"action": { "action": {
"editPlaylist": "editar $t(entity.playlist, {\"count\": 1})", "editPlaylist": "editar $t(entity.playlist, {\"count\": 1})",
@@ -407,7 +451,10 @@
"removeFromFavorites": "eliminar de $t(entity.favorite, {\"count\": 2})", "removeFromFavorites": "eliminar de $t(entity.favorite, {\"count\": 2})",
"openIn": { "openIn": {
"lastfm": "Abrir en Last.fm", "lastfm": "Abrir en Last.fm",
"musicbrainz": "Abrir en MusicBrainz" "musicbrainz": "Abrir en MusicBrainz",
"spotify": "Abrir en Spotify",
"listenbrainz": "Abrir en ListenBrainz",
"qobuz": "Abrir en Qobuz"
}, },
"moveToNext": "pasar al siguiente", "moveToNext": "pasar al siguiente",
"downloadStarted": "Iniciada descarga de {{count}} elementos", "downloadStarted": "Iniciada descarga de {{count}} elementos",
@@ -425,13 +472,14 @@
"openApplicationDirectory": "Abrir directorio de la aplicación", "openApplicationDirectory": "Abrir directorio de la aplicación",
"addOrRemoveFromSelection": "Añadir o quitar de la selección", "addOrRemoveFromSelection": "Añadir o quitar de la selección",
"selectRangeOfItems": "Seleccionar un intervalo de elementos", "selectRangeOfItems": "Seleccionar un intervalo de elementos",
"selectAll": "Seleccionar todo" "selectAll": "Seleccionar todo",
"goToCurrent": "Ir al elemento actual"
}, },
"common": { "common": {
"backward": "hacia atrás", "backward": "hacia atrás",
"increase": "aumentar", "increase": "aumentar",
"rating": "calificación", "rating": "calificación",
"bpm": "lpm", "bpm": "bpm",
"refresh": "actualizar", "refresh": "actualizar",
"unknown": "desconocido", "unknown": "desconocido",
"areYouSure": "seguro?", "areYouSure": "seguro?",
@@ -443,7 +491,7 @@
"currentSong": "$t(entity.track, {\"count\": 1}) actual", "currentSong": "$t(entity.track, {\"count\": 1}) actual",
"collapse": "contraer", "collapse": "contraer",
"trackNumber": "pista", "trackNumber": "pista",
"descending": "descendiente", "descending": "descendente",
"add": "añadir", "add": "añadir",
"ascending": "ascendente", "ascending": "ascendente",
"dismiss": "descartar", "dismiss": "descartar",
@@ -470,8 +518,8 @@
"cancel": "cancelar", "cancel": "cancelar",
"forceRestartRequired": "reiniciar para aplicar cambios... cerrar la notificación para reiniciar", "forceRestartRequired": "reiniciar para aplicar cambios... cerrar la notificación para reiniciar",
"setting_one": "configuración", "setting_one": "configuración",
"setting_many": "configuraciones", "setting_many": "configuración",
"setting_other": "configuraciones", "setting_other": "configuración",
"version": "versión", "version": "versión",
"title": "título", "title": "título",
"filters": "filtros", "filters": "filtros",
@@ -551,7 +599,10 @@
"example": "Ejemplo", "example": "Ejemplo",
"filter_single": "simple", "filter_single": "simple",
"filter_multiple": "multi", "filter_multiple": "multi",
"rename": "Renombrar" "rename": "Renombrar",
"newVersionAvailable": "Una nueva versión está disponible",
"numberOfResults": "{{numberOfResults}} resultados",
"grouping": "Agrupar"
}, },
"error": { "error": {
"remotePortWarning": "reiniciar el servidor para aplicar el nuevo puerto", "remotePortWarning": "reiniciar el servidor para aplicar el nuevo puerto",
@@ -582,13 +633,16 @@
"multipleServerSaveQueueError": "La cola de reproducción tiene una o más canciones que no son del servidor actual. Esto no está soportado", "multipleServerSaveQueueError": "La cola de reproducción tiene una o más canciones que no son del servidor actual. Esto no está soportado",
"settingsSyncError": "Se encontraron discrepancias entre las opciones del renderizador y el proceso principal. Reinicia la aplicación para aplicar los cambios", "settingsSyncError": "Se encontraron discrepancias entre las opciones del renderizador y el proceso principal. Reinicia la aplicación para aplicar los cambios",
"noNetwork": "Servidor no disponible", "noNetwork": "Servidor no disponible",
"noNetworkDescription": "No se pudo conectar a este servidor" "noNetworkDescription": "No se pudo conectar a este servidor",
"invalidJson": "JSON inválido",
"serverLockSingleServer": "Solo se permite un servidor cuando el servidor está bloqueado",
"playbackPausedDueToError": "La reproducción fue pausada debido a un error"
}, },
"filter": { "filter": {
"mostPlayed": "más reproducido", "mostPlayed": "más reproducidos",
"isCompilation": "es una compilación", "isCompilation": "es una compilación",
"recentlyPlayed": "recientemente reproducido", "recentlyPlayed": "recientemente reproducido",
"isRated": "es clasificado", "isRated": "Está calificado",
"title": "título", "title": "título",
"rating": "calificación", "rating": "calificación",
"search": "buscar", "search": "buscar",
@@ -604,7 +658,7 @@
"albumArtist": "$t(entity.albumArtist, {\"count\": 1})", "albumArtist": "$t(entity.albumArtist, {\"count\": 1})",
"isRecentlyPlayed": "reproducido recientemente", "isRecentlyPlayed": "reproducido recientemente",
"isFavorited": "es favorito", "isFavorited": "es favorito",
"bpm": "lpm", "bpm": "bpm",
"releaseYear": "año de lanzamiento", "releaseYear": "año de lanzamiento",
"disc": "disco", "disc": "disco",
"biography": "biografía", "biography": "biografía",
@@ -623,12 +677,14 @@
"owner": "$t(common.owner)", "owner": "$t(common.owner)",
"genre": "$t(entity.genre, {\"count\": 1})", "genre": "$t(entity.genre, {\"count\": 1})",
"id": "id", "id": "id",
"songCount": "número de canción", "songCount": "número de canciones",
"isPublic": "es público", "isPublic": "es público",
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
"albumCount": "Contar $t(entity.album, {\"count\": 2})", "albumCount": "Número de $t(entity.album, {\"count\": 2})",
"explicitStatus": "$t(common.explicitStatus)", "explicitStatus": "$t(common.explicitStatus)",
"sortName": "Ordenar por nombre" "sortName": "Ordenar por nombre",
"matchAnd": "y",
"matchOr": "o"
}, },
"page": { "page": {
"sidebar": { "sidebar": {
@@ -720,7 +776,9 @@
"lyricGap": "desfase de letra", "lyricGap": "desfase de letra",
"dynamicImageBlur": "tamaño de desenfoque de imagen", "dynamicImageBlur": "tamaño de desenfoque de imagen",
"dynamicIsImage": "habilitar imagen de fondo", "dynamicIsImage": "habilitar imagen de fondo",
"lyricOffset": "desplazamiento de letras (ms)" "lyricOffset": "desplazamiento de letras (ms)",
"lyricScaleNonActive": "Escala de letra no activa",
"lyricOpacityNonActive": "Opacidad de letra no activa"
}, },
"lyrics": "letras", "lyrics": "letras",
"related": "relacionado", "related": "relacionado",
@@ -865,8 +923,8 @@
"input_name": "nombre del servidor", "input_name": "nombre del servidor",
"success": "servidor añadido correctamente", "success": "servidor añadido correctamente",
"input_savePassword": "guardar contraseña", "input_savePassword": "guardar contraseña",
"ignoreSsl": "ignorar ssl ($t(common.restartRequired))", "ignoreSsl": "Ignorar SSL ($t(common.restartRequired))",
"ignoreCors": "ignorar cors ($t(common.restartRequired))", "ignoreCors": "Ignorar CORS ($t(common.restartRequired))",
"error_savePassword": "un error ocurrió cuando se intentó guardar la contraseña", "error_savePassword": "un error ocurrió cuando se intentó guardar la contraseña",
"input_preferInstantMix": "Preferir mix instantáneo", "input_preferInstantMix": "Preferir mix instantáneo",
"input_preferInstantMixDescription": "Usa solo el mix instantáneo para obtener canciones similares. Útil si tienes complementos que modifican este comportamiento", "input_preferInstantMixDescription": "Usa solo el mix instantáneo para obtener canciones similares. Útil si tienes complementos que modifican este comportamiento",
@@ -880,7 +938,8 @@
"input_skipDuplicates": "saltar duplicados", "input_skipDuplicates": "saltar duplicados",
"input_playlists": "$t(entity.playlist, {\"count\": 2})", "input_playlists": "$t(entity.playlist, {\"count\": 2})",
"create": "Crear $t(entity.playlist, {\"count\": 1}) {{playlist}}", "create": "Crear $t(entity.playlist, {\"count\": 1}) {{playlist}}",
"searchOrCreate": "Buscar $t(entity.playlist, {\"count\": 2}) o escribir para crear uno nuevo" "searchOrCreate": "Buscar $t(entity.playlist, {\"count\": 2}) o escribir para crear uno nuevo",
"noneAdded": "Ninguna pista fue añadida a $t(entity.playlist, {\"count\": 1}) '{{playlist}}'"
}, },
"updateServer": { "updateServer": {
"title": "actualizar servidor", "title": "actualizar servidor",
@@ -894,8 +953,7 @@
"editPlaylist": { "editPlaylist": {
"title": "editar $t(entity.playlist, {\"count\": 1})", "title": "editar $t(entity.playlist, {\"count\": 1})",
"success": "$t(entity.playlist, {\"count\": 1}) actualizada correctamente", "success": "$t(entity.playlist, {\"count\": 1}) actualizada correctamente",
"publicJellyfinNote": "Jellyfin por alguna razón no expone si una lista de reproducción es pública o no. Si deseas que ésta siga siendo pública, por favor ten seleccionada la siguiente entrada", "publicJellyfinNote": "Jellyfin por alguna razón no expone si una lista de reproducción es pública o no. Si deseas que ésta siga siendo pública, por favor ten seleccionada la siguiente entrada"
"editNote": "No se recomiendan las ediciones manuales para grandes listas de reproducción. ¿Seguro que aceptas el riesgo de pérdida de información incurrido por sobrescribir la lista de reproducción existente?"
}, },
"queryEditor": { "queryEditor": {
"input_optionMatchAll": "coincidir todos", "input_optionMatchAll": "coincidir todos",
@@ -912,7 +970,9 @@
"description": "Descripción", "description": "Descripción",
"setExpiration": "Establecer expiración", "setExpiration": "Establecer expiración",
"success": "Enlace de compartición copiado al portapapeles (o pulsa aquí para abrir)", "success": "Enlace de compartición copiado al portapapeles (o pulsa aquí para abrir)",
"expireInvalid": "La expiración debe ser en el futuro" "expireInvalid": "La expiración debe ser en el futuro",
"copyToClipboard": "Copiar al portapapeles: Ctrl+C, Enter",
"successMustClick": "Compartir creado correctamente. Haz clic aquí para abrir"
}, },
"privateMode": { "privateMode": {
"enabled": "Modo privado activado, el estado de reproducción ahora está oculto de integraciones externas", "enabled": "Modo privado activado, el estado de reproducción ahora está oculto de integraciones externas",
@@ -948,6 +1008,9 @@
"export": "Exportar letras", "export": "Exportar letras",
"input_synced": "Exportar letras sincronizadas", "input_synced": "Exportar letras sincronizadas",
"input_offset": "$t(setting.lyricOffset)" "input_offset": "$t(setting.lyricOffset)"
},
"editRadioStation": {
"success": "Estación de radio actualizada con éxito"
} }
}, },
"table": { "table": {
@@ -964,7 +1027,7 @@
"releaseDate": "fecha de lanzamiento", "releaseDate": "fecha de lanzamiento",
"bitrate": "tasa de bits", "bitrate": "tasa de bits",
"title": "título", "title": "título",
"bpm": "lpm", "bpm": "bpm",
"dateAdded": "fecha de adición", "dateAdded": "fecha de adición",
"artist": "$t(entity.artist, {\"count\": 1})", "artist": "$t(entity.artist, {\"count\": 1})",
"songCount": "$t(entity.track, {\"count\": 2})", "songCount": "$t(entity.track, {\"count\": 2})",
@@ -1016,7 +1079,8 @@
"bitDepth": "$t(common.bitDepth)", "bitDepth": "$t(common.bitDepth)",
"sampleRate": "$t(common.sampleRate)", "sampleRate": "$t(common.sampleRate)",
"titleArtist": "$t(common.title) (artista)", "titleArtist": "$t(common.title) (artista)",
"composer": "Compositor" "composer": "Compositor",
"albumGroup": "Grupo del álbum"
}, },
"general": { "general": {
"gap": "$t(common.gap)", "gap": "$t(common.gap)",
@@ -1029,8 +1093,8 @@
"followCurrentSong": "seguir la canción actual", "followCurrentSong": "seguir la canción actual",
"advancedSettings": "Opciones avanzadas", "advancedSettings": "Opciones avanzadas",
"autosize": "Autodimensionar", "autosize": "Autodimensionar",
"moveUp": "Ascender", "moveUp": "Subir",
"moveDown": "Descender", "moveDown": "Bajar",
"pinToLeft": "Anclar a la izquierda", "pinToLeft": "Anclar a la izquierda",
"pinToRight": "Anclar a la derecha", "pinToRight": "Anclar a la derecha",
"alignLeft": "Alinear a la izquierda", "alignLeft": "Alinear a la izquierda",
@@ -1053,7 +1117,8 @@
"view": { "view": {
"table": "tabla", "table": "tabla",
"list": "Lista", "list": "Lista",
"grid": "Cuadrícula" "grid": "Cuadrícula",
"detail": "Detalle"
} }
} }
}, },
@@ -1323,6 +1388,13 @@
"lowResolution": "Baja resolución", "lowResolution": "Baja resolución",
"splitGradient": "Dividir degradado", "splitGradient": "Dividir degradado",
"noteLabels": "Etiquetas de notas", "noteLabels": "Etiquetas de notas",
"lumiBars": "Barras luminiscentes" "lumiBars": "Barras luminiscentes",
"systemAudioConsentAllow": "Permitir",
"systemAudioConsentDecline": "Denegar",
"systemAudioConsentTitle": "¿Permitir acceso al sistema de audio?",
"systemAudioConsentBody": "El visualizador requiere acceso al sistema de audio para funcionar",
"systemAudioCaptureFailed": "No se pudo iniciar la captura: {{message}}",
"systemAudioNoAudioTrack": "Ninguna pista de audio devuelta. Asegúrate de que la captura de audio está activada cuando se solicite.",
"systemAudioExclusiveModeNotSupported": "El visualizador no está disponible mientras el modo de audio exclusivo esté activado. Desactiva el modo de audio exclusivo en la configuración de MPV e inténtalo de nuevo."
} }
} }
+125 -22
View File
@@ -15,7 +15,10 @@
"viewPlaylists": "ikusi $t(entity.playlist, {\"count\": 2})", "viewPlaylists": "ikusi $t(entity.playlist, {\"count\": 2})",
"openIn": { "openIn": {
"lastfm": "Ireki Last.fm-n", "lastfm": "Ireki Last.fm-n",
"musicbrainz": "Ireki MusicBrainz-en" "musicbrainz": "Ireki MusicBrainz-en",
"listenbrainz": "Ireki ListenBrainz-en",
"qobuz": "Ireki Qobuz-en",
"spotify": "Ireki Spotify-n"
}, },
"clearQueue": "garbitu ilara", "clearQueue": "garbitu ilara",
"createPlaylist": "sortu $t(entity.playlist, {\"count\": 1})", "createPlaylist": "sortu $t(entity.playlist, {\"count\": 1})",
@@ -33,7 +36,8 @@
"shuffleAll": "nahastu dena", "shuffleAll": "nahastu dena",
"shuffleSelected": "nahastu aukeratutak", "shuffleSelected": "nahastu aukeratutak",
"moveItems": "elementuak mugitu", "moveItems": "elementuak mugitu",
"openApplicationDirectory": "ireki aplikazioaren direktorioa" "openApplicationDirectory": "ireki aplikazioaren direktorioa",
"goToCurrent": "joan uneko elementura"
}, },
"common": { "common": {
"add": "gehitu", "add": "gehitu",
@@ -67,8 +71,8 @@
"filter_other": "iragazkiak", "filter_other": "iragazkiak",
"filters": "iragazkiak", "filters": "iragazkiak",
"forceRestartRequired": "berreabiarazi aldaketak aplikatzeko... itxi notifikazioa berreabiarazteko", "forceRestartRequired": "berreabiarazi aldaketak aplikatzeko... itxi notifikazioa berreabiarazteko",
"setting_one": "ezarpenak", "setting_one": "ezarpena",
"setting_other": "", "setting_other": "ezarpenak",
"share": "partekatu", "share": "partekatu",
"action_one": "ekintza", "action_one": "ekintza",
"action_other": "ekintzak", "action_other": "ekintzak",
@@ -150,7 +154,11 @@
"recordLabel": "diskoetxea", "recordLabel": "diskoetxea",
"example": "adibidea", "example": "adibidea",
"tableColumns": "taulako zutabeak", "tableColumns": "taulako zutabeak",
"doNotShowAgain": "ez erakutsi hau berriro" "doNotShowAgain": "ez erakutsi hau berriro",
"numberOfResults": "{{numberOfResults}} emaitza",
"rename": "berrizendatu",
"newVersionAvailable": "bertsio berri bat eskuragarri dago",
"gridRows": "sareta-errenkadak"
}, },
"player": { "player": {
"repeat": "errepikatu", "repeat": "errepikatu",
@@ -351,7 +359,11 @@
"noNetwork": "zerbitzaria ez dago erabilgarri", "noNetwork": "zerbitzaria ez dago erabilgarri",
"noNetworkDescription": "ezin izan da zerbitzari honetara konektatu", "noNetworkDescription": "ezin izan da zerbitzari honetara konektatu",
"saveQueueFailed": "huts egin du ilara gordetzean", "saveQueueFailed": "huts egin du ilara gordetzean",
"multipleServerSaveQueueError": "erreprodukzio-ilarak zerbitzarikoak ez diren abesti bat edo gehiago ditu. hau ez da onartzen" "multipleServerSaveQueueError": "erreprodukzio-ilarak zerbitzarikoak ez diren abesti bat edo gehiago ditu. hau ez da onartzen",
"invalidJson": "JSON baliogabea",
"playbackPausedDueToError": "erreprodukzioa eten egin da errore baten ondorioz",
"serverLockSingleServer": "zerbitzaria blokeatuta dagoenean, zerbitzari bakarra onartzen da",
"settingsSyncError": "desadostasunak aurkitu dira errendatzailearen ezarpenen eta prozesu nagusiaren artean. berrabiarazi aplikazioa aldaketak aplikatzeko"
}, },
"filter": { "filter": {
"disc": "diskoa", "disc": "diskoa",
@@ -371,7 +383,7 @@
"biography": "biografia", "biography": "biografia",
"bitrate": "bit-emaria", "bitrate": "bit-emaria",
"bpm": "bpm-ak", "bpm": "bpm-ak",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel, {\"count\": 2})",
"comment": "iruzkina", "comment": "iruzkina",
"favorited": "gogoko gisa markatua", "favorited": "gogoko gisa markatua",
"genre": "$t(entity.genre, {\"count\": 1})", "genre": "$t(entity.genre, {\"count\": 1})",
@@ -396,7 +408,10 @@
"releaseYear": "argitalpen urtea", "releaseYear": "argitalpen urtea",
"toYear": "urtera arte", "toYear": "urtera arte",
"fromYear": "urtetik aurrera", "fromYear": "urtetik aurrera",
"explicitStatus": "$t(common.explicitStatus)" "explicitStatus": "$t(common.explicitStatus)",
"matchAnd": "eta",
"matchOr": "edo",
"sortName": "izenaren arabera ordenatu"
}, },
"setting": { "setting": {
"hotkey_playbackPause": "pausatu", "hotkey_playbackPause": "pausatu",
@@ -561,7 +576,7 @@
"hotkey_browserForward": "nabigatzailean aurreraka", "hotkey_browserForward": "nabigatzailean aurreraka",
"imageAspectRatio": "erabili jatorrizko azaleko artearen aspektu-erlazioa", "imageAspectRatio": "erabili jatorrizko azaleko artearen aspektu-erlazioa",
"lyricFetchProvider": "letrak eskuratzeko hornitzaileak", "lyricFetchProvider": "letrak eskuratzeko hornitzaileak",
"lyricFetchProvider_description": "aukeratu letrak eskuratzeko hornitzaileak. hornitzaileen ordena kontsultatuko diren ordena da", "lyricFetchProvider_description": "aukeratu letrak eskuratzeko hornitzaileak",
"minimizeToTray": "minimizatu erretilura", "minimizeToTray": "minimizatu erretilura",
"minimizeToTray_description": "minimizatu aplikazioa sistemaren erretilura", "minimizeToTray_description": "minimizatu aplikazioa sistemaren erretilura",
"minimumScrobblePercentage": "scrobble iraupen minimoa (ehunekoa)", "minimumScrobblePercentage": "scrobble iraupen minimoa (ehunekoa)",
@@ -630,7 +645,7 @@
"passwordStore_description": "zein pasahitz/sekretu biltegi erabili. aldatu hau pasahitzak gordetzeko arazoak badituzu", "passwordStore_description": "zein pasahitz/sekretu biltegi erabili. aldatu hau pasahitzak gordetzeko arazoak badituzu",
"playerFilters": "Iragazi ilarako abestiak", "playerFilters": "Iragazi ilarako abestiak",
"sidePlayQueueStyle_description": "alboko erreprodukzio-ilararen estiloa ezartzen du", "sidePlayQueueStyle_description": "alboko erreprodukzio-ilararen estiloa ezartzen du",
"mediaSession_description": "Windows Media Session integrazioa gaitzen du, multimedia kontrolak eta metadatuak sistemaren bolumenaren gainjartzean eta blokeo pantailan bistaratuz (Windows bakarrik)", "mediaSession_description": "Media Session integrazioa gaitzen du, multimedia kontrolak eta metadatuak sistemaren bolumenaren gainjartzean eta blokeo pantailan bistaratuz",
"sidePlayQueueStyle": "alboko erreprodukzio-ilarako estiloa", "sidePlayQueueStyle": "alboko erreprodukzio-ilarako estiloa",
"skipPlaylistPage": "saltatu erreprodukzio-zerrenda orria", "skipPlaylistPage": "saltatu erreprodukzio-zerrenda orria",
"startMinimized_description": "abiarazi aplikazioa sistemaren erretiluan", "startMinimized_description": "abiarazi aplikazioa sistemaren erretiluan",
@@ -675,7 +690,45 @@
"remotePort_description": "urruneko kontrol zerbitzariaren portua ezartzen du", "remotePort_description": "urruneko kontrol zerbitzariaren portua ezartzen du",
"remotePort": "urruneko kontrol zerbitzariaren ataka", "remotePort": "urruneko kontrol zerbitzariaren ataka",
"remoteUsername_description": "urruneko kontrol zerbitzariaren erabiltzaile-izena ezartzen du. Erabiltzaile-izena eta pasahitza hutsik badaude, autentifikazioa desgaituta egongo da", "remoteUsername_description": "urruneko kontrol zerbitzariaren erabiltzaile-izena ezartzen du. Erabiltzaile-izena eta pasahitza hutsik badaude, autentifikazioa desgaituta egongo da",
"remoteUsername": "urruneko kontrol zerbitzariaren erabiltzaile-izena" "remoteUsername": "urruneko kontrol zerbitzariaren erabiltzaile-izena",
"logLevel_optionWarn": "abisua",
"qobuz_description": "erakutsi Qobuz-erako estekak artista/album orrialdeetan",
"qobuz": "erakutsi Qobuz-erako estekak",
"spotify_description": "erakutsi Spotify-rako estekak artista/album orrialdeetan",
"spotify": "erakutsi Spotify-rako estekak",
"nativeSpotify_description": "ireki Spotify aplikazioan, arakatzailearen ordez",
"nativeSpotify": "erabili Spotify aplikazioa",
"playerbarSlider_description": "uhin-forma ez da gomendagarria interneteko konexio motela edo neurtua baduzu",
"playerbarSliderType_optionWaveform": "uhin-forma",
"playerbarWaveformAlign": "uhin-formaren lerrokatzea",
"playerbarWaveformAlign_optionTop": "nagusia",
"playerbarWaveformBarWidth": "uhin-formako barraren zabalera",
"playerbarWaveformGap": "uhin-formaren tartea",
"playerbarWaveformRadius": "uhin-formaren erradioa",
"showLyricsInSidebar_description": "letrak erakusten dituen panel bat gehituko da erantsitako erreprodukzio-ilaran",
"showLyricsInSidebar": "erakutsi letra erreproduzitzailearen alboko barran",
"blurExplicitImages": "irudi esplizituak lausotu",
"blurExplicitImages_description": "esplizitu gisa etiketatutako albumaren eta abestiaren azalak lausotuta agertuko dira",
"enableGridMultiSelect": "gaitu sareta anitzeko hautaketa",
"enableGridMultiSelect_description": "gaituta dagoenean, sareta-ikuspegietan hainbat elementu hautatzea ahalbidetzen du. desgaituta dagoenean, sareta-elementuen irudietan klik egitean elementuaren orrialdera nabigatuko da",
"showVisualizerInSidebar_description": "bistaratzailea erakusten duen panel bat gehituko da erreproduzitzailearen alboko barran",
"preservePitch_description": "erreprodukzio-abiadura aldatzean tonua mantentzen du",
"preservePitch": "mantendu tonua",
"preventSleepOnPlayback": "erreprodukzioan loa saihestu",
"replayGainClipping_description": "Saihestu {{ReplayGain}}-k eragindako mozketa irabazpena automatikoki jaitsiz",
"replayGainMode_description": "doitu bolumenaren irabazia fitxategiaren metadatuetan gordetako {{ReplayGain}} balioen arabera",
"listenbrainz": "erakutsi ListenBrainz estekak",
"sidebarPlaylistSorting": "alboko barrako erreprodukzio-zerrenda ordenatzea",
"sidebarPlaylistListFilterRegex_description": "ezkutatu alboko barran adierazpen erregular honekin bat datozen erreprodukzio-zerrendak",
"sidebarPlaylistListFilterRegex_placeholder": "adib. ^Eguneroko Nahasketa.*",
"sidebarPlaylistListFilterRegex": "erreprodukzio-zerrenda iragazteko adierazpen erregularra",
"sidePlayQueueLayout": "alboko erreprodukzio-ilararen diseinua",
"sidePlayQueueLayout_description": "erantsitako alboko erreprodukzio-ilararen diseinua ezartzen du",
"sidePlayQueueLayout_optionHorizontal": "horizontala",
"sidePlayQueueLayout_optionVertical": "bertikala",
"skipDuration_description": "erreproduzitzailearen barran saltatzeko botoiak erabiltzean saltatzeko iraupena ezartzen du",
"skipPlaylistPage_description": "erreprodukzio-zerrenda batera nabigatzean, joan erreprodukzio-zerrendako abestien zerrendara lehenetsitako orrialdera joan beharrean",
"translationApiKey_description": "itzulpenerako api gakoa (zerbitzu globalaren amaiera-puntua soilik)"
}, },
"form": { "form": {
"addServer": { "addServer": {
@@ -692,7 +745,9 @@
"success": "zerbitzaria behar bezala gehitu da", "success": "zerbitzaria behar bezala gehitu da",
"input_preferInstantMix": "nahiago izan berehalako nahasketa", "input_preferInstantMix": "nahiago izan berehalako nahasketa",
"input_preferInstantMixDescription": "erabili berehalako nahasketa soilik antzeko abestiak lortzeko. erabilgarria portaera hau aldatzen duten pluginak badituzu", "input_preferInstantMixDescription": "erabili berehalako nahasketa soilik antzeko abestiak lortzeko. erabilgarria portaera hau aldatzen duten pluginak badituzu",
"input_remoteUrl": "URL publikoa" "input_remoteUrl": "URL publikoa",
"input_preferRemoteUrl": "url publikoa nahiago izan",
"input_remoteUrlPlaceholder": "aukerakoa: kanpoko funtzioetarako url publikoa"
}, },
"addToPlaylist": { "addToPlaylist": {
"input_playlists": "$t(entity.playlist, {\"count\": 2})", "input_playlists": "$t(entity.playlist, {\"count\": 2})",
@@ -700,7 +755,8 @@
"input_skipDuplicates": "saltatu bikoiztuak", "input_skipDuplicates": "saltatu bikoiztuak",
"title": "gehitu $t(entity.playlist, {\"count\": 1})-(a)ri", "title": "gehitu $t(entity.playlist, {\"count\": 1})-(a)ri",
"create": "sortu $t(entity.playlist, {\"count\": 1}) {{playlist}}", "create": "sortu $t(entity.playlist, {\"count\": 1}) {{playlist}}",
"searchOrCreate": "bilatu $t(entity.playlist, {\"count\": 2}) edo idatzi berri bat sortzeko" "searchOrCreate": "bilatu $t(entity.playlist, {\"count\": 2}) edo idatzi berri bat sortzeko",
"noneAdded": "ez da pistarik gehitu honi $t(entity.playlist, {\"count\": 1}) '{{playlist}}'"
}, },
"createPlaylist": { "createPlaylist": {
"input_description": "$t(common.description)", "input_description": "$t(common.description)",
@@ -721,7 +777,9 @@
"success": "partekatzeko esteka arbelera kopiatu da (edo egin klik hemen irekitzeko)", "success": "partekatzeko esteka arbelera kopiatu da (edo egin klik hemen irekitzeko)",
"expireInvalid": "iraungitze-data etorkizunean izan behar da", "expireInvalid": "iraungitze-data etorkizunean izan behar da",
"allowDownloading": "baimendu deskargatzea", "allowDownloading": "baimendu deskargatzea",
"createFailed": "partekatzea sortzeak huts egin du (partekatzea gaituta al dago?)" "createFailed": "partekatzea sortzeak huts egin du (partekatzea gaituta al dago?)",
"copyToClipboard": "Kopiatu arbelean: Ctrl+C, Enter",
"successMustClick": "partekatzea behar bezala sortu da. egin klik hemen irekitzeko"
}, },
"deletePlaylist": { "deletePlaylist": {
"success": "$t(entity.playlist, {\"count\": 1}) behar bezala ezabatu da", "success": "$t(entity.playlist, {\"count\": 1}) behar bezala ezabatu da",
@@ -731,15 +789,16 @@
"editPlaylist": { "editPlaylist": {
"success": "$t(entity.playlist, {\"count\": 1}) behar bezala eguneratu da", "success": "$t(entity.playlist, {\"count\": 1}) behar bezala eguneratu da",
"title": "$t(entity.playlist, {\"count\": 1}) editatu", "title": "$t(entity.playlist, {\"count\": 1}) editatu",
"publicJellyfinNote": "Arrazoiren batengatik, Jellyfin ez du erakusten erreprodukzio-zerrendak publikoak diren edo ez. Hau publiko izaten jarraitzea nahi baduzu, hautatu sarrera hau", "publicJellyfinNote": "Arrazoiren batengatik, Jellyfin ez du erakusten erreprodukzio-zerrendak publikoak diren edo ez. Hau publiko izaten jarraitzea nahi baduzu, hautatu sarrera hau"
"editNote": "ez da gomendatzen eskuzko edizioak egitea erreprodukzio-zerrenda handietarako. ziur zaude onartzen duzula lehendik dagoen erreprodukzio-zerrenda gainidazteagatik datuak galtzeko arriskua?"
}, },
"queryEditor": { "queryEditor": {
"title": "kontsulta editorea", "title": "kontsulta editorea",
"input_optionMatchAll": "guztiak bat etorri", "input_optionMatchAll": "guztiak bat etorri",
"input_optionMatchAny": "edozeinekin bat etorri", "input_optionMatchAny": "edozeinekin bat etorri",
"resetToDefault": "lehenetsitako egoerara berrezarri", "resetToDefault": "lehenetsitako egoerara berrezarri",
"clearFilters": "garbitu iragazkiak" "clearFilters": "garbitu iragazkiak",
"addRuleGroup": "gehitu arau-taldea",
"removeRuleGroup": "kendu arau-taldea"
}, },
"updateServer": { "updateServer": {
"success": "zerbitzaria behar bezala eguneratu da", "success": "zerbitzaria behar bezala eguneratu da",
@@ -751,7 +810,8 @@
"disabled": "modu pribatua desgaituta, erreprodukzio egoera ikusgai dago orain gaitutako kanpoko integrazioentzat" "disabled": "modu pribatua desgaituta, erreprodukzio egoera ikusgai dago orain gaitutako kanpoko integrazioentzat"
}, },
"largeFetchConfirmation": { "largeFetchConfirmation": {
"title": "gehitu elementuak ilaran" "title": "gehitu elementuak ilaran",
"description": "Ekintza honek uneko iragazki-ikuspegian dauden elementu guztiak gehituko ditu"
}, },
"createRadioStation": { "createRadioStation": {
"input_homepageUrl": "hasierako orriaren URLa", "input_homepageUrl": "hasierako orriaren URLa",
@@ -928,7 +988,8 @@
"nowPlaying": "orain erreproduzitzen", "nowPlaying": "orain erreproduzitzen",
"shared": "partekatutako $t(entity.playlist, {\"count\": 2})", "shared": "partekatutako $t(entity.playlist, {\"count\": 2})",
"favorites": "$t(entity.favorite, {\"count\": 2})", "favorites": "$t(entity.favorite, {\"count\": 2})",
"radio": "$t(entity.radioStation, {\"count\": 2})" "radio": "$t(entity.radioStation, {\"count\": 2})",
"collections": "bildumak"
}, },
"trackList": { "trackList": {
"title": "$t(entity.track, {\"count\": 2})", "title": "$t(entity.track, {\"count\": 2})",
@@ -946,7 +1007,10 @@
"recentReleases": "azken argitalpenak", "recentReleases": "azken argitalpenak",
"viewDiscography": "ikusi diskografia", "viewDiscography": "ikusi diskografia",
"groupingTypeAll": "argitalpen mota guztiak", "groupingTypeAll": "argitalpen mota guztiak",
"groupingTypePrimary": "argitalpen mota nagusiak" "groupingTypePrimary": "argitalpen mota nagusiak",
"favoriteSongs": "abesti gogokoenak",
"topSongsCommunity": "komunitatea",
"topSongsPersonal": "pertsonala"
}, },
"itemDetail": { "itemDetail": {
"copyPath": "kopiatu bidea arbelean", "copyPath": "kopiatu bidea arbelean",
@@ -964,6 +1028,13 @@
}, },
"radioList": { "radioList": {
"title": "irrati-kateak" "title": "irrati-kateak"
},
"releasenotes": {
"noStableReleaseToCompare": "ez dago bertsio egonkorrik alderatzeko"
},
"windowBar": {
"paused": "(Pausatuta) ",
"privateMode": "(Modu pribatua)"
} }
}, },
"releaseType": { "releaseType": {
@@ -996,7 +1067,19 @@
"notContains": "ez dauka", "notContains": "ez dauka",
"startsWith": "honekin hasten da", "startsWith": "honekin hasten da",
"endsWith": "honekin amaitzen da", "endsWith": "honekin amaitzen da",
"isNot": "ez da" "isNot": "ez da",
"afterDate": "(data) ondoren da",
"after": "ondoren da",
"before": "lehenago da",
"beforeDate": "(data) baino lehenagokoa da",
"inTheLast": "azkenengoan dago",
"inPlaylist": "bertan dago",
"inTheRange": "tartean dago",
"inTheRangeDate": "(data) tartean dago",
"isGreaterThan": "hau baino handiagoa da",
"isLessThan": "hau baino gutxiago da",
"notInPlaylist": "ez dago barruan",
"notInTheLast": "ez dago azkenengoan"
}, },
"visualizer": { "visualizer": {
"general": "Orokorra", "general": "Orokorra",
@@ -1097,6 +1180,26 @@
"saveAsPreset": "Aurrezarpen gisa gorde", "saveAsPreset": "Aurrezarpen gisa gorde",
"applyPreset": "Aurrezarpena Aplikatu", "applyPreset": "Aurrezarpena Aplikatu",
"selectPreset": "Aukeratu Aurrezarpena", "selectPreset": "Aukeratu Aurrezarpena",
"presets": "Aurrezarpenak" "presets": "Aurrezarpenak",
"visualizerType": "Bistaratzaile Mota",
"cycleTime": "Zikloaren denbora (segundoak)",
"includeAllPresets": "Aurrezarpen guztiak sartu",
"ignoredPresets": "Aurrezarpen baztertuak",
"selectedPresets": "Hautatutako aurrezarpenak",
"mode1To8": "1 - 8 modua",
"mode10": "10 modua",
"gradientLeft": "Gradientearen ezkerra",
"gradientRight": "Gradientearen eskuina",
"peakBehavior": "Gailurraren Portaera",
"peakLine": "Gailurraren lerroa",
"miscellaneousSettings": "Hainbat ezarpen",
"alphaBars": "Alfa barrak",
"ansiBands": "ANSI bandak",
"ledBars": "LED barrak",
"trueLeds": "True LED-ak",
"roundBars": "Barra biribilduak",
"lowResolution": "Erresoluzio baxua",
"showFPS": "Erakutsi FPS",
"showScaleX": "Erakutsi X eskala"
} }
} }
+221 -23
View File
@@ -4,7 +4,7 @@
"search": "etsi", "search": "etsi",
"sortOrder": "järjestys", "sortOrder": "järjestys",
"setting_one": "asetus", "setting_one": "asetus",
"setting_other": "", "setting_other": "asetukset",
"title": "otsikko", "title": "otsikko",
"trackNumber": "raita", "trackNumber": "raita",
"action_one": "toiminto", "action_one": "toiminto",
@@ -102,7 +102,24 @@
"recordLabel": "levy-yhtiö", "recordLabel": "levy-yhtiö",
"releaseType": "julkaisun tyyppi", "releaseType": "julkaisun tyyppi",
"explicit": "eksplisiittinen", "explicit": "eksplisiittinen",
"clean": "puhdas" "clean": "puhdas",
"countSelected": "{{count}} valittuna",
"doNotShowAgain": "älä näytä uudelleen",
"view": "katso",
"example": "esimerkki",
"externalLinks": "ulkoiset linkit",
"faster": "nopeammin",
"filter_single": "yksi",
"filter_multiple": "useampi",
"mood": "mieliala",
"noFilters": "suodattimia ei ole määritetty",
"retry": "yritä uudelleen",
"rename": "nimeä uudelleen",
"slower": "hitaammin",
"sort": "järjestä",
"gridRows": "ruudukon rivejä",
"tableColumns": "taulukon sarakkeita",
"itemsMore": "{{count}} lisää"
}, },
"entity": { "entity": {
"album_one": "albumi", "album_one": "albumi",
@@ -139,7 +156,11 @@
"play_one": "{{count}} toisto", "play_one": "{{count}} toisto",
"play_other": "{{count}} toistoa", "play_other": "{{count}} toistoa",
"song_one": "kappale", "song_one": "kappale",
"song_other": "kappaleet" "song_other": "kappaleet",
"radioStation_one": "radioasema",
"radioStation_other": "radioasemaa",
"radioStationWithCount_one": "{{count}} radioasema",
"radioStationWithCount_other": "{{count}} radioasemaa"
}, },
"action": { "action": {
"clearQueue": "tyhjennä jono", "clearQueue": "tyhjennä jono",
@@ -153,7 +174,7 @@
"musicbrainz": "Avaa MusicBrainz:ssä" "musicbrainz": "Avaa MusicBrainz:ssä"
}, },
"goToPage": "mene sivulle", "goToPage": "mene sivulle",
"moveToBottom": "siirry pohjalle", "moveToBottom": "siirrä alimmaksi",
"moveToTop": "siirry ylös", "moveToTop": "siirry ylös",
"addToFavorites": "lisää kohteeseen $t(entity.favorite, {\"count\": 2})", "addToFavorites": "lisää kohteeseen $t(entity.favorite, {\"count\": 2})",
"addToPlaylist": "lisää kohteeseen $t(entity.playlist, {\"count\": 1})", "addToPlaylist": "lisää kohteeseen $t(entity.playlist, {\"count\": 1})",
@@ -163,7 +184,24 @@
"deletePlaylist": "poista $t(entity.playlist, {\"count\": 1})", "deletePlaylist": "poista $t(entity.playlist, {\"count\": 1})",
"removeFromPlaylist": "poista kohteesta $t(entity.playlist, {\"count\": 1})", "removeFromPlaylist": "poista kohteesta $t(entity.playlist, {\"count\": 1})",
"setRating": "aseta arvostelu", "setRating": "aseta arvostelu",
"moveToNext": "siirry seuraavaan" "moveToNext": "siirry seuraavaan",
"selectRangeOfItems": "valitse useita peräkkäisiä kohteita",
"goToCurrent": "siirry nykyiseen kohteeseen",
"createRadioStation": "luo $t(entity.radioStation, {\"count\": 1})",
"deleteRadioStation": "poista $t(entity.radioStation, {\"count\": 1})",
"selectAll": "valitse kaikki",
"downloadStarted": "aloitettiin lataamaan {{count}} kohdetta",
"moveUp": "siirrä ylöspäin",
"moveDown": "siirrä alaspäin",
"holdToMoveToTop": "pidä pohjassa siirtääksesi ylimmäksi",
"holdToMoveToBottom": "pidä pohjassa siirtääksesi alimmaksi",
"moveItems": "siirrä kohteet",
"shuffle": "sekoita",
"shuffleAll": "sekoita kaikki",
"shuffleSelected": "sekoita valitut",
"viewMore": "katso lisää",
"openApplicationDirectory": "avaa ohjelman kansio",
"addOrRemoveFromSelection": "lisää tai poista valinnasta"
}, },
"error": { "error": {
"remoteEnableError": "virhe tapahtui yrittäessä $t(common.enable) etäpalvelinta", "remoteEnableError": "virhe tapahtui yrittäessä $t(common.enable) etäpalvelinta",
@@ -189,7 +227,15 @@
"remotePortWarning": "käynnistä palvelin uudestaan ottaaksesi uuden portin käyttöön", "remotePortWarning": "käynnistä palvelin uudestaan ottaaksesi uuden portin käyttöön",
"endpointNotImplementedError": "päätepiste {{endpoint}} ei ole toteutettu {{serverType}} varten", "endpointNotImplementedError": "päätepiste {{endpoint}} ei ole toteutettu {{serverType}} varten",
"badValue": "kelpaamaton optio \"{{value}}\". tätä arvoa ei ole enää olemassa", "badValue": "kelpaamaton optio \"{{value}}\". tätä arvoa ei ole enää olemassa",
"notificationDenied": "luvat ilmouilmoituksia varten evättiin. tällä asetuksella ei ole vaikutusta" "notificationDenied": "luvat ilmouilmoituksia varten evättiin. tällä asetuksella ei ole vaikutusta",
"invalidJson": "virheellinen JSON",
"multipleServerSaveQueueError": "soittojonossa on yksi tai useampi kappale, jotka eivät ole nykyiseltä palvelimelta. tätä ei ole tuettu",
"noNetwork": "palvelin ei ole käytettävissä",
"noNetworkDescription": "ei voida yhdistää palvelimeen",
"serverLockSingleServer": "lukitussa tilassa sallitaan vain yksi palvelin",
"settingsSyncError": "rendererin ja pääprosessin asetukset eivät täsmää. Käynnistä sovellus uudelleen, jotta muutokset otetaan käyttöön",
"playbackPausedDueToError": "toisto tauotettiin virheen takia",
"saveQueueFailed": "jonon tallentaminen epäonnistui"
}, },
"filter": { "filter": {
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
@@ -198,7 +244,7 @@
"biography": "biografia", "biography": "biografia",
"bitrate": "bittinopeus", "bitrate": "bittinopeus",
"bpm": "lyöntiä minuutissa (bpm)", "bpm": "lyöntiä minuutissa (bpm)",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel, {\"count\": 2})",
"title": "otsikko", "title": "otsikko",
"playCount": "toistomäärä", "playCount": "toistomäärä",
"dateAdded": "lisätty päivänä", "dateAdded": "lisätty päivänä",
@@ -234,7 +280,10 @@
"owner": "$t(common.owner)", "owner": "$t(common.owner)",
"path": "polku", "path": "polku",
"songCount": "kappalemäärä", "songCount": "kappalemäärä",
"explicitStatus": "$t(common.explicitStatus)" "explicitStatus": "$t(common.explicitStatus)",
"matchAnd": "ja",
"matchOr": "tai",
"sortName": "järjestä nimen mukaan"
}, },
"form": { "form": {
"addServer": { "addServer": {
@@ -250,7 +299,10 @@
"input_username": "käyttäjänimi", "input_username": "käyttäjänimi",
"success": "palvelin lisätty onnistuneesti", "success": "palvelin lisätty onnistuneesti",
"input_preferInstantMix": "suosi pika-miksausta", "input_preferInstantMix": "suosi pika-miksausta",
"input_preferInstantMixDescription": "käytä vain pika-miksausta saadaksesi samankaltaisia kappaleita. käytännöllinen jos sinulla on lisäosia, jotka muuttavat tätä käytöstä" "input_preferInstantMixDescription": "käytä vain pika-miksausta saadaksesi samankaltaisia kappaleita. käytännöllinen jos sinulla on lisäosia, jotka muuttavat tätä käytöstä",
"input_preferRemoteUrl": "suosi julkista url-osoitetta",
"input_remoteUrl": "julkinen url-osoite",
"input_remoteUrlPlaceholder": "valinnainen: julkinen url-osoite ulkoisille toiminnoille"
}, },
"createPlaylist": { "createPlaylist": {
"input_public": "julkinen", "input_public": "julkinen",
@@ -293,17 +345,53 @@
"description": "kuvaus", "description": "kuvaus",
"setExpiration": "aseta vanheneminen", "setExpiration": "aseta vanheneminen",
"success": "jakolinkki kopioitu leikepöydälle (tai klikkaa tästä avataksesi)", "success": "jakolinkki kopioitu leikepöydälle (tai klikkaa tästä avataksesi)",
"expireInvalid": "vanhetumisen pitää olla tulevaisuudessa" "expireInvalid": "vanhetumisen pitää olla tulevaisuudessa",
"copyToClipboard": "Kopioi leikepöydälle: Ctrl+C, Enter",
"successMustClick": "jako luotu onnistuneesti. paina tästä avataksesi"
}, },
"queryEditor": { "queryEditor": {
"input_optionMatchAny": "sovita joku", "input_optionMatchAny": "sovita joku",
"input_optionMatchAll": "sovita kaikki", "input_optionMatchAll": "sovita kaikki",
"title": "kyselyeditori" "title": "kyselyeditori",
"addRuleGroup": "lisää sääntöryhmä",
"removeRuleGroup": "poista sääntöryhmä",
"resetToDefault": "palauta oletukset",
"clearFilters": "poista suodattimet"
}, },
"privateMode": { "privateMode": {
"enabled": "yksityinen tila käytössä, toistotila on nyt piilotettu ulkoisilta integraatioilta", "enabled": "yksityinen tila käytössä, toistotila on nyt piilotettu ulkoisilta integraatioilta",
"disabled": "yksityinen tila poissa käytössä, toistotila on nyt näkyvillä ulkoisille integraatioille", "disabled": "yksityinen tila poissa käytössä, toistotila on nyt näkyvillä ulkoisille integraatioille",
"title": "yksityinen tila" "title": "yksityinen tila"
},
"largeFetchConfirmation": {
"title": "lisää kohteet jonoon",
"description": "lisää kaikki suodatetun näkymän kohteet"
},
"createRadioStation": {
"success": "radiokanava luotu onnistuneesti",
"title": "luo radiokanava",
"input_homepageUrl": "kotisivun osoite",
"input_name": "nimi",
"input_streamUrl": "suoratoisto-osoite"
},
"lyricsExport": {
"export": "vie sanoitukset",
"input_synced": "vie ajastetut sanoitukset",
"input_offset": "$t(setting.lyricOffset)"
},
"saveQueue": {
"success": "toistojono tallennettu palvelimelle"
},
"shuffleAll": {
"title": "soita satunnainen",
"input_genre": "$t(entity.genre, {\"count\": 1})",
"input_limit": "kuinka monta kappaletta?",
"input_minYear": "vuodesta",
"input_maxYear": "vuoteen",
"input_played": "toiston suodatin",
"input_played_optionAll": "kaikki raidat",
"input_played_optionUnplayed": "vain toistamattomat raidat",
"input_played_optionPlayed": "vain toistetut raidat"
} }
}, },
"setting": { "setting": {
@@ -540,7 +628,12 @@
"releaseChannel_optionLatest": "viimeisin", "releaseChannel_optionLatest": "viimeisin",
"releaseChannel": "julkaisulinja", "releaseChannel": "julkaisulinja",
"releaseChannel_description": "valitse vakaiden ja beetaversioiden välillä automaattisille päivityksille", "releaseChannel_description": "valitse vakaiden ja beetaversioiden välillä automaattisille päivityksille",
"discordDisplayType_artistname": "artistin nimi / artistien nimet" "discordDisplayType_artistname": "artistin nimi / artistien nimet",
"autoDJ": "auto DJ",
"autoDJ_description": "lisää automaattisesti samanlaisia kappaleita jonoon",
"autoDJ_itemCount": "kohteiden määrä",
"autoDJ_itemCount_description": "jonoon lisättäväksi yritettyjen kohteiden määrä, kun auto DJ on käytössä",
"autoDJ_timing": "ajastus"
}, },
"page": { "page": {
"itemDetail": { "itemDetail": {
@@ -573,7 +666,11 @@
"collapseSidebar": "kutista sivupalkki", "collapseSidebar": "kutista sivupalkki",
"version": "versio {{version}}", "version": "versio {{version}}",
"privateModeOff": "käännä yksityinen tila pois käytöstä", "privateModeOff": "käännä yksityinen tila pois käytöstä",
"privateModeOn": "käännä yksityinen tila käyttöön" "privateModeOn": "käännä yksityinen tila käyttöön",
"commandPalette": "avaa komentopaletti",
"selectMusicFolder": "valitse musiikkikansio",
"noMusicFolder": "musiikkikansiota ei ole valittu",
"multipleMusicFolders": "{{count}} musiikkikansio(ta) valittu"
}, },
"contextMenu": { "contextMenu": {
"playSimilarSongs": "$t(player.playSimilarSongs)", "playSimilarSongs": "$t(player.playSimilarSongs)",
@@ -599,7 +696,9 @@
"moveToNext": "$t(action.moveToNext)", "moveToNext": "$t(action.moveToNext)",
"removeFromQueue": "$t(action.removeFromQueue)", "removeFromQueue": "$t(action.removeFromQueue)",
"goToAlbum": "mene $t(entity.album, {\"count\": 1})", "goToAlbum": "mene $t(entity.album, {\"count\": 1})",
"goToAlbumArtist": "mene $t(entity.albumArtist, {\"count\": 1})" "goToAlbumArtist": "mene $t(entity.albumArtist, {\"count\": 1})",
"moveItems": "$t(action.moveItems)",
"goTo": "mene"
}, },
"sidebar": { "sidebar": {
"albumArtists": "$t(entity.albumArtist, {\"count\": 2})", "albumArtists": "$t(entity.albumArtist, {\"count\": 2})",
@@ -614,14 +713,35 @@
"nowPlaying": "nyt soi", "nowPlaying": "nyt soi",
"playlists": "$t(entity.playlist, {\"count\": 2})", "playlists": "$t(entity.playlist, {\"count\": 2})",
"search": "$t(common.search)", "search": "$t(common.search)",
"myLibrary": "oma kirjasto" "myLibrary": "oma kirjasto",
"collections": "kokoelmat",
"favorites": "$t(entity.favorite, {\"count\": 2})",
"radio": "$t(entity.radioStation, {\"count\": 2})"
}, },
"setting": { "setting": {
"generalTab": "yleinen", "generalTab": "yleinen",
"windowTab": "ikkuna", "windowTab": "ikkuna",
"hotkeysTab": "pikanäppäimet", "hotkeysTab": "pikanäppäimet",
"playbackTab": "toisto", "playbackTab": "toisto",
"advanced": "edistyneet" "advanced": "edistyneet",
"analytics": "tilastot",
"updates": "päivitä",
"cache": "välimuisti",
"application": "aplikaatio",
"queryBuilder": "kyselynrakentaja",
"theme": "teema",
"controls": "säätimet",
"sidebar": "sivupalkki",
"remote": "kauko-ohjain",
"exportImport": "tuo/vie",
"scrobble": "scrobblata",
"audio": "audio",
"lyrics": "sanat",
"lyricsDisplay": "sanojen näyttö",
"transcoding": "transkoodaus",
"discord": "discord",
"logger": "lokittaja",
"playerFilters": "soittimen suodattimet"
}, },
"fullscreenPlayer": { "fullscreenPlayer": {
"upNext": "seuraavaksi", "upNext": "seuraavaksi",
@@ -665,10 +785,11 @@
"title": "$t(common.home)", "title": "$t(common.home)",
"mostPlayed": "eniten soitetut", "mostPlayed": "eniten soitetut",
"newlyAdded": "hiljattain lisätyt julkaisut", "newlyAdded": "hiljattain lisätyt julkaisut",
"recentlyReleased": "hiljattain julkaistu" "recentlyReleased": "hiljattain julkaistu",
"genres": "$t(entity.genre, {\"count\": 2})"
}, },
"albumArtistDetail": { "albumArtistDetail": {
"about": "{{artist}}{sta/stä", "about": "{{artist}}",
"viewDiscography": "katsele diskografiaa", "viewDiscography": "katsele diskografiaa",
"relatedArtists": "liittyvät $t(entity.artist, {\"count\": 2})", "relatedArtists": "liittyvät $t(entity.artist, {\"count\": 2})",
"appearsOn": "esiintyy", "appearsOn": "esiintyy",
@@ -676,7 +797,13 @@
"topSongsFrom": "parhaat kappaleet albumilta {{title}}", "topSongsFrom": "parhaat kappaleet albumilta {{title}}",
"recentReleases": "hiljattaiset julkaisut", "recentReleases": "hiljattaiset julkaisut",
"viewAll": "katsele kaikkia", "viewAll": "katsele kaikkia",
"viewAllTracks": "katsele kaikkia $t(entity.track, {\"count\": 2})" "viewAllTracks": "katsele kaikkia $t(entity.track, {\"count\": 2})",
"favoriteSongs": "suosikki kappaleet",
"groupingTypeAll": "kaikki julkaisun tyypit",
"groupingTypePrimary": "ensisijaiset tyypin julkaisut",
"topSongsCommunity": "yhteisö",
"topSongsPersonal": "henkilökohtainen",
"favoriteSongsFrom": "suosikkikappale {{title}}:sta"
}, },
"playlistList": { "playlistList": {
"title": "$t(entity.playlist, {\"count\": 2})" "title": "$t(entity.playlist, {\"count\": 2})"
@@ -696,11 +823,33 @@
"artistTracks": "artistin {{artist}} kappaleet", "artistTracks": "artistin {{artist}} kappaleet",
"genreTracks": "\"{{genre}}\" $t(entity.track, {\"count\": 2})", "genreTracks": "\"{{genre}}\" $t(entity.track, {\"count\": 2})",
"title": "$t(entity.track, {\"count\": 2})" "title": "$t(entity.track, {\"count\": 2})"
},
"radioList": {
"title": "radiokanavat"
},
"releasenotes": {
"commitsSinceStable": "muutokset {{stable}} verrattuna",
"noNewCommits": "ei uusia muutoksia tällä välillä",
"noStableReleaseToCompare": "vertailukelpoista vakaata versiota ei löytynyt"
},
"favorites": {
"title": "$t(entity.favorite, {\"count\": 2})"
},
"windowBar": {
"paused": "(Tauotettu) ",
"privateMode": "(Yksityinen tila)"
},
"folderList": {
"title": "$t(entity.folder, {\"count\": 2})"
},
"collections": {
"overrideExisting": "syrjäytä olemassa olevat",
"saveAsCollection": "tallenna kokoelmana"
} }
}, },
"player": { "player": {
"addLast": "lisää viimeinen", "addLast": "viimeinen",
"addNext": "lisää seuraava", "addNext": "seuraava",
"favorite": "suosikki", "favorite": "suosikki",
"queue_moveToTop": "siirrä valittu alas", "queue_moveToTop": "siirrä valittu alas",
"queue_remove": "poista valittu", "queue_remove": "poista valittu",
@@ -719,7 +868,7 @@
"repeat_all": "kertaa kaikki", "repeat_all": "kertaa kaikki",
"playbackFetchCancel": "tämä vie aikaa... sulje ilmoitus peruaksesi", "playbackFetchCancel": "tämä vie aikaa... sulje ilmoitus peruaksesi",
"mute": "mykistä", "mute": "mykistä",
"shuffle": "soita sekoitettuna", "shuffle": "soita (sekoitettuna)",
"next": "seuraava", "next": "seuraava",
"play": "toista", "play": "toista",
"playbackFetchInProgress": "ladataan kappaleita…", "playbackFetchInProgress": "ladataan kappaleita…",
@@ -729,7 +878,25 @@
"playSimilarSongs": "toista samanlaisia kappaleita", "playSimilarSongs": "toista samanlaisia kappaleita",
"repeat_off": "kertaus pois päältä", "repeat_off": "kertaus pois päältä",
"shuffle_off": "sekoitus pois päältä", "shuffle_off": "sekoitus pois päältä",
"toggleFullscreenPlayer": "vaihda kokoruudun soittimeen" "toggleFullscreenPlayer": "vaihda kokoruudun soittimeen",
"addLastShuffled": "viimeinen (sekoitettu)",
"addNextShuffled": "seuraava (sekoitettu)",
"albumRadio": "albumiradio",
"artistRadio": "artistiradio",
"holdToShuffle": "pidä sekoittaaksesi",
"lyrics": "sanat",
"restoreQueueFromServer": "palauta tiedustelu palvelimelta",
"saveQueueToServer": "tallenna tiedustelu palvelimelle",
"trackRadio": "raitaradio",
"sleepTimer": "uniajastin",
"sleepTimer_endOfSong": "nykyisen kappaleen loppu",
"sleepTimer_minutes": "{{count}} min",
"sleepTimer_hours": "{{count}} t",
"sleepTimer_custom": "mukautettu",
"sleepTimer_off": "pois",
"sleepTimer_timeRemaining": "{{time}} jäljellä",
"sleepTimer_setCustom": "aseta ajastin",
"sleepTimer_cancel": "peruuta ajastin"
}, },
"table": { "table": {
"config": { "config": {
@@ -828,5 +995,36 @@
"soundtrack": "elokuvamusiikki", "soundtrack": "elokuvamusiikki",
"spokenWord": "puhetta" "spokenWord": "puhetta"
} }
},
"datetime": {
"minuteShort": "m",
"secondShort": "s",
"hourShort": "t",
"dayShort": "p"
},
"filterOperator": {
"after": "jälkeen",
"afterDate": "jälkeen (päivän)",
"before": "ennen",
"beforeDate": "ennen (päivää)",
"contains": "sisältää",
"endsWith": "loppuu",
"inPlaylist": "on",
"inTheLast": "on viimeisenä",
"inTheRange": "on välillä",
"inTheRangeDate": "on valitulla aikavälillä (päivä)",
"is": "on",
"isNot": "ei ole",
"isGreaterThan": "enemmän kuin",
"isLessThan": "vähemmän kuin",
"matchesRegex": "vastaa säännöllistä lausetta (regex)",
"notContains": "ei sisällä",
"notInPlaylist": "ei ole",
"notInTheLast": "ei ole viimeisenä",
"startsWith": "alkaa"
},
"queryBuilder": {
"standardTags": "standardi tagit",
"customTags": "mukautetut tagit"
} }
} }
+378 -189
View File
File diff suppressed because it is too large Load Diff
+1 -2
View File
@@ -313,8 +313,7 @@
"editPlaylist": { "editPlaylist": {
"success": "$t(entity.playlist, {\"count\": 1}) sikeresen módosítva", "success": "$t(entity.playlist, {\"count\": 1}) sikeresen módosítva",
"publicJellyfinNote": "A Jellyfin valamiért nem teszi közzé, hogy egy lejátszási lista publikus-e vagy sem. Amennyiben azt szeretnéd, hogy publikus maradjon, válaszd ki az alábbi beviteli mezőt", "publicJellyfinNote": "A Jellyfin valamiért nem teszi közzé, hogy egy lejátszási lista publikus-e vagy sem. Amennyiben azt szeretnéd, hogy publikus maradjon, válaszd ki az alábbi beviteli mezőt",
"title": "szerkesztés $t(entity.playlist, {\"count\": 1})", "title": "szerkesztés $t(entity.playlist, {\"count\": 1})"
"editNote": "A kézi szerkesztés nem ajánlott nagy lejátszási listák esetén. Biztosan vállalod a meglévő lejátszási lista felülírásával járó adatvesztés kockázatát?"
}, },
"lyricSearch": { "lyricSearch": {
"input_artist": "$t(entity.artist, {\"count\": 1})", "input_artist": "$t(entity.artist, {\"count\": 1})",
+58 -13
View File
@@ -37,7 +37,8 @@
"shuffleAll": "acak semua", "shuffleAll": "acak semua",
"shuffleSelected": "acak yang dipilih", "shuffleSelected": "acak yang dipilih",
"viewMore": "lihat lebih banyak", "viewMore": "lihat lebih banyak",
"openApplicationDirectory": "buka direktori aplikasi" "openApplicationDirectory": "buka direktori aplikasi",
"goToCurrent": "pergi ke item saat ini"
}, },
"common": { "common": {
"clear": "bersihkan", "clear": "bersihkan",
@@ -208,7 +209,9 @@
"noNetworkDescription": "tidak dapat terhubung ke server ini", "noNetworkDescription": "tidak dapat terhubung ke server ini",
"notificationDenied": "izin untuk notifikasi ditolak. pengaturan ini tidak berpengaruh", "notificationDenied": "izin untuk notifikasi ditolak. pengaturan ini tidak berpengaruh",
"saveQueueFailed": "gagal menyimpan antrean", "saveQueueFailed": "gagal menyimpan antrean",
"settingsSyncError": "ditemukan ketidaksesuaian antara pengaturan di perender dan proses utama. mulai ulang aplikasi untuk menerapkan perubahan" "settingsSyncError": "ditemukan ketidaksesuaian antara pengaturan di perender dan proses utama. mulai ulang aplikasi untuk menerapkan perubahan",
"invalidJson": "JSON tidak valid",
"serverLockSingleServer": "hanya satu server yang diizinkan ketika server dikunci"
}, },
"filter": { "filter": {
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
@@ -254,7 +257,9 @@
"title": "judul", "title": "judul",
"path": "path(jalur)", "path": "path(jalur)",
"sortName": "nama pengurutan", "sortName": "nama pengurutan",
"explicitStatus": "$t(common.explicitStatus)" "explicitStatus": "$t(common.explicitStatus)",
"matchAnd": "dan",
"matchOr": "atau"
}, },
"form": { "form": {
"addServer": { "addServer": {
@@ -299,8 +304,7 @@
"editPlaylist": { "editPlaylist": {
"publicJellyfinNote": "Jellyfin entah bagaimana tidak menampilkan apakah playlist ini publik atau tidak. Jika Anda ingin playlist ini tetap publik, harap pilih entri berikut", "publicJellyfinNote": "Jellyfin entah bagaimana tidak menampilkan apakah playlist ini publik atau tidak. Jika Anda ingin playlist ini tetap publik, harap pilih entri berikut",
"success": "$t(entity.playlist, {\"count\": 1}) berhasil diperbarui", "success": "$t(entity.playlist, {\"count\": 1}) berhasil diperbarui",
"title": "ubah $t(entity.playlist, {\"count\": 1})", "title": "ubah $t(entity.playlist, {\"count\": 1})"
"editNote": "pengeditan manual tidak disarankan untuk playlist besar. apakah Anda yakin menerima risiko kehilangan data yang timbul akibat menimpa playlist yang ada?"
}, },
"lyricSearch": { "lyricSearch": {
"input_artist": "$t(entity.artist, {\"count\": 1})", "input_artist": "$t(entity.artist, {\"count\": 1})",
@@ -322,7 +326,9 @@
"setExpiration": "Atur masa berlaku", "setExpiration": "Atur masa berlaku",
"success": "Tautan berbagi berhasil disalin ke papan klip (atau klik di sini untuk membuka)", "success": "Tautan berbagi berhasil disalin ke papan klip (atau klik di sini untuk membuka)",
"expireInvalid": "Masa berlaku harus di masa depan", "expireInvalid": "Masa berlaku harus di masa depan",
"createFailed": "Tidak dapat membuat sumber daya berbagi (Apakah berbagi diaktifkan?)" "createFailed": "Tidak dapat membuat sumber daya berbagi (Apakah berbagi diaktifkan?)",
"copyToClipboard": "Salin ke clipboard: Ctrl+C, Enter",
"successMustClick": "berbagi berhasil dibuat. klik di sini untuk membuka"
}, },
"updateServer": { "updateServer": {
"success": "Server berhasil diperbarui", "success": "Server berhasil diperbarui",
@@ -376,7 +382,11 @@
"viewAllTracks": "Lihat semua $t(entity.track, {\"count\": 2})", "viewAllTracks": "Lihat semua $t(entity.track, {\"count\": 2})",
"appearsOn": "Tampil di", "appearsOn": "Tampil di",
"groupingTypeAll": "semua jenis rilis", "groupingTypeAll": "semua jenis rilis",
"groupingTypePrimary": "jenis rilis utama" "groupingTypePrimary": "jenis rilis utama",
"favoriteSongs": "lagu favorit",
"topSongsCommunity": "komunitas",
"topSongsPersonal": "pribadi",
"favoriteSongsFrom": "lagu favorit dari {{title}}"
}, },
"albumArtistList": { "albumArtistList": {
"title": "$t(entity.albumArtist, {\"count\": 2})" "title": "$t(entity.albumArtist, {\"count\": 2})"
@@ -565,6 +575,11 @@
"collections": { "collections": {
"overrideExisting": "timpa yang ada", "overrideExisting": "timpa yang ada",
"saveAsCollection": "simpan sebagai koleksi" "saveAsCollection": "simpan sebagai koleksi"
},
"releasenotes": {
"commitsSinceStable": "commit sejak {{stable}}",
"noNewCommits": "tidak ada commit baru dalam rentang ini",
"noStableReleaseToCompare": "tidak ada rilis stabil yang tersedia untuk dibandingkan"
} }
}, },
"player": { "player": {
@@ -606,7 +621,17 @@
"lyrics": "lirik", "lyrics": "lirik",
"restoreQueueFromServer": "pulihkan antrean dari server", "restoreQueueFromServer": "pulihkan antrean dari server",
"saveQueueToServer": "simpan antrean ke server", "saveQueueToServer": "simpan antrean ke server",
"trackRadio": "radio trek" "trackRadio": "radio trek",
"albumRadio": "radio album",
"sleepTimer": "pengatur waktu tidur",
"sleepTimer_endOfSong": "akhir lagu saat ini",
"sleepTimer_minutes": "{{count}} menit",
"sleepTimer_hours": "{{count}} jam",
"sleepTimer_custom": "kustom",
"sleepTimer_off": "mati",
"sleepTimer_timeRemaining": "{{time}} tersisa",
"sleepTimer_setCustom": "atur pengatur waktu",
"sleepTimer_cancel": "batalkan pengatur waktu"
}, },
"setting": { "setting": {
"accentColor": "warna sorotan", "accentColor": "warna sorotan",
@@ -620,7 +645,7 @@
"artistConfiguration": "Pengaturan halaman artis album", "artistConfiguration": "Pengaturan halaman artis album",
"artistConfiguration_description": "Atur elemen apa yang ditampilkan dan urutannya di halaman artis album", "artistConfiguration_description": "Atur elemen apa yang ditampilkan dan urutannya di halaman artis album",
"audioDevice": "perangkat audio", "audioDevice": "perangkat audio",
"audioDevice_description": "pilih perangkat audio yang digunakan untuk pemutaran (hanya pemutar web)", "audioDevice_description": "pilih perangkat audio yang digunakan untuk pemutaran",
"audioExclusiveMode": "mode audio eksklusif", "audioExclusiveMode": "mode audio eksklusif",
"audioExclusiveMode_description": "aktifkan mode audio eksklusif. Dalam mode ini, sistem biasanya diblokir, dan hanya mpv yang akan diizinkan untuk output audio", "audioExclusiveMode_description": "aktifkan mode audio eksklusif. Dalam mode ini, sistem biasanya diblokir, dan hanya mpv yang akan diizinkan untuk output audio",
"audioPlayer": "pemutar audio", "audioPlayer": "pemutar audio",
@@ -839,7 +864,7 @@
"releaseChannel_optionBeta": "beta", "releaseChannel_optionBeta": "beta",
"releaseChannel_optionLatest": "terbaru", "releaseChannel_optionLatest": "terbaru",
"releaseChannel": "kanal rilis", "releaseChannel": "kanal rilis",
"releaseChannel_description": "pilih antara rilis stabil atau rilis beta untuk pembaruan otomatis", "releaseChannel_description": "pilih antara rilis stabil, beta, atau alpha (nightly) untuk pembaruan otomatis",
"discordDisplayType_artistname": "nama artis", "discordDisplayType_artistname": "nama artis",
"discordDisplayType_description": "mengubah apa yang Anda dengarkan di status Anda", "discordDisplayType_description": "mengubah apa yang Anda dengarkan di status Anda",
"discordDisplayType_songname": "nama lagu", "discordDisplayType_songname": "nama lagu",
@@ -947,7 +972,25 @@
"queryBuilderCustomFields_inputLabel": "label", "queryBuilderCustomFields_inputLabel": "label",
"queryBuilderCustomFields_inputTag": "tag", "queryBuilderCustomFields_inputTag": "tag",
"queryBuilderCustomFields": "kolom kustom", "queryBuilderCustomFields": "kolom kustom",
"queryBuilderCustomFields_description": "tambahkan kolom kustom untuk digunakan di pembuat kueri" "queryBuilderCustomFields_description": "tambahkan kolom kustom untuk digunakan di pembuat kueri",
"useThemePrimaryShade": "gunakan warna utama tema",
"useThemePrimaryShade_description": "gunakan warna utama yang ditentukan dalam tema yang dipilih untuk varian warna utama",
"primaryShade": "warna utama tema",
"primaryShade_description": "timpa warna utama (09) yang digunakan untuk tombol, tautan, dan elemen berwarna utama lainnya",
"analyticsEnable": "Kirim analitik berbasis penggunaan",
"analyticsEnable_description": "Data penggunaan yang dianonimkan dikirim ke pengembang untuk membantu meningkatkan aplikasi",
"automaticUpdates": "Pembaruan otomatis",
"automaticUpdates_description": "Periksa dan instal pembaruan secara otomatis",
"releaseChannel_optionAlpha": "alpha (nightly)",
"discordStateIcon": "tampilkan ikon sedang diputar",
"discordStateIcon_description": "tampilkan ikon kecil sedang diputar di status rich presence. ikon dijeda selalu ditampilkan ketika \"Tampilkan rich presence saat dijeda\" diaktifkan",
"blurExplicitImages": "buramkan gambar eksplisit",
"blurExplicitImages_description": "sampul album dan lagu yang ditandai sebagai eksplisit akan diburamkan",
"playerItemConfiguration_description": "konfigurasikan item apa yang ditampilkan, dan dalam urutan apa, pada pemutar layar penuh",
"playerItemConfiguration": "konfigurasi item pemutar",
"sidebarPlaylistListFilterRegex_description": "sembunyikan playlist di bilah sisi yang cocok dengan ekspresi reguler ini",
"sidebarPlaylistListFilterRegex_placeholder": "mis. ^Daily Mix.*",
"sidebarPlaylistListFilterRegex": "regex filter playlist"
}, },
"table": { "table": {
"column": { "column": {
@@ -1047,12 +1090,14 @@
"genreBadge": "$t(entity.genre, {\"count\": 1}) (lencana)", "genreBadge": "$t(entity.genre, {\"count\": 1}) (lencana)",
"image": "gambar", "image": "gambar",
"sampleRate": "$t(common.sampleRate)", "sampleRate": "$t(common.sampleRate)",
"titleArtist": "$t(common.title) (artis)" "titleArtist": "$t(common.title) (artis)",
"albumGroup": "grup album"
}, },
"view": { "view": {
"table": "tabel", "table": "tabel",
"grid": "kisi", "grid": "kisi",
"list": "daftar" "list": "daftar",
"detail": "detail"
} }
} }
}, },
+277 -30
View File
@@ -21,7 +21,20 @@
"openIn": { "openIn": {
"lastfm": "Apri in Last.fm", "lastfm": "Apri in Last.fm",
"musicbrainz": "Apri in MusicBrainz" "musicbrainz": "Apri in MusicBrainz"
} },
"addOrRemoveFromSelection": "aggiungi o rimuovi dalla selezione",
"selectRangeOfItems": "seleziona un intervallo di elementi",
"createRadioStation": "crea $t(entity.radioStation, {\"count\": 1})",
"deleteRadioStation": "rimuovi $t(entity.radioStation, {\"count\": 1})",
"selectAll": "seleziona tutto",
"downloadStarted": "download di {{count}} elementi iniziato",
"moveUp": "sposta sopra",
"moveDown": "sposta in basso",
"holdToMoveToTop": "tieni premuto per muovere in cima",
"holdToMoveToBottom": "tieni premuto per muoverlo in fondo",
"moveItems": "muovi elementi",
"shuffle": "casuale",
"viewMore": "mostra di più"
}, },
"common": { "common": {
"backward": "indietro", "backward": "indietro",
@@ -76,8 +89,8 @@
"delete": "elimina", "delete": "elimina",
"forceRestartRequired": "riavvia per applicare le modifiche... chiudi la notifica per riavviare", "forceRestartRequired": "riavvia per applicare le modifiche... chiudi la notifica per riavviare",
"setting_one": "impostazione", "setting_one": "impostazione",
"setting_many": "", "setting_many": "impostazioni",
"setting_other": "", "setting_other": "impostazioni",
"version": "versione", "version": "versione",
"title": "titolo", "title": "titolo",
"filter_one": "filtro", "filter_one": "filtro",
@@ -115,6 +128,7 @@
"close": "chiudi", "close": "chiudi",
"codec": "codec", "codec": "codec",
"mbid": "MusicBrainz ID", "mbid": "MusicBrainz ID",
"grouping": "raggruppamento",
"preview": "anteprima", "preview": "anteprima",
"reload": "aggiorna", "reload": "aggiorna",
"share": "condividi", "share": "condividi",
@@ -123,7 +137,24 @@
"trackPeak": "picco di volume del brano", "trackPeak": "picco di volume del brano",
"translation": "traduzione", "translation": "traduzione",
"bitDepth": "bit depth (profondità di bit)", "bitDepth": "bit depth (profondità di bit)",
"sampleRate": "sample rate (frequenza di campionamento)" "sampleRate": "sample rate (frequenza di campionamento)",
"countSelected": "{{count}} selezionati",
"doNotShowAgain": "non mostrarlo di nuovo",
"view": "visualizza",
"example": "esempio",
"externalLinks": "link esterni",
"faster": "più rapido",
"filter_single": "singolo",
"noFilters": "nessun filtro configurato",
"private": "privato",
"public": "pubblico",
"retry": "riprova",
"recordLabel": "registra etichetta",
"rename": "rinomina",
"sort": "ordina",
"explicit": "esplicito",
"clean": "pulisci",
"itemsMore": "ancora {{count}}"
}, },
"player": { "player": {
"repeat_all": "ripeti coda", "repeat_all": "ripeti coda",
@@ -140,7 +171,7 @@
"shuffle": "riproduzione casuale", "shuffle": "riproduzione casuale",
"playbackFetchNoResults": "nessuna canzone trovata", "playbackFetchNoResults": "nessuna canzone trovata",
"playbackFetchInProgress": "caricamento canzoni…", "playbackFetchInProgress": "caricamento canzoni…",
"addNext": "aggiungi successivo", "addNext": "successivo",
"playbackSpeed": "velocità di riproduzione", "playbackSpeed": "velocità di riproduzione",
"playbackFetchCancel": "ci sta mettendo un po'... chiudi la notifica per annullare", "playbackFetchCancel": "ci sta mettendo un po'... chiudi la notifica per annullare",
"play": "riproduci", "play": "riproduci",
@@ -152,18 +183,30 @@
"queue_moveToTop": "sposta selezionati in fondo", "queue_moveToTop": "sposta selezionati in fondo",
"queue_moveToBottom": "sposta selezionati in cima", "queue_moveToBottom": "sposta selezionati in cima",
"shuffle_off": "non mescolare", "shuffle_off": "non mescolare",
"addLast": "aggiungi in coda", "addLast": "per ultima",
"mute": "silenzia", "mute": "silenzia",
"skip_forward": "salta avanti", "skip_forward": "salta avanti",
"playSimilarSongs": "riproduci brani simili", "playSimilarSongs": "riproduci brani simili",
"viewQueue": "visualizza coda" "viewQueue": "visualizza coda",
"holdToShuffle": "tieni premuto per la riproduzione casuale",
"lyrics": "testi",
"restoreQueueFromServer": "ripristina coda dal server",
"saveQueueToServer": "salva coda sul server",
"trackRadio": "radio della traccia",
"sleepTimer_minutes": "{{count}} minuti",
"sleepTimer_hours": "{{count}} ore",
"sleepTimer_custom": "personalizzato",
"sleepTimer_off": "spento",
"sleepTimer_timeRemaining": "{{time}} rimanente",
"sleepTimer_setCustom": "imposta timer",
"sleepTimer_cancel": "cancella timer"
}, },
"setting": { "setting": {
"crossfadeStyle_description": "seleziona lo stile dissolvenza da usare per il player audio", "crossfadeStyle_description": "seleziona lo stile dissolvenza da usare per il player audio",
"remotePort_description": "imposta la porta del server di controllo remoto", "remotePort_description": "imposta la porta del server di controllo remoto",
"hotkey_skipBackward": "salta a precedente", "hotkey_skipBackward": "salta a precedente",
"volumeWheelStep_description": "la quantità di volume da cambiare quando si scorre la rotellina del mouse sullo slider del volume", "volumeWheelStep_description": "la quantità di volume da cambiare quando si scorre la rotellina del mouse sullo slider del volume",
"audioDevice_description": "seleziona il device audioda usare per la riproduzione (solo web player)", "audioDevice_description": "seleziona il dispositivo audio da usare per la riproduzione",
"theme_description": "imposta il tema da usare per l'applicazione", "theme_description": "imposta il tema da usare per l'applicazione",
"hotkey_playbackPause": "pausa", "hotkey_playbackPause": "pausa",
"hotkey_volumeUp": "alza volume", "hotkey_volumeUp": "alza volume",
@@ -260,7 +303,7 @@
"useSystemTheme_description": "segui le preferenze del tema definite dal sistema", "useSystemTheme_description": "segui le preferenze del tema definite dal sistema",
"playButtonBehavior_optionAddNext": "$t(player.addNext)", "playButtonBehavior_optionAddNext": "$t(player.addNext)",
"lyricFetch_description": "ottieni testi da varie sorgenti internet", "lyricFetch_description": "ottieni testi da varie sorgenti internet",
"lyricFetchProvider_description": "seleziona i provider da dove prendere i testi. l'ordine dei provider è l'ordine in cui vengono fatte le richieste", "lyricFetchProvider_description": "seleziona i provider dai quali prendere i testi",
"globalMediaHotkeys_description": "attiva/disattiva l'uso dei tasti media globali per controllare la riproduzione", "globalMediaHotkeys_description": "attiva/disattiva l'uso dei tasti media globali per controllare la riproduzione",
"customFontPath": "percorso font personalizzato", "customFontPath": "percorso font personalizzato",
"followLyric": "segui testo corrente", "followLyric": "segui testo corrente",
@@ -393,7 +436,35 @@
"discordLinkType": "link di attività {{discord}}", "discordLinkType": "link di attività {{discord}}",
"discordLinkType_description": "aggiunge collegamenti esterni a {{lastfm}} o {{musicbrainz}} ai campi del brano e dell'artista nell'attività {{discord}}. {{musicbrainz}} è il più accurato, ma richiede tag e non fornisce collegamenti dell'artista mentre {{lastfm}} dovrebbe sempre fornire un link. non rende richieste di rete extra", "discordLinkType_description": "aggiunge collegamenti esterni a {{lastfm}} o {{musicbrainz}} ai campi del brano e dell'artista nell'attività {{discord}}. {{musicbrainz}} è il più accurato, ma richiede tag e non fornisce collegamenti dell'artista mentre {{lastfm}} dovrebbe sempre fornire un link. non rende richieste di rete extra",
"discordLinkType_none": "$t(common.none)", "discordLinkType_none": "$t(common.none)",
"discordLinkType_mbz_lastfm": "{{musicbrainz}} con {{lastfm}} fallback" "discordLinkType_mbz_lastfm": "{{musicbrainz}} con {{lastfm}} fallback",
"autoDJ": "auto DJ",
"autoDJ_description": "aggiungi automaticamente canzoni simili alla coda",
"autoDJ_itemCount": "conteggio elementi",
"analyticsDisable_description": "Alcuni dati anonimi sull'utilizzo vengono inviati allo sviluppatore per migliorare l'applicazione",
"artistBackground": "immagine dello sfondo dell'artista",
"releaseChannel_optionBeta": "beta",
"releaseChannel_optionLatest": "ultima",
"releaseChannel": "canale di rilascio",
"releaseChannel_description": "seleziona tra rilascio stabile, beta o alpha (nightly) per gli aggiornamenti automatici",
"discordRichPresence": "{{discord}} rich presence",
"releaseChannel_optionAlpha": "alpha (nightly)",
"automaticUpdates_description": "Controlla e installa aggiornamenti automaticamente",
"automaticUpdates": "Aggiornamenti automatici",
"exportImportSettings_notValidJSON": "il file passato non è un JSON valido",
"language": "lingua",
"logLevel_optionDebug": "debug",
"logLevel_optionError": "errore",
"logLevel_optionInfo": "info",
"pathReplace_optionRemovePrefix": "rimuovi prefisso",
"pathReplace_optionAddPrefix": "aggiungi prefisso",
"playerFilters": "Filtra canzoni dalla coda",
"imageResolution_optionHeader": "header",
"playerbarWaveformAlign_optionTop": "in cima",
"sidebarPlaylistListFilterRegex_placeholder": "es. ^Daily Mix.*",
"transcode": "abilita transcodifica",
"queryBuilderCustomFields_inputLabel": "etichetta",
"queryBuilderCustomFields_inputTag": "tag",
"queryBuilderCustomFields": "campi personalizzati"
}, },
"error": { "error": {
"remotePortWarning": "riavvia il server per applicare la nuova porta", "remotePortWarning": "riavvia il server per applicare la nuova porta",
@@ -419,14 +490,17 @@
"badValue": "opzione non valida \"{{value}}\". valore inesistente", "badValue": "opzione non valida \"{{value}}\". valore inesistente",
"networkError": "si è verificato un errore di rete", "networkError": "si è verificato un errore di rete",
"openError": "impossibile aprire il file", "openError": "impossibile aprire il file",
"notificationDenied": "i permessi per le notifiche non sono stati concessi. questa configurazione non ha effetto" "notificationDenied": "i permessi per le notifiche non sono stati concessi. questa configurazione non ha effetto",
"invalidJson": "JSON non valido",
"noNetwork": "server non disponibile",
"noNetworkDescription": "impossibile connettersi al server"
}, },
"filter": { "filter": {
"mostPlayed": "più riprodotti", "mostPlayed": "più riprodotti",
"comment": "commento", "comment": "commento",
"playCount": "numero di riproduzioni", "playCount": "numero di riproduzioni",
"recentlyUpdated": "aggiornati recentemente", "recentlyUpdated": "aggiornati recentemente",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel, {\"count\": 2})",
"isCompilation": "è una compilation", "isCompilation": "è una compilation",
"recentlyPlayed": "riprodotti recentemente", "recentlyPlayed": "riprodotti recentemente",
"isRated": "è valutato", "isRated": "è valutato",
@@ -463,7 +537,9 @@
"fromYear": "dall'anno", "fromYear": "dall'anno",
"criticRating": "voto della critica", "criticRating": "voto della critica",
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
"trackNumber": "traccia" "trackNumber": "traccia",
"matchOr": "o",
"sortName": "ordina nome"
}, },
"page": { "page": {
"sidebar": { "sidebar": {
@@ -479,7 +555,10 @@
"artists": "$t(entity.artist, {\"count\": 2})", "artists": "$t(entity.artist, {\"count\": 2})",
"albumArtists": "$t(entity.albumArtist, {\"count\": 2})", "albumArtists": "$t(entity.albumArtist, {\"count\": 2})",
"myLibrary": "la mia libreria", "myLibrary": "la mia libreria",
"shared": "condivisa $t(entity.playlist, {\"count\": 2})" "shared": "condivisa $t(entity.playlist, {\"count\": 2})",
"collections": "collezioni",
"favorites": "$t(entity.favorite, {\"count\": 2})",
"radio": "$t(entity.radioStation, {\"count\": 2})"
}, },
"fullscreenPlayer": { "fullscreenPlayer": {
"config": { "config": {
@@ -516,7 +595,10 @@
"goBack": "torna indietro", "goBack": "torna indietro",
"goForward": "vai avanti", "goForward": "vai avanti",
"privateModeOff": "disabilita modalità privata", "privateModeOff": "disabilita modalità privata",
"privateModeOn": "abilita modalità privata" "privateModeOn": "abilita modalità privata",
"selectMusicFolder": "seleziona cartella con musica",
"noMusicFolder": "nessuna cartella con musica selezionata",
"multipleMusicFolders": "{{count}} cartelle con musica selezionate"
}, },
"contextMenu": { "contextMenu": {
"addToPlaylist": "$t(action.addToPlaylist)", "addToPlaylist": "$t(action.addToPlaylist)",
@@ -542,7 +624,9 @@
"shareItem": "condividi elemento", "shareItem": "condividi elemento",
"showDetails": "mostra info", "showDetails": "mostra info",
"goToAlbum": "vai a $t(entity.album, {\"count\": 1})", "goToAlbum": "vai a $t(entity.album, {\"count\": 1})",
"goToAlbumArtist": "vai a $t(entity.albumArtist, {\"count\": 1})" "goToAlbumArtist": "vai a $t(entity.albumArtist, {\"count\": 1})",
"moveItems": "$t(action.moveItems)",
"goTo": "vai a"
}, },
"home": { "home": {
"mostPlayed": "più riprodotti", "mostPlayed": "più riprodotti",
@@ -550,7 +634,8 @@
"title": "$t(common.home)", "title": "$t(common.home)",
"explore": "esplora dalla tua libreria", "explore": "esplora dalla tua libreria",
"recentlyPlayed": "riprodotti recentemente", "recentlyPlayed": "riprodotti recentemente",
"recentlyReleased": "appena pubblicato" "recentlyReleased": "appena pubblicato",
"genres": "$t(entity.genre, {\"count\": 2})"
}, },
"albumDetail": { "albumDetail": {
"moreFromArtist": "di più da questo $t(entity.artist, {\"count\": 1})", "moreFromArtist": "di più da questo $t(entity.artist, {\"count\": 1})",
@@ -562,7 +647,20 @@
"generalTab": "generale", "generalTab": "generale",
"hotkeysTab": "tasti a scelta rapida", "hotkeysTab": "tasti a scelta rapida",
"windowTab": "finestra", "windowTab": "finestra",
"advanced": "avanzate" "advanced": "avanzate",
"updates": "aggiorna",
"cache": "cache",
"application": "applicazione",
"theme": "tema",
"controls": "controlla",
"remote": "remoto",
"exportImport": "importa/esporta",
"scrobble": "scrobble",
"audio": "audio",
"lyrics": "testi",
"transcoding": "transcodifica",
"discord": "discord",
"lyricsDisplay": "mostra testi"
}, },
"albumArtistList": { "albumArtistList": {
"title": "$t(entity.albumArtist, {\"count\": 2})" "title": "$t(entity.albumArtist, {\"count\": 2})"
@@ -602,7 +700,10 @@
"topSongs": "brani migliori", "topSongs": "brani migliori",
"topSongsFrom": "brani migliori da {{title}}", "topSongsFrom": "brani migliori da {{title}}",
"viewAll": "mostra tutto", "viewAll": "mostra tutto",
"viewAllTracks": "mostra tutto $t(entity.track, {\"count\": 2})" "viewAllTracks": "mostra tutto $t(entity.track, {\"count\": 2})",
"favoriteSongs": "canzoni preferite",
"topSongsPersonal": "personale",
"favoriteSongsFrom": "canzoni preferite da {{title}}"
}, },
"manageServers": { "manageServers": {
"title": "gestisci servers", "title": "gestisci servers",
@@ -619,6 +720,16 @@
}, },
"playlist": { "playlist": {
"reorder": "riordino abilitato solo quando si ordina per id" "reorder": "riordino abilitato solo quando si ordina per id"
},
"radioList": {
"title": "stazioni radio"
},
"folderList": {
"title": "$t(entity.folder, {\"count\": 2})"
},
"collections": {
"overrideExisting": "sovrascrivi esistente",
"saveAsCollection": "salva come collezione"
} }
}, },
"form": { "form": {
@@ -648,13 +759,17 @@
"ignoreCors": "ignora cors ($t(common.restartRequired))", "ignoreCors": "ignora cors ($t(common.restartRequired))",
"error_savePassword": "si è verificato un errore quando si è provato a salvare la password", "error_savePassword": "si è verificato un errore quando si è provato a salvare la password",
"input_preferInstantMix": "preferisci mix istantaneo", "input_preferInstantMix": "preferisci mix istantaneo",
"input_preferInstantMixDescription": "usa solo mix istantaneo per ottenere canzoni simili. utile se si dispone di plugin che modificano questo comportamento" "input_preferInstantMixDescription": "usa solo mix istantaneo per ottenere canzoni simili. utile se si dispone di plugin che modificano questo comportamento",
"input_preferRemoteUrl": "preferisci url pubblico",
"input_remoteUrl": "url pubblico"
}, },
"addToPlaylist": { "addToPlaylist": {
"success": "aggiunto $t(entity.trackWithCount, {\"count\": {{message}} }) a $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} })", "success": "aggiunto $t(entity.trackWithCount, {\"count\": {{message}} }) a $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} })",
"title": "aggiungi a $t(entity.playlist, {\"count\": 1})", "title": "aggiungi a $t(entity.playlist, {\"count\": 1})",
"input_skipDuplicates": "salta duplicati", "input_skipDuplicates": "salta duplicati",
"input_playlists": "$t(entity.playlist, {\"count\": 2})" "input_playlists": "$t(entity.playlist, {\"count\": 2})",
"create": "crea $t(entity.playlist, {\"count\": 1})",
"searchOrCreate": "cerca $t(entity.playlist, {\"count\": 2}) o digita per crearne una nuova"
}, },
"updateServer": { "updateServer": {
"title": "aggiorna server", "title": "aggiorna server",
@@ -663,7 +778,9 @@
"queryEditor": { "queryEditor": {
"input_optionMatchAll": "soddisfa tutti", "input_optionMatchAll": "soddisfa tutti",
"input_optionMatchAny": "soddisfa qualsiasi", "input_optionMatchAny": "soddisfa qualsiasi",
"title": "editor di query" "title": "editor di query",
"resetToDefault": "ripristina predefinito",
"clearFilters": "rimuovi filtri"
}, },
"lyricSearch": { "lyricSearch": {
"input_name": "$t(common.name)", "input_name": "$t(common.name)",
@@ -687,6 +804,27 @@
"enabled": "la modalità privata è abilitata: lo stato di riproduzione viene ora nascosto alle integrazioni esterne", "enabled": "la modalità privata è abilitata: lo stato di riproduzione viene ora nascosto alle integrazioni esterne",
"disabled": "la modalità privata è disabilitata: lo stato di riproduzione è ora visibile alle integrazioni esterne abilitate", "disabled": "la modalità privata è disabilitata: lo stato di riproduzione è ora visibile alle integrazioni esterne abilitate",
"title": "modalità privata" "title": "modalità privata"
},
"largeFetchConfirmation": {
"title": "aggiungi elementi alla coda"
},
"createRadioStation": {
"success": "stazione radio creata con successo",
"title": "crea stazione radio",
"input_name": "nome"
},
"lyricsExport": {
"export": "esporta testi",
"input_synced": "esporta testi sincronizzati",
"input_offset": "$t(setting.lyricOffset)"
},
"shuffleAll": {
"input_limit": "quante canzoni?",
"input_minYear": "dall'anno",
"input_maxYear": "all'anno",
"input_played_optionAll": "tutte le tracce",
"input_played_optionUnplayed": "solo tracce non ancora riprodotte",
"input_played_optionPlayed": "solo tracce riprodotte"
} }
}, },
"table": { "table": {
@@ -699,12 +837,29 @@
"size": "$t(common.size)", "size": "$t(common.size)",
"followCurrentSong": "segui il brano corrente", "followCurrentSong": "segui il brano corrente",
"itemGap": "spaziatura tra gli elementi (px)", "itemGap": "spaziatura tra gli elementi (px)",
"itemSize": "dimensione dellelemento (px)" "itemSize": "dimensione dellelemento (px)",
"advancedSettings": "impostazioni avanzate",
"moveUp": "muovi sopra",
"moveDown": "muovi sotto",
"pinToLeft": "fissa a sinistra",
"pinToRight": "fissa a destra",
"alignLeft": "allinea a sinistra",
"alignCenter": "allina al centro",
"alignRight": "allinea a destra",
"itemsPerRow": "elementi per riga",
"size_default": "predefinito",
"size_compact": "compatto",
"size_large": "largo",
"pagination": "paginazione",
"pagination_itemsPerPage": "elementi per pagina",
"pagination_infinite": "infinita",
"pagination_paginate": "impaginato"
}, },
"view": { "view": {
"table": "tabella", "table": "tabella",
"grid": "griglia", "grid": "griglia",
"list": "lista" "list": "lista",
"detail": "dettaglio"
}, },
"label": { "label": {
"releaseDate": "data rilascio", "releaseDate": "data rilascio",
@@ -724,17 +879,23 @@
"biography": "$t(common.biography)", "biography": "$t(common.biography)",
"owner": "$t(common.owner)", "owner": "$t(common.owner)",
"path": "$t(common.path)", "path": "$t(common.path)",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel, {\"count\": 2})",
"playCount": "numero riproduzioni", "playCount": "numero riproduzioni",
"bitrate": "$t(common.bitrate)", "bitrate": "$t(common.bitrate)",
"actions": "$t(common.action_other)", "actions": "$t(common.action, {\"count\": 2})",
"genre": "$t(entity.genre, {\"count\": 1})", "genre": "$t(entity.genre, {\"count\": 1})",
"discNumber": "numero disco", "discNumber": "numero disco",
"favorite": "$t(common.favorite)", "favorite": "$t(common.favorite)",
"year": "$t(common.year)", "year": "$t(common.year)",
"albumArtist": "$t(entity.albumArtist, {\"count\": 1})", "albumArtist": "$t(entity.albumArtist, {\"count\": 1})",
"codec": "$t(common.codec)", "codec": "$t(common.codec)",
"songCount": "$t(entity.track, {\"count\": 2})" "songCount": "$t(entity.track, {\"count\": 2})",
"bitDepth": "$t(common.bitDepth)",
"albumCount": "$t(entity.album, {\"count\": 2})",
"composer": "compositore",
"image": "immagine",
"sampleRate": "$t(common.sampleRate)",
"titleArtist": "$t(common.title) (artista)"
} }
}, },
"column": { "column": {
@@ -759,9 +920,12 @@
"albumArtist": "artista album", "albumArtist": "artista album",
"path": "percorso", "path": "percorso",
"discNumber": "disco", "discNumber": "disco",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel, {\"count\": 2})",
"size": "$t(common.size)", "size": "$t(common.size)",
"codec": "$t(common.codec)" "codec": "$t(common.codec)",
"bitDepth": "$t(common.bitDepth)",
"sampleRate": "$t(common.sampleRate)",
"owner": "proprietario"
} }
}, },
"entity": { "entity": {
@@ -816,6 +980,89 @@
"play_other": "{{count}} riproduzioni", "play_other": "{{count}} riproduzioni",
"song_one": "traccia", "song_one": "traccia",
"song_many": "tracce", "song_many": "tracce",
"song_other": "tracce" "song_other": "tracce",
"radioStation_one": "stazione radio",
"radioStation_many": "stazioni radio",
"radioStation_other": "stazioni radio",
"radioStationWithCount_one": "{{count}} stazione radio",
"radioStationWithCount_many": "{{count}} stazioni radio",
"radioStationWithCount_other": "{{count}} stazioni radio"
},
"datetime": {
"minuteShort": "m",
"secondShort": "s",
"hourShort": "o",
"dayShort": "g"
},
"filterOperator": {
"contains": "contiene",
"endsWith": "finisce con",
"inPlaylist": "è in",
"is": "è",
"isNot": "non è",
"isGreaterThan": "è più grande di",
"isLessThan": "è meno di",
"notContains": "non contiene",
"notInPlaylist": "non è in",
"startsWith": "inizia con"
},
"releaseType": {
"primary": {
"album": "$t(entity.album, {\"count\": 1})",
"broadcast": "broadcast",
"ep": "ep",
"other": "altro",
"single": "singolo"
},
"secondary": {
"audiobook": "audiolibro",
"audioDrama": "audio drama",
"compilation": "compilation",
"interview": "intervista",
"live": "live",
"mixtape": "mixtape",
"remix": "remix",
"soundtrack": "soundtrack"
}
},
"queryBuilder": {
"customTags": "tag personalizzati"
},
"dragDropZone": {
"error_oneFileOnly": "Per favore seleziona solo 1 file",
"error_readingFile": "errore nella lettura del file: {{errorMessage}}",
"mainText": "rilascia un file qui"
},
"visualizer": {
"ignoredPresets": "Preset Ignorati",
"includeAllPresets": "Includi Tutti i Preset",
"selectedPresets": "Preset Selezionati",
"presets": "Preset",
"selectPreset": "Seleziona Preset",
"applyPreset": "Applica Preset",
"saveAsPreset": "Salva come Preset",
"updatePreset": "Aggiorna Preset",
"copyConfiguration": "Copia Configurazione",
"pasteConfiguration": "Incolla Configurazione",
"pasteConfigurationPlaceholder": "Incolla la configurazione JSON qui...",
"pasteFromClipboard": "Incolla dalla Clipboard",
"applyConfiguration": "Applica Configurazione",
"presetName": "Nome Preset",
"presetNamePlaceholder": "Inserisci il nome del preset",
"general": "Generale",
"mode": "Modalità",
"maxFPS": "Max FPS",
"opacity": "Opacità",
"customGradients": "Gradienti Personalizzati",
"gradientNamePlaceholder": "Nome Gradiente",
"vertical": "Verticale",
"horizontal": "Orizzontale",
"addColor": "Aggiungi Colore",
"position": "Posizione",
"level": "Livello",
"remove": "Rimuovi",
"pasteGradient": "Incolla Gradiente",
"custom": "Personalizzato",
"gradient": "Gradiente"
} }
} }
+327 -69
View File
@@ -7,7 +7,7 @@
"playRandom": "ランダム再生", "playRandom": "ランダム再生",
"skip": "スキップ", "skip": "スキップ",
"previous": "前へ", "previous": "前へ",
"toggleFullscreenPlayer": "フルスクリーンプレーヤー切り替え", "toggleFullscreenPlayer": "全画面プレーヤー切り替え",
"skip_back": "前へスキップ", "skip_back": "前へスキップ",
"favorite": "お気に入り", "favorite": "お気に入り",
"next": "次へ", "next": "次へ",
@@ -30,12 +30,25 @@
"skip_forward": "次へスキップ", "skip_forward": "次へスキップ",
"pause": "一時停止", "pause": "一時停止",
"playSimilarSongs": "似たような曲を再生する", "playSimilarSongs": "似たような曲を再生する",
"viewQueue": "キューを表示する", "viewQueue": "キューを表示",
"lyrics": "歌詞", "lyrics": "歌詞",
"restoreQueueFromServer": "サーバーからキューを復元", "restoreQueueFromServer": "サーバーからキューを復元",
"saveQueueToServer": "サーバーにキューを保存", "saveQueueToServer": "サーバーにキューを保存",
"addLastShuffled": "最後 (シャッフル)", "addLastShuffled": "最後 (シャッフル)",
"addNextShuffled": "次 (シャッフル)" "addNextShuffled": "次 (シャッフル)",
"sleepTimer_minutes": "{{count}} 分",
"sleepTimer_hours": "{{count}} 時間",
"sleepTimer": "スリープタイマー",
"sleepTimer_endOfSong": "現在の曲の終わり",
"sleepTimer_custom": "カスタム",
"sleepTimer_off": "オフ",
"sleepTimer_timeRemaining": "残り {{time}}",
"sleepTimer_setCustom": "タイマーを設定",
"sleepTimer_cancel": "タイマーをキャンセル",
"holdToShuffle": "長押しでシャッフル",
"albumRadio": "アルバム・ラジオ",
"artistRadio": "アーティストラジオ",
"trackRadio": "ラジオを追跡する"
}, },
"setting": { "setting": {
"crossfadeStyle_description": "オーディオプレーヤーが使用するクロスフェードのスタイルを選択します", "crossfadeStyle_description": "オーディオプレーヤーが使用するクロスフェードのスタイルを選択します",
@@ -43,11 +56,11 @@
"hotkey_skipBackward": "前にスキップ", "hotkey_skipBackward": "前にスキップ",
"replayGainMode_description": "ファイルのメタデータに保存されている {{ReplayGain}} 値に従って音量ゲインを調整します", "replayGainMode_description": "ファイルのメタデータに保存されている {{ReplayGain}} 値に従って音量ゲインを調整します",
"volumeWheelStep_description": "音量スライダーでマウスホイールをスクロールしたときに変化する音量を設定します", "volumeWheelStep_description": "音量スライダーでマウスホイールをスクロールしたときに変化する音量を設定します",
"audioDevice_description": "再生に使用するオーディオデバイスを選択します (Web プレーヤーのみ)", "audioDevice_description": "再生に使用するオーディオデバイスを選択します",
"theme_description": "アプリケーションに使用するテーマを設定します", "theme_description": "アプリケーションに使用するテーマを設定します",
"hotkey_playbackPause": "一時停止", "hotkey_playbackPause": "一時停止",
"replayGainFallback": "{{ReplayGain}} フォールバック", "replayGainFallback": "{{ReplayGain}} フォールバック",
"sidebarCollapsedNavigation_description": "折りたたサイドバーのナビゲーションを表示/非表示にします", "sidebarCollapsedNavigation_description": "折りたたまれたサイドバーのナビゲーションを表示または非表示にします",
"hotkey_volumeUp": "音量を上げる", "hotkey_volumeUp": "音量を上げる",
"skipDuration": "スキップの長さ", "skipDuration": "スキップの長さ",
"discordIdleStatus_description": "有効にすると、プレーヤーがアイドル状態でもステータスを更新します", "discordIdleStatus_description": "有効にすると、プレーヤーがアイドル状態でもステータスを更新します",
@@ -62,7 +75,7 @@
"mpvExecutablePath_description": "MPV を実行するファイルパスを設定します。空のままにすると、デフォルトのパスが使用されます", "mpvExecutablePath_description": "MPV を実行するファイルパスを設定します。空のままにすると、デフォルトのパスが使用されます",
"replayGainClipping_description": "自動的にゲインを下げて {{ReplayGain}} によるクリッピングを防ぎます", "replayGainClipping_description": "自動的にゲインを下げて {{ReplayGain}} によるクリッピングを防ぎます",
"replayGainPreamp": "{{ReplayGain}} プリアンプ (dB)", "replayGainPreamp": "{{ReplayGain}} プリアンプ (dB)",
"hotkey_favoriteCurrentSong": "$t(common.currentSong) をお気に入り", "hotkey_favoriteCurrentSong": "$t(common.currentSong) をお気に入りに登録",
"sampleRate": "サンプルレート", "sampleRate": "サンプルレート",
"sidePlayQueueStyle_optionAttached": "結合", "sidePlayQueueStyle_optionAttached": "結合",
"sidebarConfiguration": "サイドバー設定", "sidebarConfiguration": "サイドバー設定",
@@ -73,23 +86,23 @@
"scrobble_description": "再生した音楽をメディアサーバーから Scrobble します", "scrobble_description": "再生した音楽をメディアサーバーから Scrobble します",
"hotkey_browserForward": "ブラウザ 進む", "hotkey_browserForward": "ブラウザ 進む",
"audioExclusiveMode_description": "排他出力モードを有効にします。このモードでは、システムの他の出力がロックされ、MPV のみがオーディオを出力できるようになります", "audioExclusiveMode_description": "排他出力モードを有効にします。このモードでは、システムの他の出力がロックされ、MPV のみがオーディオを出力できるようになります",
"discordUpdateInterval": "{{discord}} Rich Presenceアップデート間隔", "discordUpdateInterval": "{{discord}} Rich Presence の更新間隔",
"themeLight": "テーマ (ライト)", "themeLight": "テーマ (ライト)",
"fontType_optionBuiltIn": "組み込みフォント", "fontType_optionBuiltIn": "組み込みフォント",
"hotkey_playbackPlayPause": "再生 / 一時停止", "hotkey_playbackPlayPause": "再生 / 一時停止",
"hotkey_rate1": "1つ星で評価", "hotkey_rate1": "1 つ星で評価",
"hotkey_skipForward": "次へスキップ", "hotkey_skipForward": "次へスキップ",
"disableLibraryUpdateOnStartup": "起動時の新バージョンチェックを無効にします", "disableLibraryUpdateOnStartup": "起動時の新バージョンチェックを無効にします",
"discordApplicationId_description": "{{discord}} に Rich Presence ステータスを表示するためのアプリケーション ID (デフォルトは {{defaultId}} です)", "discordApplicationId_description": "{{discord}} に Rich Presence ステータスを表示するためのアプリケーション ID (デフォルトは {{defaultId}} です)",
"sidePlayQueueStyle": "サイド再生キュースタイル", "sidePlayQueueStyle": "サイド再生キューの形式",
"gaplessAudio": "ギャップレス再生", "gaplessAudio": "ギャップレス再生",
"playButtonBehavior_optionAddLast": "$t(player.addLast)", "playButtonBehavior_optionAddLast": "$t(player.addLast)",
"zoom": "ズーム率", "zoom": "ズーム率",
"minimizeToTray_description": "最小化ボタンが押された際、システムトレイに格納します", "minimizeToTray_description": "最小化ボタンが押された際、システムトレイに格納します",
"hotkey_playbackPlay": "再生", "hotkey_playbackPlay": "再生",
"hotkey_togglePreviousSongFavorite": "$t(common.previousSong) お気に入り登録/解除", "hotkey_togglePreviousSongFavorite": "$t(common.previousSong) お気に入りを切り替え",
"hotkey_volumeDown": "音量を下げる", "hotkey_volumeDown": "音量を下げる",
"hotkey_unfavoritePreviousSong": "$t(common.previousSong) をお気に入り解除", "hotkey_unfavoritePreviousSong": "$t(common.previousSong) をお気に入りから解除",
"audioPlayer_description": "再生に使用するオーディオプレーヤーを選択します", "audioPlayer_description": "再生に使用するオーディオプレーヤーを選択します",
"globalMediaHotkeys": "グローバルメディアホットキー", "globalMediaHotkeys": "グローバルメディアホットキー",
"hotkey_globalSearch": "グローバル検索", "hotkey_globalSearch": "グローバル検索",
@@ -97,10 +110,10 @@
"remoteUsername_description": "リモートコントロール サーバーのユーザ名を設定します。 ユーザー名とパスワードの両方が空の場合、認証は無効になります", "remoteUsername_description": "リモートコントロール サーバーのユーザ名を設定します。 ユーザー名とパスワードの両方が空の場合、認証は無効になります",
"exitToTray_description": "アプリケーション終了ボタンが押された際、システムトレイに格納します", "exitToTray_description": "アプリケーション終了ボタンが押された際、システムトレイに格納します",
"followLyric_description": "現在の再生位置に歌詞をスクロールします", "followLyric_description": "現在の再生位置に歌詞をスクロールします",
"hotkey_favoritePreviousSong": "$t(common.previousSong) をお気に入り", "hotkey_favoritePreviousSong": "$t(common.previousSong) をお気に入りに登録",
"replayGainMode_optionAlbum": "$t(entity.album, {\"count\": 1})", "replayGainMode_optionAlbum": "$t(entity.album, {\"count\": 1})",
"lyricOffset": "歌詞のオフセット (ミリ秒)", "lyricOffset": "歌詞のオフセット (ミリ秒)",
"discordUpdateInterval_description": "更新間隔 (秒単位, 最小15秒)", "discordUpdateInterval_description": "更新間隔 (秒単位最小 15 秒)",
"fontType_optionCustom": "カスタムフォント", "fontType_optionCustom": "カスタムフォント",
"themeDark_description": "アプリケーションに使用するダークテーマを設定します", "themeDark_description": "アプリケーションに使用するダークテーマを設定します",
"audioExclusiveMode": "オーディオ排他モード", "audioExclusiveMode": "オーディオ排他モード",
@@ -108,16 +121,16 @@
"lyricFetchProvider": "歌詞取得先", "lyricFetchProvider": "歌詞取得先",
"language_description": "アプリケーションの言語を設定します ($t(common.restartRequired))", "language_description": "アプリケーションの言語を設定します ($t(common.restartRequired))",
"playbackStyle_optionCrossFade": "クロスフェード", "playbackStyle_optionCrossFade": "クロスフェード",
"hotkey_rate3": "3つ星で評価", "hotkey_rate3": "3 つ星で評価",
"font": "フォント", "font": "フォント",
"replayGainMode_optionTrack": "$t(entity.track, {\"count\": 1})", "replayGainMode_optionTrack": "$t(entity.track, {\"count\": 1})",
"themeLight_description": "アプリケーションに使用するライトテーマを設定します", "themeLight_description": "アプリケーションに使用するライトテーマを設定します",
"hotkey_toggleFullScreenPlayer": "フルスクリーンプレーヤー切り替え", "hotkey_toggleFullScreenPlayer": "全画面プレーヤー切り替え",
"hotkey_localSearch": "ページ内検索", "hotkey_localSearch": "ページ内検索",
"hotkey_toggleQueue": "キューの切り替え", "hotkey_toggleQueue": "キューの切り替え",
"zoom_description": "アプリケーションのズーム率を設定します", "zoom_description": "アプリケーションのズーム率を設定します",
"remotePassword_description": "リモートコントロール サーバーのパスワードを設定します。 ログイン情報はデフォルトでセキュアな通信がされないため、個人情報と関係ないランダムなパスワードを利用してください", "remotePassword_description": "リモートコントロール サーバーのパスワードを設定します。 ログイン情報はデフォルトでセキュアな通信がされないため、個人情報と関係ないランダムなパスワードを利用してください",
"hotkey_rate5": "5つ星で評価", "hotkey_rate5": "5 つ星で評価",
"hotkey_playbackPrevious": "前のトラック", "hotkey_playbackPrevious": "前のトラック",
"showSkipButtons_description": "プレーヤーバーのスキップボタンを表示または非表示にします", "showSkipButtons_description": "プレーヤーバーのスキップボタンを表示または非表示にします",
"crossfadeDuration_description": "クロスフェード効果の時間を設定します", "crossfadeDuration_description": "クロスフェード効果の時間を設定します",
@@ -128,11 +141,11 @@
"discordRichPresence_description": "{{discord}} Rich Presence で再生ステータスを有効にします。画像キー: {{icon}}, {{playing}}, {{paused}}", "discordRichPresence_description": "{{discord}} Rich Presence で再生ステータスを有効にします。画像キー: {{icon}}, {{playing}}, {{paused}}",
"mpvExecutablePath": "MPV 実行ファイルパス", "mpvExecutablePath": "MPV 実行ファイルパス",
"audioDevice": "オーディオデバイス", "audioDevice": "オーディオデバイス",
"hotkey_rate2": "2つ星で評価", "hotkey_rate2": "2 つ星で評価",
"playButtonBehavior_description": "キューに曲を追加するときの再生ボタンのデフォルトの動作を設定します", "playButtonBehavior_description": "キューに曲を追加するときの再生ボタンのデフォルトの動作を設定します",
"minimumScrobblePercentage_description": "Scrobble されるために必要な最短の再生時間 (%)", "minimumScrobblePercentage_description": "Scrobble されるために必要な最短の再生時間 (%)",
"exitToTray": "終了時にシステムトレイに格納", "exitToTray": "終了時にシステムトレイに格納",
"hotkey_rate4": "4つ星で評価", "hotkey_rate4": "4 つ星で評価",
"enableRemote": "リモートコントロール サーバーを有効化", "enableRemote": "リモートコントロール サーバーを有効化",
"showSkipButton_description": "プレーヤーバーのスキップボタンを表示または非表示にします", "showSkipButton_description": "プレーヤーバーのスキップボタンを表示または非表示にします",
"savePlayQueue": "再生キューを保存", "savePlayQueue": "再生キューを保存",
@@ -141,9 +154,9 @@
"fontType_description": "組み込みフォントの場合、Feishin が提供するフォントの中から 1 つ選択します。 システムフォントの場合、OS が提供する任意のフォントを選択できます。 カスタムフォントの場合、フォントファイルを自身で選択できます", "fontType_description": "組み込みフォントの場合、Feishin が提供するフォントの中から 1 つ選択します。 システムフォントの場合、OS が提供する任意のフォントを選択できます。 カスタムフォントの場合、フォントファイルを自身で選択できます",
"playButtonBehavior": "再生ボタンの動作", "playButtonBehavior": "再生ボタンの動作",
"volumeWheelStep": "音量ホイールステップ", "volumeWheelStep": "音量ホイールステップ",
"sidebarPlaylistList_description": "サイドバープレイリストのリストを表示/非表示にします", "sidebarPlaylistList_description": "サイドバープレイリストを表示または非表示にします",
"accentColor": "アクセントカラー", "accentColor": "アクセントカラー",
"sidePlayQueueStyle_description": "サイド再生キューのスタイルを設定します", "sidePlayQueueStyle_description": "サイド再生キューの形式を設定します",
"accentColor_description": "アプリケーションが利用するアクセントカラーを設定します", "accentColor_description": "アプリケーションが利用するアクセントカラーを設定します",
"replayGainMode": "{{ReplayGain}} モード", "replayGainMode": "{{ReplayGain}} モード",
"playbackStyle_optionNormal": "通常", "playbackStyle_optionNormal": "通常",
@@ -152,7 +165,7 @@
"replayGainPreamp_description": "{{ReplayGain}} の値に適用されるプリアンプゲインを調整します", "replayGainPreamp_description": "{{ReplayGain}} の値に適用されるプリアンプゲインを調整します",
"hotkey_toggleRepeat": "リピートの切り替え", "hotkey_toggleRepeat": "リピートの切り替え",
"lyricOffset_description": "歌詞のオフセットをミリ秒単位で指定します", "lyricOffset_description": "歌詞のオフセットをミリ秒単位で指定します",
"sidebarConfiguration_description": "サイドバーに表示されるアイテムと並び順を選択します", "sidebarConfiguration_description": "サイドバーに表示する項目と順序を選択します",
"fontType": "フォントタイプ", "fontType": "フォントタイプ",
"remotePort": "リモートコントロールサーバーのポート", "remotePort": "リモートコントロールサーバーのポート",
"applicationHotkeys": "アプリケーションホットキー", "applicationHotkeys": "アプリケーションホットキー",
@@ -169,16 +182,16 @@
"sidePlayQueueStyle_optionDetached": "分離", "sidePlayQueueStyle_optionDetached": "分離",
"audioPlayer": "オーディオプレーヤー", "audioPlayer": "オーディオプレーヤー",
"hotkey_zoomOut": "縮小", "hotkey_zoomOut": "縮小",
"hotkey_unfavoriteCurrentSong": "$t(common.currentSong) をお気に入り解除", "hotkey_unfavoriteCurrentSong": "$t(common.currentSong) をお気に入りから解除",
"hotkey_rate0": "評価をクリア", "hotkey_rate0": "評価をクリア",
"discordApplicationId": "{{discord}} アプリケーション ID", "discordApplicationId": "{{discord}} アプリケーション ID",
"applicationHotkeys_description": "アプリケーションのホットキーを設定します。チェックボックスを切り替えて、グローバルホットキーとして設定します (デスクトップのみ)", "applicationHotkeys_description": "アプリケーションのホットキーを設定します。チェックボックスを切り替えて、グローバルホットキーとして設定します (デスクトップのみ)",
"hotkey_volumeMute": "音量をミュート", "hotkey_volumeMute": "音量をミュート",
"hotkey_toggleCurrentSongFavorite": "$t(common.currentSong) お気に入り登録/解除", "hotkey_toggleCurrentSongFavorite": "$t(common.currentSong) お気に入りを切り替え",
"remoteUsername": "リモートコントロールサーバーのユーザー名", "remoteUsername": "リモートコントロールサーバーのユーザー名",
"hotkey_browserBack": "ブラウザ 戻る", "hotkey_browserBack": "ブラウザ 戻る",
"showSkipButton": "スキップボタンを表示", "showSkipButton": "スキップボタンを表示",
"sidebarPlaylistList": "サイドバー プレイリスト リスト", "sidebarPlaylistList": "サイドバープレイリスト",
"minimizeToTray": "最小化時にシステムトレイに格納", "minimizeToTray": "最小化時にシステムトレイに格納",
"skipPlaylistPage": "プレイリストページをスキップ", "skipPlaylistPage": "プレイリストページをスキップ",
"themeDark": "テーマ (ダーク)", "themeDark": "テーマ (ダーク)",
@@ -206,10 +219,10 @@
"trayEnabled": "トレイを表示する", "trayEnabled": "トレイを表示する",
"volumeWidth_description": "音量スライダーの幅", "volumeWidth_description": "音量スライダーの幅",
"volumeWidth": "音量スライダーの幅", "volumeWidth": "音量スライダーの幅",
"webAudio_description": "Web Audio を使用します。これにより、リプレイゲインなどの高度な機能が有効になります。それ以外の場合は無効にしてください", "webAudio_description": "Web Audio を使用します。これにより、リプレイゲインなどの高度な機能が有効になります。問題が発生した場合は無効にしてください",
"mpvExtraParameters_help": "1 行に 1 つずつ", "mpvExtraParameters_help": "1 行に 1 つずつ",
"musicbrainz_description": "MusicBrainz ID が存在するアーティスト/アルバムページに MusicBrainz へのリンクを表示します", "musicbrainz_description": "MusicBrainz ID が存在するアーティストアルバムページに MusicBrainz へのリンクを表示します",
"musicbrainz": "MusicBrainz リンクを表示する", "musicbrainz": "MusicBrainz リンクを表示",
"neteaseTranslation_description": "有効にすると、利用可能な場合は NetEase から翻訳された歌詞を取得して表示します", "neteaseTranslation_description": "有効にすると、利用可能な場合は NetEase から翻訳された歌詞を取得して表示します",
"neteaseTranslation": "NetEase 翻訳歌詞を有効にする", "neteaseTranslation": "NetEase 翻訳歌詞を有効にする",
"passwordStore_description": "使用するパスワード / シークレットストア。パスワードの保存に問題がある場合はこれを変更してください", "passwordStore_description": "使用するパスワード / シークレットストア。パスワードの保存に問題がある場合はこれを変更してください",
@@ -225,8 +238,8 @@
"imageAspectRatio": "ネイティブのカバーアートの縦横比を使用する", "imageAspectRatio": "ネイティブのカバーアートの縦横比を使用する",
"language": "言語", "language": "言語",
"imageAspectRatio_description": "有効にすると、カバーアートはネイティブの縦横比で表示されます。縦横比が 1:1 でない場合、残りのスペースは空白になります", "imageAspectRatio_description": "有効にすると、カバーアートはネイティブの縦横比で表示されます。縦横比が 1:1 でない場合、残りのスペースは空白になります",
"lastfm_description": "アーティスト/アルバムページに Last.fm へのリンクを表示します", "lastfm_description": "アーティストアルバムページに Last.fm へのリンクを表示します",
"lastfm": "Last.fm リンクを表示する", "lastfm": "Last.fm リンクを表示",
"lastfmApiKey": "{{lastfm}} API キー", "lastfmApiKey": "{{lastfm}} API キー",
"homeConfiguration_description": "ホーム画面に表示する項目と表示順序を設定します", "homeConfiguration_description": "ホーム画面に表示する項目と表示順序を設定します",
"homeConfiguration": "ホーム画面の設定", "homeConfiguration": "ホーム画面の設定",
@@ -246,8 +259,8 @@
"artistConfiguration_description": "アルバムアーティストページに表示するアイテムと順序を設定します", "artistConfiguration_description": "アルバムアーティストページに表示するアイテムと順序を設定します",
"buttonSize_description": "プレーヤーバーのボタンのサイズ", "buttonSize_description": "プレーヤーバーのボタンのサイズ",
"buttonSize": "プレーヤーバーのボタンサイズ", "buttonSize": "プレーヤーバーのボタンサイズ",
"clearCache_description": "Feishin の「ハードクリア」。Feishin のキャッシュをクリアするだけでなく、ブラウザのキャッシュ (保存された画像やその他のアセット) も空にします。サーバーの資格情報や設定は保持されます", "clearCache_description": "Feishin の「ハードクリア」。Feishin のキャッシュをクリアするだけでなく、ブラウザのキャッシュ (保存された画像やその他のアセット) も空にします。サーバーの資格情報や設定は保持されます",
"clearCache": "ブラウザのキャッシュをクリアする", "clearCache": "ブラウザのキャッシュをクリア",
"clearCacheSuccess": "キャッシュが正常にクリアされました", "clearCacheSuccess": "キャッシュが正常にクリアされました",
"clearQueryCache_description": "Feishin の「ソフトクリア」。これにより、プレイリストとトラックのメタデータが更新され、保存された歌詞がリセットされます。設定、サーバーの資格情報、キャッシュされた画像は保持されます", "clearQueryCache_description": "Feishin の「ソフトクリア」。これにより、プレイリストとトラックのメタデータが更新され、保存された歌詞がリセットされます。設定、サーバーの資格情報、キャッシュされた画像は保持されます",
"clearQueryCache": "Feishin のキャッシュをクリアする", "clearQueryCache": "Feishin のキャッシュをクリアする",
@@ -262,11 +275,11 @@
"releaseChannel_optionBeta": "ベータ", "releaseChannel_optionBeta": "ベータ",
"releaseChannel_optionLatest": "最新", "releaseChannel_optionLatest": "最新",
"releaseChannel": "リリースチャンネル", "releaseChannel": "リリースチャンネル",
"releaseChannel_description": "自動更新のために安定版リリースまたはベータ版リリース選択してください", "releaseChannel_description": "自動更新のために安定版、ベータ版、またはアルファ版 (nightly build) リリースから選択してください",
"discordDisplayType_artistname": "アーティスト名", "discordDisplayType_artistname": "アーティスト名",
"discordDisplayType_songname": "曲名", "discordDisplayType_songname": "曲名",
"discordLinkType_description": "{{discord}} Rich Presence において、曲とアーティストのフィールドに {{lastfm}} または {{musicbrainz}} への外部リンクを追加します。{{musicbrainz}} は最も正確ですが、タグが必要でアーティストリンクを提供しません。一方、{{lastfm}} は常にリンクを提供します。追加のネットワークリクエストは発生しません", "discordLinkType_description": "{{discord}} Rich Presence において、曲とアーティストのフィールドに {{lastfm}} または {{musicbrainz}} への外部リンクを追加します。{{musicbrainz}} は最も正確ですが、タグが必要でアーティストリンクを提供しません。一方、{{lastfm}} は常にリンクを提供します。追加のネットワークリクエストは発生しません",
"discordPausedStatus": "一時停止時に Rich Presence を表示する", "discordPausedStatus": "一時停止時に Rich Presence を表示",
"discordRichPresence": "{{discord}} Rich Presence", "discordRichPresence": "{{discord}} Rich Presence",
"discordServeImage_description": "{{discord}} Rich Presence 用のカバーアートをサーバーから共有します。Jellyfin と Navidrome でのみ利用できます。{{discord}} は bot を使用して画像を取得するため、サーバーはパブリックインターネットからアクセスできる必要があります", "discordServeImage_description": "{{discord}} Rich Presence 用のカバーアートをサーバーから共有します。Jellyfin と Navidrome でのみ利用できます。{{discord}} は bot を使用して画像を取得するため、サーバーはパブリックインターネットからアクセスできる必要があります",
"exportImportSettings_control_exportText": "設定をエクスポート", "exportImportSettings_control_exportText": "設定をエクスポート",
@@ -274,7 +287,7 @@
"exportImportSettings_control_title": "設定をインポート/エクスポート", "exportImportSettings_control_title": "設定をインポート/エクスポート",
"exportImportSettings_control_description": "JSON 経由で設定をエクスポートおよびインポートする", "exportImportSettings_control_description": "JSON 経由で設定をエクスポートおよびインポートする",
"exportImportSettings_destructiveWarning": "設定のインポートは破壊的です。下の「インポート」をクリックする前に、上記の内容を必ずご確認ください!", "exportImportSettings_destructiveWarning": "設定のインポートは破壊的です。下の「インポート」をクリックする前に、上記の内容を必ずご確認ください!",
"hotkey_navigateHome": "ホーム移動", "hotkey_navigateHome": "ホーム画面へ移動",
"playButtonBehavior_optionPlayShuffled": "$t(player.shuffle)", "playButtonBehavior_optionPlayShuffled": "$t(player.shuffle)",
"playerbarOpenDrawer": "プレーヤーバーの全画面表示切り替え", "playerbarOpenDrawer": "プレーヤーバーの全画面表示切り替え",
"transcode": "トランスコーディングを有効にする", "transcode": "トランスコーディングを有効にする",
@@ -290,7 +303,7 @@
"discordDisplayType": "{{discord}} Presence 表示タイプ", "discordDisplayType": "{{discord}} Presence 表示タイプ",
"discordLinkType_none": "$t(common.none)", "discordLinkType_none": "$t(common.none)",
"discordListening_description": "Playing ではなく Listening としてステータスを表示します", "discordListening_description": "Playing ではなく Listening としてステータスを表示します",
"discordListening": "ステータスを Listening として表示する", "discordListening": "ステータスを Listening として表示",
"discordPausedStatus_description": "有効にすると、プレーヤーが一時停止されているときにもステータスを表示します", "discordPausedStatus_description": "有効にすると、プレーヤーが一時停止されているときにもステータスを表示します",
"discordDisplayType_description": "ステータスで聴いている内容を変更します", "discordDisplayType_description": "ステータスで聴いている内容を変更します",
"discordLinkType": "{{discord}} Presence リンク", "discordLinkType": "{{discord}} Presence リンク",
@@ -316,11 +329,11 @@
"followCurrentSong": "現在の曲をフォロー", "followCurrentSong": "現在の曲をフォロー",
"followCurrentSong_description": "再生キューを現在再生中の曲まで自動的にスクロールします", "followCurrentSong_description": "再生キューを現在再生中の曲まで自動的にスクロールします",
"logLevel": "ログレベル", "logLevel": "ログレベル",
"logLevel_description": "表示するログの最小レベルを設定します。debug はすべてのログを表示し、error はエラーのみを表示します", "logLevel_description": "表示するログの最小レベルを設定します。Debug はすべてのログを表示し、Error はエラーのみを表示します",
"logLevel_optionDebug": "debug", "logLevel_optionDebug": "Debug",
"logLevel_optionError": "error", "logLevel_optionError": "Error",
"logLevel_optionInfo": "info", "logLevel_optionInfo": "Info",
"logLevel_optionWarn": "warn", "logLevel_optionWarn": "Warn",
"playerFilters": "キューから曲をフィルタリング", "playerFilters": "キューから曲をフィルタリング",
"playerFilters_description": "以下の基準に基づいて曲をキューに追加しないようにします", "playerFilters_description": "以下の基準に基づいて曲をキューに追加しないようにします",
"artistRadioCount": "アーティスト / トラックのラジオカウント", "artistRadioCount": "アーティスト / トラックのラジオカウント",
@@ -328,7 +341,7 @@
"imageResolution": "画像の解像度", "imageResolution": "画像の解像度",
"imageResolution_description": "アプリ内で使用される画像の解像度。値を 0 に設定すると、デフォルトでネイティブ画像解像度が適用されます", "imageResolution_description": "アプリ内で使用される画像の解像度。値を 0 に設定すると、デフォルトでネイティブ画像解像度が適用されます",
"showLyricsInSidebar_description": "添付の再生キューに歌詞を表示するパネルが追加されます", "showLyricsInSidebar_description": "添付の再生キューに歌詞を表示するパネルが追加されます",
"showLyricsInSidebar": "プレーヤーのサイドバーに歌詞を表示する", "showLyricsInSidebar": "サイドバーのプレーヤーに歌詞を表示",
"showRatings": "星評価を表示する", "showRatings": "星評価を表示する",
"imageResolution_optionSidebar": "サイドバー", "imageResolution_optionSidebar": "サイドバー",
"imageResolution_optionHeader": "ヘッダー", "imageResolution_optionHeader": "ヘッダー",
@@ -339,12 +352,12 @@
"playerbarSliderType_optionWaveform": "波形", "playerbarSliderType_optionWaveform": "波形",
"playerbarWaveformAlign": "波形アライメント", "playerbarWaveformAlign": "波形アライメント",
"showRatings_description": "インターフェースに星評価機能を表示するかどうかを制御します", "showRatings_description": "インターフェースに星評価機能を表示するかどうかを制御します",
"showVisualizerInSidebar": "プレーヤーのサイドバーにビジュアライザーを表示する", "showVisualizerInSidebar": "サイドバーのプレーヤーにビジュアライザーを表示",
"combinedLyricsAndVisualizer": "プレーヤーのサイドバーに歌詞とビジュアライザーを統合する", "combinedLyricsAndVisualizer": "サイドバーのプレーヤーに歌詞とビジュアライザーを統合",
"audioFadeOnStatusChange_description": "再生 / 一時停止の状態が変わったときにフェードアウトとフェードインを有効にします", "audioFadeOnStatusChange_description": "再生 / 一時停止の状態が変わったときにフェードアウトとフェードインを有効にします",
"audioFadeOnStatusChange": "ステータス変更時の音声フェード", "audioFadeOnStatusChange": "ステータス変更時の音声フェード",
"combinedLyricsAndVisualizer_description": "歌詞とビジュアライザーを同じパネルに統合します", "combinedLyricsAndVisualizer_description": "歌詞とビジュアライザーを同じパネルに統合します",
"showVisualizerInSidebar_description": "プレーヤーのサイドバーにビジュアライザーを表示するパネルが追加されます", "showVisualizerInSidebar_description": "サイドバーのプレーヤーにビジュアライザーを表示するパネルが追加されます",
"queryBuilderCustomFields": "カスタムフィールド", "queryBuilderCustomFields": "カスタムフィールド",
"queryBuilderCustomFields_inputLabel": "ラベル", "queryBuilderCustomFields_inputLabel": "ラベル",
"queryBuilderCustomFields_inputTag": "タグ", "queryBuilderCustomFields_inputTag": "タグ",
@@ -359,7 +372,60 @@
"pathReplace": "ファイルパスの置換", "pathReplace": "ファイルパスの置換",
"pathReplace_description": "サーバーのデフォルトのファイルパスを置き換えます", "pathReplace_description": "サーバーのデフォルトのファイルパスを置き換えます",
"pathReplace_optionRemovePrefix": "接頭辞を削除", "pathReplace_optionRemovePrefix": "接頭辞を削除",
"pathReplace_optionAddPrefix": "接頭辞を追加" "pathReplace_optionAddPrefix": "接頭辞を追加",
"analyticsEnable": "使用状況に基づく分析を送信する",
"analyticsEnable_description": "匿名化された利用データは、アプリケーションの改善のために開発者に送信されます",
"automaticUpdates": "自動更新",
"automaticUpdates_description": "更新を自動的に確認してインストールします",
"releaseChannel_optionAlpha": "アルファ (nightly)",
"discordStateIcon": "再生中アイコンを表示",
"discordStateIcon_description": "Rich Presence ステータスに小さな再生アイコンを表示します。「一時停止時に Rich Presence を表示」が有効になっている場合は、常に一時停止アイコンが表示されます",
"sidebarPlaylistListFilterRegex_description": "この正規表現に一致するプレイリストをサイドバーから非表示にします",
"sidebarPlaylistListFilterRegex_placeholder": "例: ^Daily Mix.*",
"sidebarPlaylistListFilterRegex": "プレイリストフィルターの正規表現",
"sidebarPlaylistSorting": "サイドバーでプレイリストを並べ替え",
"sidebarPlaylistSorting_description": "デフォルトのサーバー順ではなく、ドラッグアンドドロップを使用してサイドバーでプレイリストを手動で並べ替えることができます",
"playerItemConfiguration_description": "全画面プレーヤーに表示する項目と順序を設定します",
"playerItemConfiguration": "プレーヤーの項目設定",
"autosave": "再生キューを自動的に保存",
"autosave_description": "再生キューをサーバーに自動的に保存できるようにします。これは Navidrome/Subsonic を使用している場合にのみ可能であり、再生キューを混在させることはできません。",
"autosaveCount": "自動再生キューの保存頻度",
"autosaveCount_description": "キューが保存されるまでにトラックが変更される回数を設定します。1 (最小値) は曲が変わるたびに保存されることを意味します",
"useThemePrimaryShade_description": "選択したテーマで定義されたプライマリシェードをプライマリカラーのバリアントに使用します",
"useThemePrimaryShade": "テーマのプライマリシェードを使用",
"primaryShade": "プライマリシェード",
"primaryShade_description": "ボタン、リンク、およびその他の主要色要素に使用されるプライマリシェード (0–9) を上書きします",
"playerbarWaveformAlign_optionTop": "上部",
"playerbarWaveformAlign_optionCenter": "中央",
"playerbarWaveformAlign_optionBottom": "下部",
"imageResolution_optionTable": "表",
"imageResolution_optionItemCard": "アイテムカード",
"blurExplicitImages": "露骨な画像をぼかす",
"blurExplicitImages_description": "露骨な表現を含むタグが付けられたアルバムおよび楽曲のアートワークをぼかします",
"enableGridMultiSelect": "グリッドの複数選択を有効にする",
"enableGridMultiSelect_description": "有効にすると、グリッドビューで複数のアイテムを選択できます。無効にすると、グリッドアイテムの画像をクリックするとアイテムページに移動します",
"playerbarWaveformBarWidth": "波形バーの幅",
"playerbarWaveformGap": "波形ギャップ",
"playerbarWaveformRadius": "波形半径",
"hotkey_listNavigateToPage": "項目の詳細ページへ移動",
"hotkey_listPlayDefault": "リストを再生 (デフォルト)",
"hotkey_listPlayLast": "最後に再生",
"hotkey_listPlayNext": "次に再生",
"hotkey_listPlayNow": "今すぐ再生",
"spotify_description": "アーティストとアルバムページに Spotify へのリンクを表示します",
"spotify": "Spotify のリンクを表示",
"nativeSpotify_description": "ブラウザーの代わりに Spotify アプリで開きます",
"nativeSpotify": "Spotify アプリを使用",
"listenbrainz_description": "アーティストとアルバムページに ListenBrainz へのリンクを表示します",
"listenbrainz": "ListenBrainz のリンクを表示",
"qobuz_description": "アーティストとアルバムページに Qobuz へのリンクを表示します",
"qobuz": "Qobuz のリンクを表示",
"sidePlayQueueLayout": "サイド再生キューのレイアウト",
"sidePlayQueueLayout_description": "結合されたサイド再生キューのレイアウトを設定します",
"sidePlayQueueLayout_optionHorizontal": "水平",
"sidePlayQueueLayout_optionVertical": "垂直",
"waveformLoadingDelay": "波形読み込みの遅延",
"waveformLoadingDelay_description": "波形を読み込むまでの遅延時間(秒単位)を設定します。Web プレーヤー使用時にカクつきが発生する場合は、この値を増やしてください。"
}, },
"action": { "action": {
"editPlaylist": "$t(entity.playlist, {\"count\": 1}) を編集", "editPlaylist": "$t(entity.playlist, {\"count\": 1}) を編集",
@@ -381,7 +447,10 @@
"removeFromFavorites": "$t(entity.favorite, {\"count\": 2}) から削除", "removeFromFavorites": "$t(entity.favorite, {\"count\": 2}) から削除",
"openIn": { "openIn": {
"lastfm": "Last.fm で開く", "lastfm": "Last.fm で開く",
"musicbrainz": "MusicBrainz で開く" "musicbrainz": "MusicBrainz で開く",
"spotify": "Spotify で開く",
"listenbrainz": "ListenBrainz で開く",
"qobuz": "Qobuz で開く"
}, },
"moveToNext": "次", "moveToNext": "次",
"downloadStarted": "{{count}} 曲のダウンロードを開始しました", "downloadStarted": "{{count}} 曲のダウンロードを開始しました",
@@ -399,7 +468,8 @@
"holdToMoveToBottom": "押し続けると一番下に移動します", "holdToMoveToBottom": "押し続けると一番下に移動します",
"openApplicationDirectory": "アプリケーションディレクトリを開く", "openApplicationDirectory": "アプリケーションディレクトリを開く",
"selectRangeOfItems": "項目の範囲を選択", "selectRangeOfItems": "項目の範囲を選択",
"addOrRemoveFromSelection": "選択に追加または削除" "addOrRemoveFromSelection": "選択に追加または削除",
"goToCurrent": "現在の項目へ移動"
}, },
"common": { "common": {
"backward": "戻る", "backward": "戻る",
@@ -447,8 +517,8 @@
"setting_other": "設定", "setting_other": "設定",
"version": "バージョン", "version": "バージョン",
"title": "タイトル", "title": "タイトル",
"filter_other": "フィルタ", "filter_other": "フィルタ",
"filters": "フィルタ", "filters": "フィルタ",
"create": "作成", "create": "作成",
"bitrate": "ビットレート", "bitrate": "ビットレート",
"saveAndReplace": "保存して変更", "saveAndReplace": "保存して変更",
@@ -517,19 +587,23 @@
"clean": "クリーン", "clean": "クリーン",
"filter_single": "シングル", "filter_single": "シングル",
"filter_multiple": "複数枚組", "filter_multiple": "複数枚組",
"rename": "名前を変更" "rename": "名前を変更",
"newVersionAvailable": "新しいバージョンが利用可能です",
"numberOfResults": "{{numberOfResults}} 件の結果",
"grouping": "グループ化"
}, },
"table": { "table": {
"config": { "config": {
"view": { "view": {
"table": "テーブル", "table": "",
"grid": "グリッド", "grid": "グリッド",
"list": "リスト" "list": "リスト",
"detail": "詳細"
}, },
"general": { "general": {
"displayType": "表示タイプ", "displayType": "表示タイプ",
"gap": "$t(common.gap)", "gap": "$t(common.gap)",
"tableColumns": "テーブル カラム", "tableColumns": "テーブル",
"autoFitColumns": "カラム長を自動調整", "autoFitColumns": "カラム長を自動調整",
"size": "$t(common.size)", "size": "$t(common.size)",
"itemSize": "項目のサイズ (px)", "itemSize": "項目のサイズ (px)",
@@ -549,7 +623,14 @@
"size_compact": "コンパクト", "size_compact": "コンパクト",
"size_large": "大きい", "size_large": "大きい",
"pagination_itemsPerPage": "ページあたりの項目数", "pagination_itemsPerPage": "ページあたりの項目数",
"pagination_infinite": "無限" "pagination_infinite": "無限",
"pagination": "ページネーション",
"pagination_paginate": "ページ分割",
"showHeader": "ヘッダーを表示",
"verticalBorders": "列の境界線",
"rowHoverHighlight": "行ホバーハイライト",
"alternateRowColors": "交互の行の色",
"horizontalBorders": "行の境界線"
}, },
"label": { "label": {
"releaseDate": "発売日", "releaseDate": "発売日",
@@ -586,7 +667,8 @@
"image": "画像", "image": "画像",
"sampleRate": "$t(common.sampleRate)", "sampleRate": "$t(common.sampleRate)",
"composer": "作曲家", "composer": "作曲家",
"titleArtist": "$t(common.title) (アーティスト)" "titleArtist": "$t(common.title) (アーティスト)",
"albumGroup": "アルバムグループ"
} }
}, },
"column": { "column": {
@@ -648,7 +730,10 @@
"noNetwork": "サーバーが利用できません", "noNetwork": "サーバーが利用できません",
"noNetworkDescription": "このサーバーに接続できませんでした", "noNetworkDescription": "このサーバーに接続できませんでした",
"saveQueueFailed": "キューを保存できませんでした", "saveQueueFailed": "キューを保存できませんでした",
"settingsSyncError": "レンダラーとメインプロセスの設定に矛盾が見つかりました。変更を適用するにはアプリケーションを再起動してください" "settingsSyncError": "レンダラーとメインプロセスの設定に矛盾が見つかりました。変更を適用するにはアプリケーションを再起動してください",
"invalidJson": "無効な JSON",
"serverLockSingleServer": "サーバーがロックされている場合、1 つのサーバーのみが許可されます",
"playbackPausedDueToError": "エラーのため再生が一時停止されました"
}, },
"filter": { "filter": {
"mostPlayed": "最も多く再生", "mostPlayed": "最も多く再生",
@@ -694,7 +779,9 @@
"id": "ID", "id": "ID",
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
"explicitStatus": "$t(common.explicitStatus)", "explicitStatus": "$t(common.explicitStatus)",
"sortName": "ソート名" "sortName": "ソート名",
"matchAnd": "すべて",
"matchOr": "いずれか"
}, },
"page": { "page": {
"sidebar": { "sidebar": {
@@ -745,7 +832,7 @@
"manageServers": "サーバーの管理", "manageServers": "サーバーの管理",
"expandSidebar": "サイドバーを展開", "expandSidebar": "サイドバーを展開",
"collapseSidebar": "サイドバーを折りたたむ", "collapseSidebar": "サイドバーを折りたたむ",
"openBrowserDevtools": "ブラウザの開発者ツールを開く", "openBrowserDevtools": "ブラウザの開発者ツールを開く",
"quit": "$t(common.quit)", "quit": "$t(common.quit)",
"goBack": "戻る", "goBack": "戻る",
"goForward": "進む", "goForward": "進む",
@@ -858,12 +945,16 @@
"recentReleases": "最近のリリース", "recentReleases": "最近のリリース",
"viewDiscography": "ディスコグラフィーを見る", "viewDiscography": "ディスコグラフィーを見る",
"topSongs": "人気曲", "topSongs": "人気曲",
"topSongsFrom": "{{title}} からの人気曲", "topSongsFrom": "{{title}} の人気曲",
"viewAll": "すべて表示", "viewAll": "すべて表示",
"viewAllTracks": "$t(entity.track, {\"count\": 2}) をすべて表示", "viewAllTracks": "$t(entity.track, {\"count\": 2}) をすべて表示",
"relatedArtists": "関連の $t(entity.artist, {\"count\": 2})", "relatedArtists": "関連の $t(entity.artist, {\"count\": 2})",
"groupingTypeAll": "すべてのリリースタイプ", "groupingTypeAll": "すべてのリリースタイプ",
"groupingTypePrimary": "主なリリースタイプ" "groupingTypePrimary": "主なリリースタイプ",
"favoriteSongs": "お気に入りの曲",
"topSongsCommunity": "コミュニティ",
"favoriteSongsFrom": "{{title}} のお気に入りの曲",
"topSongsPersonal": "個人的"
}, },
"manageServers": { "manageServers": {
"title": "サーバーの管理", "title": "サーバーの管理",
@@ -897,6 +988,11 @@
"collections": { "collections": {
"overrideExisting": "既存のものを上書き", "overrideExisting": "既存のものを上書き",
"saveAsCollection": "コレクションとして保存" "saveAsCollection": "コレクションとして保存"
},
"releasenotes": {
"commitsSinceStable": "{{stable}} 以降のコミット",
"noNewCommits": "この範囲に新しいコミットはありません",
"noStableReleaseToCompare": "比較可能な安定版リリースはありません"
} }
}, },
"form": { "form": {
@@ -941,7 +1037,7 @@
}, },
"updateServer": { "updateServer": {
"title": "サーバーをアップデート", "title": "サーバーをアップデート",
"success": "サーバーがアップデートされました" "success": "サーバーの更新に成功しました"
}, },
"queryEditor": { "queryEditor": {
"input_optionMatchAll": "すべて一致", "input_optionMatchAll": "すべて一致",
@@ -960,8 +1056,7 @@
"editPlaylist": { "editPlaylist": {
"title": "$t(entity.playlist, {\"count\": 1}) を編集", "title": "$t(entity.playlist, {\"count\": 1}) を編集",
"publicJellyfinNote": "Jellyfin では、何らかの理由でプレイリストが公開されているかどうかが表示されません。公開されたままにしたい場合は、以下の項目を選択してください", "publicJellyfinNote": "Jellyfin では、何らかの理由でプレイリストが公開されているかどうかが表示されません。公開されたままにしたい場合は、以下の項目を選択してください",
"success": "$t(entity.playlist, {\"count\": 1}) が正常に更新されました", "success": "$t(entity.playlist, {\"count\": 1}) が正常に更新されました"
"editNote": "大規模なプレイリストの場合、手動編集は推奨されません。既存のプレイリストを上書きすることでデータ損失が発生するリスクを許容しますか?"
}, },
"shareItem": { "shareItem": {
"allowDownloading": "ダウンロードを許可", "allowDownloading": "ダウンロードを許可",
@@ -969,7 +1064,9 @@
"setExpiration": "有効期限を設定", "setExpiration": "有効期限を設定",
"success": "共有リンクがクリップボードにコピーされました (またはここをクリックして開きます)", "success": "共有リンクがクリップボードにコピーされました (またはここをクリックして開きます)",
"expireInvalid": "有効期限は将来の日時である必要があります", "expireInvalid": "有効期限は将来の日時である必要があります",
"createFailed": "共有リンクを作成できませんでした (共有は有効になっていますか?)" "createFailed": "共有リンクを作成できませんでした (共有は有効になっていますか?)",
"copyToClipboard": "クリップボードにコピー: Ctrl+C、Enter",
"successMustClick": "共有リンクが正常に作成されました。開くにはここをクリックしてください"
}, },
"privateMode": { "privateMode": {
"enabled": "プライベートモードが有効になりました。再生ステータスは外部連携から非表示になっています", "enabled": "プライベートモードが有効になりました。再生ステータスは外部連携から非表示になっています",
@@ -985,7 +1082,7 @@
"title": "ラジオ局を作成", "title": "ラジオ局を作成",
"input_homepageUrl": "ホームページ URL", "input_homepageUrl": "ホームページ URL",
"input_name": "名前", "input_name": "名前",
"input_streamUrl": "Stream URL" "input_streamUrl": "ストリーム URL"
}, },
"lyricsExport": { "lyricsExport": {
"export": "歌詞をエクスポート", "export": "歌詞をエクスポート",
@@ -995,7 +1092,7 @@
"shuffleAll": { "shuffleAll": {
"title": "ランダムに再生", "title": "ランダムに再生",
"input_genre": "$t(entity.genre, {\"count\": 1})", "input_genre": "$t(entity.genre, {\"count\": 1})",
"input_limit": "曲が多すぎます", "input_limit": "何曲?",
"input_minYear": "年から", "input_minYear": "年から",
"input_maxYear": "年まで", "input_maxYear": "年まで",
"input_played_optionAll": "すべてのトラック", "input_played_optionAll": "すべてのトラック",
@@ -1005,6 +1102,9 @@
}, },
"saveQueue": { "saveQueue": {
"success": "プレイキューをサーバーに保存しました" "success": "プレイキューをサーバーに保存しました"
},
"editRadioStation": {
"success": "ラジオ局の更新に成功しました"
} }
}, },
"entity": { "entity": {
@@ -1046,9 +1146,15 @@
"audiobook": "オーディオブック", "audiobook": "オーディオブック",
"audioDrama": "オーディオドラマ", "audioDrama": "オーディオドラマ",
"compilation": "コンピレーション", "compilation": "コンピレーション",
"djMix": "DJ Mix", "djMix": "DJ ミックス",
"demo": "デモ", "demo": "デモ",
"soundtrack": "サウンドトラック" "soundtrack": "サウンドトラック",
"fieldRecording": "フィールドレコーディング",
"interview": "インタビュー",
"live": "ライブ",
"mixtape": "ミックステープ",
"remix": "リミックス",
"spokenWord": "スポークン・ワード"
} }
}, },
"datetime": { "datetime": {
@@ -1083,6 +1189,158 @@
"notInTheLast": "より前" "notInTheLast": "より前"
}, },
"visualizer": { "visualizer": {
"visualizerType": "ビジュアライザーの種類" "visualizerType": "ビジュアライザーの種類",
"colors": "色",
"cyclePresets": "サイクルプリセット",
"cycleTime": "サイクルタイム(秒)",
"includeAllPresets": "すべてのプリセットを含める",
"ignoredPresets": "無視されたプリセット",
"selectedPresets": "選択されたプリセット",
"randomizeNextPreset": "次のプリセットをランダム化",
"blendTime": "ブレンド時間",
"presets": "プリセット",
"selectPreset": "プリセットを選択",
"applyPreset": "プリセットを適用",
"saveAsPreset": "プリセットとして保存",
"updatePreset": "プリセットを更新",
"copyConfiguration": "設定をコピーする",
"pasteConfiguration": "設定を貼り付け",
"pasteConfigurationPlaceholder": "ここに JSON 設定を貼り付けてください...",
"pasteFromClipboard": "クリップボードから貼り付け",
"applyConfiguration": "設定を適用",
"configCopied": "設定をクリップボードにコピーしました",
"configCopyFailed": "設定のコピーに失敗しました",
"configPasted": "設定が正常に適用されました",
"configPasteFailed": "設定の適用に失敗しました。形式を確認してください。",
"configPasteReadFailed": "クリップボードからの読み取りに失敗しました",
"presetName": "プリセット名",
"presetNamePlaceholder": "プリセット名を入力",
"general": "全般",
"mode": "モード",
"mode1To8": "モード 1 - 8",
"mode10": "モード 10",
"barSpace": "バースペース",
"lineWidth": "線幅",
"fillAlpha": "アルファ塗りつぶしを設定",
"channelLayout": "チャンネルレイアウト",
"maxFPS": "最大フレームレート",
"opacity": "不透明度",
"customGradients": "カスタムグラデーション",
"addCustomGradient": "カスタムグラデーションを追加",
"gradientName": "グラデーション名",
"gradientNamePlaceholder": "グラデーション名",
"vertical": "垂直",
"horizontal": "水平",
"colorStops": "カラー停止点の数",
"addColor": "色を加える",
"position": "位置",
"level": "レベル",
"remove": "取り除く",
"pasteGradient": "グラデーションを貼り付け",
"pasteGradientPlaceholder": "グラデーションの JSON をここに貼り付けてください...",
"custom": "カスタム",
"builtIn": "組み込み",
"colorMode": "カラーモード",
"gradient": "勾配",
"gradientLeft": "左へのグラデーション",
"gradientRight": "右へのグラデーション",
"fft": "高速フーリエ変換",
"fftSize": "FFT サイズ",
"smoothing": "平滑化",
"frequencyRangeAndScaling": "周波数範囲とスケーリング",
"minimumFrequency": "最小周波数",
"maximumFrequency": "最大周波数",
"frequencyScale": "周波数スケール",
"sensitivity": "感度",
"weightingFilter": "重み付けフィルタ",
"minimumDecibels": "最小デシベル",
"maximumDecibels": "最大デシベル",
"linearAmplitude": "線形振幅",
"linearBoost": "リニアブースト",
"peakBehavior": "ピーク時の振る舞い",
"showPeaks": "ピークスを表示",
"fadePeaks": "フェードピークス",
"peakLine": "ピークライン",
"gravity": "重力",
"peakFadeTime": "ピークフェード時間(ミリ秒)",
"peakHoldTime": "ピークホールド時間(ミリ秒)",
"radialSpectrum": "放射状スペクトル",
"radial": "ラジアル",
"radialInvert": "放射状インバート",
"spinSpeed": "回転速度",
"radius": "半径",
"reflexMirror": "反射鏡",
"reflexFit": "リフレックス・フィット",
"reflexRatio": "反射比",
"reflexAlpha": "リフレックス・アルファ",
"reflexBrightness": "反射輝度",
"mirror": "鏡",
"miscellaneousSettings": "その他の設定",
"alphaBars": "アルファバー",
"ansiBands": "ANSI バンド",
"ledBars": "LED バー",
"trueLeds": "真の LED",
"lumiBars": "ルミ・バー",
"outlineBars": "アウトラインバー",
"roundBars": "丸棒",
"lowResolution": "低解像度",
"splitGradient": "分割グラデーション",
"showFPS": "FPS を表示",
"showScaleX": "X 軸スケールを表示",
"noteLabels": "注釈ラベル",
"showScaleY": "Y 軸スケールを表示",
"options": {
"mode": {
"0": "[0] 離散周波数",
"1": "[1] 1/24 オクターブ / 240 バンド",
"2": "[2] 1/12 オクターブ / 120 バンド",
"3": "[3] 1/8 オクターブ / 80 バンド",
"4": "[4] 1/6 オクターブ / 60 バンド",
"5": "[5] 1/4 オクターブ / 40 バンド",
"6": "[6] 1/3 オクターブ / 30 バンド",
"7": "[7] 半オクターブ / 20 バンド",
"8": "[8] フルオクターブ / 10 バンド",
"10": "[10] 折れ線グラフ / 面グラフ"
},
"colorMode": {
"gradient": "勾配",
"barIndex": "バー・インデックス",
"barLevel": "バーレベル"
},
"gradient": {
"classic": "クラシック",
"prism": "プリズム",
"rainbow": "虹",
"steelblue": "スチールブルー",
"orangered": "オレンジレッド"
},
"channelLayout": {
"single": "シングル",
"dualCombined": "デュアルコンバインド",
"dualHorizontal": "デュアル水平",
"dualVertical": "デュアルバーティカル"
},
"frequencyScale": {
"none": "なし",
"bark": "樹皮スケール",
"linear": "線形スケール",
"log": "対数スケール",
"mel": "メル尺度"
},
"weightingFilter": {
"none": "なし",
"a": "A",
"b": "B",
"c": "C",
"d": "D",
"z": "Z"
}
},
"systemAudioConsentAllow": "許可",
"systemAudioConsentBody": "ビジュアライザーを機能させるためには、システムオーディオへのアクセスが必要です",
"systemAudioConsentDecline": "拒否",
"systemAudioConsentTitle": "システムオーディオへのアクセスを許可しますか?",
"systemAudioCaptureFailed": "キャプチャを開始できませんでした: {{message}}",
"systemAudioNoAudioTrack": "音声トラックが返されませんでした。プロンプトが表示されたら、音声キャプチャが有効になっていることを確認してください。"
} }
} }
+172 -23
View File
@@ -2,7 +2,8 @@
"action": { "action": {
"openIn": { "openIn": {
"lastfm": "Åpne i Last.fm", "lastfm": "Åpne i Last.fm",
"musicbrainz": "Åpne i MusicBrainz" "musicbrainz": "Åpne i MusicBrainz",
"spotify": "Åpne i Spotify"
}, },
"moveToBottom": "flytt til bunnen", "moveToBottom": "flytt til bunnen",
"deletePlaylist": "slett $t(entity.playlist, {\"count\": 1})", "deletePlaylist": "slett $t(entity.playlist, {\"count\": 1})",
@@ -21,7 +22,23 @@
"removeFromQueue": "fjern fra kø", "removeFromQueue": "fjern fra kø",
"removeFromPlaylist": "fjern fra $t(entity.playlist, {\"count\": 1})", "removeFromPlaylist": "fjern fra $t(entity.playlist, {\"count\": 1})",
"viewPlaylists": "vise $t(entity.playlist, {\"count\": 2})", "viewPlaylists": "vise $t(entity.playlist, {\"count\": 2})",
"toggleSmartPlaylistEditor": "bytt $t(entity.smartPlaylist) editor" "toggleSmartPlaylistEditor": "bytt $t(entity.smartPlaylist) editor",
"selectAll": "marker alle",
"downloadStarted": "startet nedlasting av {{count}} elementer",
"selectRangeOfItems": "velg en rekke elementer",
"addOrRemoveFromSelection": "legge til eller fjerne fra utvalg",
"moveUp": "flytt opp",
"moveDown": "flytt ned",
"createRadioStation": "opprett $t(entity.radioStation, {\"count\": 1})",
"deleteRadioStation": "slett $t(entity.radioStation, {\"count\": 1})",
"holdToMoveToTop": "hold nede for å gå til toppen",
"holdToMoveToBottom": "hold nede for å gå til bunnen",
"moveItems": "flytt elementer",
"shuffle": "tilfeldig avspilling",
"shuffleAll": "tilfelding avspilling av alt",
"shuffleSelected": "tilfelding avspilling av utvalgte",
"viewMore": "se mer",
"openApplicationDirectory": "åpne applikasjonskatalogen"
}, },
"common": { "common": {
"bpm": "bpm", "bpm": "bpm",
@@ -50,8 +67,8 @@
"expand": "utvid", "expand": "utvid",
"favorite": "favoritt", "favorite": "favoritt",
"filters": "filter", "filters": "filter",
"forceRestartRequired": "ta omstart for å la endringene trå i kraft... lukk meldingen for å ta omstart", "forceRestartRequired": "ta omstart for å aktivere endringene... lukk meldingen for å ta omstart",
"forward": "fremover", "forward": "framover",
"gap": "avstand", "gap": "avstand",
"home": "hjem", "home": "hjem",
"increase": "øke", "increase": "øke",
@@ -88,7 +105,7 @@
"quit": "avslutt", "quit": "avslutt",
"size": "størrelse", "size": "størrelse",
"setting_one": "innstilling", "setting_one": "innstilling",
"setting_other": "", "setting_other": "innstillinger",
"trackNumber": "spor", "trackNumber": "spor",
"title": "tittel", "title": "tittel",
"channel_one": "kanal", "channel_one": "kanal",
@@ -119,7 +136,32 @@
"albumGain": "gjennomsnittlig lydnivå for album", "albumGain": "gjennomsnittlig lydnivå for album",
"albumPeak": "høyeste lydnivå for album", "albumPeak": "høyeste lydnivå for album",
"bitDepth": "bitdybde", "bitDepth": "bitdybde",
"sampleRate": "samplingsfrekvens" "sampleRate": "samplingsfrekvens",
"countSelected": "{{count}} valgt",
"doNotShowAgain": "ikke vis dette igjen",
"view": "vis",
"example": "eksempel",
"externalLinks": "eksterne lenker",
"faster": "raskere",
"filter_single": "enkelt",
"filter_multiple": "flerfoldige",
"mood": "humør",
"noFilters": "ingen filtre konfigurert",
"private": "privat",
"public": "offentlig",
"retry": "prøv igjen",
"recordLabel": "plateselskap",
"releaseType": "utgivelsestype",
"rename": "gi nytt navn",
"slower": "saktere",
"sort": "sorter",
"explicit": "grov",
"clean": "ren",
"gridRows": "rutenettrader",
"tableColumns": "tabellkolonner",
"itemsMore": "{{count}} fler",
"explicitStatus": "grovhetsstatus",
"newVersionAvailable": "en ny version er tilgjengelig"
}, },
"entity": { "entity": {
"smartPlaylist": "smart $t(entity.playlist, {\"count\": 1})", "smartPlaylist": "smart $t(entity.playlist, {\"count\": 1})",
@@ -156,7 +198,11 @@
"artist_one": "artist", "artist_one": "artist",
"artist_other": "artister", "artist_other": "artister",
"song_one": "sang", "song_one": "sang",
"song_other": "sanger" "song_other": "sanger",
"radioStation_one": "radiostasjon",
"radioStation_other": "radiostasjoner",
"radioStationWithCount_one": "{{count}} radiostasjon",
"radioStationWithCount_other": "{{count}} radiostasjoner"
}, },
"error": { "error": {
"apiRouteError": "kan ikke behandle forespørselen", "apiRouteError": "kan ikke behandle forespørselen",
@@ -166,23 +212,31 @@
"endpointNotImplementedError": "endepunkt {{endpoint}} er ikke implementert for {{serverType}}", "endpointNotImplementedError": "endepunkt {{endpoint}} er ikke implementert for {{serverType}}",
"credentialsRequired": "innloggingsdetaljer er påkrevd", "credentialsRequired": "innloggingsdetaljer er påkrevd",
"genericError": "en feil har oppstått", "genericError": "en feil har oppstått",
"invalidServer": "ugyldig server", "invalidServer": "ugyldig tjener",
"playbackError": "et problem oppstod ved avspilling av media", "playbackError": "et problem oppstod ved avspilling av media",
"localFontAccessDenied": "ingen tilgang til lokale skrifttyper", "localFontAccessDenied": "ingen tilgang til lokale skrifttyper",
"loginRateError": "for mange innloggingsforsøk, vennligst prøv igjen om noen få sekunder", "loginRateError": "for mange innloggingsforsøk, vennligst prøv igjen om noen få sekunder",
"audioDeviceFetchError": "en feil oppstod ved innhenting av lydenheter", "audioDeviceFetchError": "en feil oppstod ved innhenting av lydenheter",
"networkError": "at nettverksproblem har oppstått", "networkError": "det har oppstått et nettverksproblem",
"openError": "kunne ikke åpne fil", "openError": "kunne ikke åpne fil",
"serverNotSelectedError": "ingen server er valgt", "serverNotSelectedError": "ingen tjener er valgt",
"remotePortError": "et problem oppstod med å sette serverport", "remotePortError": "et problem oppstod med å sette serverport",
"systemFontError": "et problem oppstod med innlasting av systemskrifttyper", "systemFontError": "et problem oppstod med innlasting av systemskrifttyper",
"serverRequired": "server er påkrevd", "serverRequired": "tjener er påkrevd",
"sessionExpiredError": "sesjonen din har utløpt", "sessionExpiredError": "sesjonen din har utløpt",
"remotePortWarning": "ta omstart av serveren for å aktivere ny port", "remotePortWarning": "ta omstart av serveren for å aktivere ny port",
"remoteDisableError": "en problem oppstod ved å $t(common.disable) serveren", "remoteDisableError": "en problem oppstod ved å $t(common.disable) serveren",
"remoteEnableError": "et problem oppstod ved å $t(common.enable) serveren", "remoteEnableError": "et problem oppstod ved å $t(common.enable) serveren",
"notificationDenied": "tillatelser for varsler ble avvist. Denne innstillingen har ingen effekt", "notificationDenied": "tillatelser for varsler ble avvist. Denne innstillingen har ingen effekt",
"badValue": "ugyldig alternativ \"{{value}}\". Denne verdien eksisterer ikke lenger" "badValue": "ugyldig alternativ \"{{value}}\". Denne verdien eksisterer ikke lenger",
"noNetwork": "tjener utilgjengelig",
"noNetworkDescription": "kunne ikke koble til tjeneren",
"invalidJson": "ugyldig JSON",
"saveQueueFailed": "kunne ikke lagre kø",
"multipleServerSaveQueueError": "Spillekøen har en eller flere sanger som ikke finnes på gjeldene tjener. Dette er ikke støttet",
"serverLockSingleServer": "kun én tjener er tillatt når tjener er låst",
"settingsSyncError": "avvik ble funnet mellom innstillinger i avspilleren og hovedprosessen. ta en omstart av applikasjonen for å aktivere endringene",
"playbackPausedDueToError": "avspilling ble paused på grunn av en feil"
}, },
"filter": { "filter": {
"bpm": "bpm", "bpm": "bpm",
@@ -223,10 +277,14 @@
"isCompilation": "er samling", "isCompilation": "er samling",
"isFavorited": "er merket som favoritt", "isFavorited": "er merket som favoritt",
"recentlyAdded": "nylig lagt til", "recentlyAdded": "nylig lagt til",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel, {\"count\": 2})",
"genre": "$t(entity.genre, {\"count\": 1})", "genre": "$t(entity.genre, {\"count\": 1})",
"trackNumber": "spor", "trackNumber": "spor",
"albumCount": "$t(entity.album, {\"count\": 2}) opptelling" "albumCount": "$t(entity.album, {\"count\": 2}) opptelling",
"matchAnd": "og",
"matchOr": "eller",
"sortName": "sorter navn",
"explicitStatus": "$t(common.explicitStatus)"
}, },
"form": { "form": {
"createPlaylist": { "createPlaylist": {
@@ -253,13 +311,19 @@
"input_legacyAuthentication": "aktiver tradisjonell autentisering", "input_legacyAuthentication": "aktiver tradisjonell autentisering",
"input_name": "servernavn", "input_name": "servernavn",
"title": "legg til server", "title": "legg til server",
"input_password": "passord" "input_password": "passord",
"input_preferInstantMix": "foretrekk øyeblikkelig miks",
"input_preferInstantMixDescription": "bruk bare øyeblikkelig miks for innhenting av lignende sanger. nyttig hvis du har tilleggsmoduler som endrer funksjonaliteten",
"input_preferRemoteUrl": "foretrekk offentlig url",
"input_remoteUrl": "offentlig url",
"input_remoteUrlPlaceholder": "valgfritt: offentlig nettadresse for eksterne funksjoner"
}, },
"addToPlaylist": { "addToPlaylist": {
"success": "la $t(entity.trackWithCount, {\"count\": {{message}} }) til $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} })", "success": "la $t(entity.trackWithCount, {\"count\": {{message}} }) til $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} })",
"title": "legg til i $t(entity.playlist, {\"count\": 1})", "title": "legg til i $t(entity.playlist, {\"count\": 1})",
"input_skipDuplicates": "hopp over duplikater", "input_skipDuplicates": "hopp over duplikater",
"input_playlists": "$t(entity.playlist, {\"count\": 2})" "input_playlists": "$t(entity.playlist, {\"count\": 2})",
"searchOrCreate": "søk $t(entity.playlist, {\"count\": 2}) eller skriv for å opprette en"
}, },
"deletePlaylist": { "deletePlaylist": {
"title": "slett $t(entity.playlist, {\"count\": 1})", "title": "slett $t(entity.playlist, {\"count\": 1})",
@@ -268,7 +332,8 @@
}, },
"editPlaylist": { "editPlaylist": {
"title": "rediger $t(entity.playlist, {\"count\": 1})", "title": "rediger $t(entity.playlist, {\"count\": 1})",
"success": "$t(entity.playlist, {\"count\": 1}) er oppdatert" "success": "$t(entity.playlist, {\"count\": 1}) er oppdatert",
"publicJellyfinNote": "Jellyfin av en grunn kan ikke oppgi om en spilleliste er offentlig eller ikke. Hvis du ønsker at denne skal beholdes offentlig, vennligst ha følgende inndata valgt"
}, },
"shareItem": { "shareItem": {
"allowDownloading": "tillat nedlasting", "allowDownloading": "tillat nedlasting",
@@ -276,7 +341,9 @@
"createFailed": "opprettelse av delt ressurs feilet (er deling aktivert?)", "createFailed": "opprettelse av delt ressurs feilet (er deling aktivert?)",
"setExpiration": "angi utløpstid", "setExpiration": "angi utløpstid",
"success": "del lenke som er kopiert til utklippstavlen (eller klikk her for å åpne)", "success": "del lenke som er kopiert til utklippstavlen (eller klikk her for å åpne)",
"expireInvalid": "utløpstid må være et fremtidig tidspunkt" "expireInvalid": "utløpstid må være et fremtidig tidspunkt",
"copyToClipboard": "Kopier til kopitavle: Ctrl+C, Enter",
"successMustClick": "opprettet deling. trykk her for å åpne"
}, },
"updateServer": { "updateServer": {
"success": "vellykket oppdatering av serveren", "success": "vellykket oppdatering av serveren",
@@ -285,7 +352,41 @@
"queryEditor": { "queryEditor": {
"input_optionMatchAll": "match alle", "input_optionMatchAll": "match alle",
"input_optionMatchAny": "matche hvilken som helst", "input_optionMatchAny": "matche hvilken som helst",
"title": "redigeringsverktøy for spørringer" "title": "redigeringsverktøy for spørringer",
"addRuleGroup": "legg til regelgruppe",
"removeRuleGroup": "fjern regelgruppe",
"resetToDefault": "tilbakestill til standard",
"clearFilters": "tøm filter"
},
"largeFetchConfirmation": {
"title": "legg til elementer i køen",
"description": "Denne handlingen vil legge alle elementene til den gjeldende filtervisningen"
},
"createRadioStation": {
"success": "vellykket opprettelse av radiostasjon",
"title": "opprett radiostasjon",
"input_homepageUrl": "hjemmesidelenke",
"input_name": "navn",
"input_streamUrl": "strømmelenke"
},
"saveQueue": {
"success": "lagre spillekø på tjener"
},
"lyricsExport": {
"export": "eksporter sangtekster",
"input_synced": "eksporter sunkroniserte sangtekster",
"input_offset": "$t(setting.lyricOffset)"
},
"shuffleAll": {
"title": "spill av tilfeldig",
"input_genre": "$t(entity.genre, {\"count\": 1})",
"input_limit": "hvor mange sanger?",
"input_minYear": "fra år",
"input_maxYear": "til år",
"input_played": "avspillingsfilter",
"input_played_optionAll": "alle sanger",
"input_played_optionUnplayed": "bare uavspilte sanger",
"input_played_optionPlayed": "bare avspilte sanger"
} }
}, },
"page": { "page": {
@@ -421,7 +522,7 @@
"playlists": "$t(entity.playlist, {\"count\": 2})", "playlists": "$t(entity.playlist, {\"count\": 2})",
"search": "$t(common.search)", "search": "$t(common.search)",
"settings": "$t(common.setting, {\"count\": 2})", "settings": "$t(common.setting, {\"count\": 2})",
"shared": "delt $t(entity.playlist, {\"count\": 2})", "shared": "delte $t(entity.playlist, {\"count\": 2})",
"artists": "$t(entity.artist, {\"count\": 2})", "artists": "$t(entity.artist, {\"count\": 2})",
"myLibrary": "mitt bibliotek" "myLibrary": "mitt bibliotek"
}, },
@@ -430,7 +531,8 @@
"advanced": "avansert", "advanced": "avansert",
"hotkeysTab": "hurtigtaster", "hotkeysTab": "hurtigtaster",
"playbackTab": "avspilling", "playbackTab": "avspilling",
"windowTab": "vindu" "windowTab": "vindu",
"theme": "tema"
}, },
"playlistList": { "playlistList": {
"title": "$t(entity.playlist, {\"count\": 2})" "title": "$t(entity.playlist, {\"count\": 2})"
@@ -501,7 +603,15 @@
"general": { "general": {
"autoFitColumns": "automatisk kolonnetilpasning", "autoFitColumns": "automatisk kolonnetilpasning",
"displayType": "visningstype", "displayType": "visningstype",
"followCurrentSong": "følg gjeldende sang" "followCurrentSong": "følg gjeldende sang",
"advancedSettings": "avanserte innstillinger",
"moveUp": "flytt opp",
"moveDown": "flytt ned",
"pinToLeft": "fest til venstre",
"pinToRight": "fest til høyre",
"alignLeft": "venstrejuster",
"alignCenter": "midtjuster",
"alignRight": "høyrejuster"
} }
}, },
"column": { "column": {
@@ -519,7 +629,46 @@
"rating": "vurdering", "rating": "vurdering",
"releaseDate": "utgivelsesdato", "releaseDate": "utgivelsesdato",
"title": "tittel", "title": "tittel",
"trackNumber": "spor" "trackNumber": "spor",
"owner": "eier"
}
},
"filterOperator": {
"after": "er etter",
"afterDate": "er etter (date)",
"before": "er før",
"beforeDate": "er før (date)",
"contains": "inneholder",
"endsWith": "ender med",
"inPlaylist": "er inne i",
"inTheLast": "er inne i de siste",
"inTheRange": "er innenfor området",
"isGreaterThan": "er større enn",
"isLessThan": "er mindre enn",
"matchesRegex": "samsvarer med regex",
"notContains": "inneholder ikke",
"notInPlaylist": "er ikke med i",
"notInTheLast": "er ikke med i de siste",
"startsWith": "starter med",
"inTheRangeDate": "er innenfor området (date)",
"is": "er",
"isNot": "er ikke"
},
"datetime": {
"minuteShort": "m",
"secondShort": "s",
"hourShort": "h",
"dayShort": "d"
},
"visualizer": {
"options": {
"weightingFilter": {
"a": "A",
"b": "B",
"c": "C",
"d": "D",
"z": "Z"
}
} }
} }
} }
+97 -22
View File
@@ -19,7 +19,10 @@
"clearQueue": "verwijder lijst", "clearQueue": "verwijder lijst",
"openIn": { "openIn": {
"lastfm": "Open in Last.fm", "lastfm": "Open in Last.fm",
"musicbrainz": "Open in MusicBrainz" "musicbrainz": "Open in MusicBrainz",
"listenbrainz": "Openen in ListenBrainz",
"qobuz": "Openen in Qobuz",
"spotify": "Openen in Spotify"
}, },
"moveToNext": "ga naar volgende", "moveToNext": "ga naar volgende",
"downloadStarted": "begonnen met downloaden van {{count}} items", "downloadStarted": "begonnen met downloaden van {{count}} items",
@@ -37,7 +40,8 @@
"moveDown": "verplaats omlaag", "moveDown": "verplaats omlaag",
"holdToMoveToTop": "ingedrukt houden om naar begin te verplaatsen", "holdToMoveToTop": "ingedrukt houden om naar begin te verplaatsen",
"holdToMoveToBottom": "ingedrukt houden om naar einde te verplaatsen", "holdToMoveToBottom": "ingedrukt houden om naar einde te verplaatsen",
"openApplicationDirectory": "applicatiemap openen" "openApplicationDirectory": "applicatiemap openen",
"goToCurrent": "ga naar huidige item"
}, },
"common": { "common": {
"backward": "achteruit", "backward": "achteruit",
@@ -130,6 +134,7 @@
"bitDepth": "bitdiepte", "bitDepth": "bitdiepte",
"codec": "codec", "codec": "codec",
"mbid": "MusicBrainz ID", "mbid": "MusicBrainz ID",
"grouping": "groepering",
"share": "deel", "share": "deel",
"explicit": "expliciet", "explicit": "expliciet",
"sampleRate": "sample rate", "sampleRate": "sample rate",
@@ -138,7 +143,7 @@
"doNotShowAgain": "niet opnieuw tonen", "doNotShowAgain": "niet opnieuw tonen",
"externalLinks": "externe links", "externalLinks": "externe links",
"faster": "sneller", "faster": "sneller",
"preview": "voorvertoning", "preview": "voorbeeld",
"private": "privé", "private": "privé",
"public": "publiekelijk", "public": "publiekelijk",
"recordLabel": "platenlabel", "recordLabel": "platenlabel",
@@ -147,7 +152,7 @@
"sort": "sorteer", "sort": "sorteer",
"trackGain": "trackvolume", "trackGain": "trackvolume",
"trackPeak": "piekniveau", "trackPeak": "piekniveau",
"clean": "schoon", "clean": "opschonen",
"gridRows": "rasterrijen", "gridRows": "rasterrijen",
"tableColumns": "tabelkolommen", "tableColumns": "tabelkolommen",
"itemsMore": "{{count}} meer", "itemsMore": "{{count}} meer",
@@ -159,7 +164,9 @@
"retry": "opnieuw proberen", "retry": "opnieuw proberen",
"filter_single": "single", "filter_single": "single",
"rename": "hernoemen", "rename": "hernoemen",
"filter_multiple": "meerdere" "filter_multiple": "meerdere",
"numberOfResults": "{{numberOfResults}} resultaten",
"newVersionAvailable": "een nieuwe versie is beschikbaar"
}, },
"filter": { "filter": {
"rating": "rating", "rating": "rating",
@@ -169,7 +176,7 @@
"comment": "commentaar", "comment": "commentaar",
"playCount": "aantal keer afgespeeld", "playCount": "aantal keer afgespeeld",
"recentlyUpdated": "recentelijk geüpdate", "recentlyUpdated": "recentelijk geüpdate",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel, {\"count\": 2})",
"isCompilation": "is compilatie", "isCompilation": "is compilatie",
"recentlyPlayed": "recentelijk afgespeeld", "recentlyPlayed": "recentelijk afgespeeld",
"isRated": "is rated", "isRated": "is rated",
@@ -205,7 +212,9 @@
"toYear": "tot jaar", "toYear": "tot jaar",
"trackNumber": "track", "trackNumber": "track",
"explicitStatus": "$t(common.explicitStatus)", "explicitStatus": "$t(common.explicitStatus)",
"sortName": "sorteernaam" "sortName": "sorteernaam",
"matchAnd": "en",
"matchOr": "of"
}, },
"page": { "page": {
"contextMenu": { "contextMenu": {
@@ -274,7 +283,9 @@
"unsynchronized": "niet gesynchronizeerd", "unsynchronized": "niet gesynchronizeerd",
"useImageAspectRatio": "gebruik aspect ratio van de afbeelding", "useImageAspectRatio": "gebruik aspect ratio van de afbeelding",
"lyricOffset": "songtekst-vertraging (ms)", "lyricOffset": "songtekst-vertraging (ms)",
"showLyricProvider": "toon songtekstaanbieder" "showLyricProvider": "toon songtekstaanbieder",
"lyricOpacityNonActive": "opaciteit van niet-actieve songtekst",
"lyricScaleNonActive": "schaal niet-actieve songtekst"
}, },
"lyrics": "liedtekst", "lyrics": "liedtekst",
"related": "gerelateerd", "related": "gerelateerd",
@@ -412,6 +423,11 @@
"collections": { "collections": {
"overrideExisting": "bestaande overschrijven", "overrideExisting": "bestaande overschrijven",
"saveAsCollection": "sla op als verzameling" "saveAsCollection": "sla op als verzameling"
},
"releasenotes": {
"commitsSinceStable": "commits sinds {{stable}}",
"noNewCommits": "geen nieuwe commits in dit bereik",
"noStableReleaseToCompare": "geen stabiele uitgave beschikbaar om mee te vergelijken"
} }
}, },
"error": { "error": {
@@ -443,7 +459,10 @@
"noNetwork": "server niet beschikbaar", "noNetwork": "server niet beschikbaar",
"noNetworkDescription": "kan geen verbinding maken met deze server", "noNetworkDescription": "kan geen verbinding maken met deze server",
"saveQueueFailed": "kan wachtrij niet opslaan", "saveQueueFailed": "kan wachtrij niet opslaan",
"settingsSyncError": "Er zijn verschillen gevonden tussen de instellingen in de renderer en het hoofdproces. Start de applicatie opnieuw op om de wijzigingen toe te passen" "settingsSyncError": "Er zijn verschillen gevonden tussen de instellingen in de renderer en het hoofdproces. Start de applicatie opnieuw op om de wijzigingen toe te passen",
"invalidJson": "ongeldige JSON",
"serverLockSingleServer": "slechts één server is toegestaan als server op slot is gezet",
"playbackPausedDueToError": "afspelen gepauzeerd vanwege een fout"
}, },
"entity": { "entity": {
"genre_one": "genre", "genre_one": "genre",
@@ -552,7 +571,8 @@
"title": "$t(common.title)", "title": "$t(common.title)",
"titleArtist": "$t(common.title) (artiest)", "titleArtist": "$t(common.title) (artiest)",
"titleCombined": "$t(common.title) (gecombineerd)", "titleCombined": "$t(common.title) (gecombineerd)",
"year": "$t(common.year)" "year": "$t(common.year)",
"albumGroup": "albumgroep"
}, },
"general": { "general": {
"advancedSettings": "geavanceerde instellingen", "advancedSettings": "geavanceerde instellingen",
@@ -589,7 +609,8 @@
"view": { "view": {
"grid": "grid", "grid": "grid",
"list": "lijst", "list": "lijst",
"table": "tabel" "table": "tabel",
"detail": "details"
} }
} }
}, },
@@ -603,7 +624,7 @@
"discordListening_description": "status weergeven als luisterend in plaats van afspelend", "discordListening_description": "status weergeven als luisterend in plaats van afspelend",
"discordListening": "status weergeven als 'luisterend'", "discordListening": "status weergeven als 'luisterend'",
"discordPausedStatus_description": "wanneer ingeschakeld, wordt de status ook weergegeven als de speler gepauzeerd is", "discordPausedStatus_description": "wanneer ingeschakeld, wordt de status ook weergegeven als de speler gepauzeerd is",
"discordPausedStatus": "rich presence tonen wanneer gepauseerd", "discordPausedStatus": "rich presence tonen wanneer gepauzeerd",
"discordRichPresence": "{{discord}} rich presence", "discordRichPresence": "{{discord}} rich presence",
"exitToTray_description": "sluit de applicatie naar het systeemvak", "exitToTray_description": "sluit de applicatie naar het systeemvak",
"exitToTray": "sluit naar systeemvak", "exitToTray": "sluit naar systeemvak",
@@ -659,9 +680,9 @@
"artistConfiguration_description": "configureer welke items worden getoond op de albumartiestpagina en in welke volgorde", "artistConfiguration_description": "configureer welke items worden getoond op de albumartiestpagina en in welke volgorde",
"artistReleaseTypeConfiguration": "configuratie artiestuitgavesoorten", "artistReleaseTypeConfiguration": "configuratie artiestuitgavesoorten",
"artistReleaseTypeConfiguration_description": "configureer welke uitgavesoorten worden getoond op de albumartiestpagina en in welke volgorde", "artistReleaseTypeConfiguration_description": "configureer welke uitgavesoorten worden getoond op de albumartiestpagina en in welke volgorde",
"audioDevice_description": "kies het audioapparaat dat wordt gebruikt om af te spelen (enkel voor de webspeler)", "audioDevice_description": "kies het audioapparaat dat wordt gebruikt om af te spelen",
"audioDevice": "audioapparaat", "audioDevice": "audioapparaat",
"audioExclusiveMode_description": "schakel exclusieve uitvoermodus in. In deze modus wordt het systeem normaliter uitgesloten en zal enkel mpv audio kunnen uitvoeren", "audioExclusiveMode_description": "schakel exclusieve uitvoermodus in. in deze modus wordt het systeem normaliter uitgesloten en zal enkel mpv audio kunnen uitvoeren. geluidsopname in de visualiseerder zal niet werken als dit is ingeschakeld",
"audioExclusiveMode": "audio-exclusieve modus", "audioExclusiveMode": "audio-exclusieve modus",
"audioPlayer_description": "kies de audiospeler om te gebruiken bij het afspelen", "audioPlayer_description": "kies de audiospeler om te gebruiken bij het afspelen",
"audioPlayer": "audiospeler", "audioPlayer": "audiospeler",
@@ -688,7 +709,7 @@
"releaseChannel_optionBeta": "beta", "releaseChannel_optionBeta": "beta",
"releaseChannel_optionLatest": "meest recente", "releaseChannel_optionLatest": "meest recente",
"releaseChannel": "releasekanaal", "releaseChannel": "releasekanaal",
"releaseChannel_description": "kies tussen stabiele releases of beta-releases voor automatische updates", "releaseChannel_description": "kies tussen stabiele, of beta- of alpha-releases (nachtelijk) voor automatische updates",
"disableLibraryUpdateOnStartup": "niet controleren op nieuwe versies bij het opstarten", "disableLibraryUpdateOnStartup": "niet controleren op nieuwe versies bij het opstarten",
"discordApplicationId_description": "de applicatie-id voor {{discord}} rich presence (standaard is {{defaultId}})", "discordApplicationId_description": "de applicatie-id voor {{discord}} rich presence (standaard is {{defaultId}})",
"hotkey_listPlayNow": "nu in lijst spelen", "hotkey_listPlayNow": "nu in lijst spelen",
@@ -728,7 +749,7 @@
"lastfmApiKey": "{{lastfm}}-API-sleutel", "lastfmApiKey": "{{lastfm}}-API-sleutel",
"lyricFetch_description": "bevraag verschillende bronnen op het internet voor songteksten", "lyricFetch_description": "bevraag verschillende bronnen op het internet voor songteksten",
"lyricFetch": "haal songteksten op van het internet", "lyricFetch": "haal songteksten op van het internet",
"lyricFetchProvider_description": "kies de diensten die geraadpleegd worden voor songteksten. de volgorde van de diensten is tevens de volgorde waarop deze worden geraadpleegd", "lyricFetchProvider_description": "kies de diensten die geraadpleegd worden voor songteksten",
"lyricFetchProvider": "diensten voor songteksten", "lyricFetchProvider": "diensten voor songteksten",
"lyricOffset_description": "compenseer de songtekst met het gegeven aantal milliseconden", "lyricOffset_description": "compenseer de songtekst met het gegeven aantal milliseconden",
"lyricOffset": "compensatie songtekst (ms)", "lyricOffset": "compensatie songtekst (ms)",
@@ -937,7 +958,40 @@
"playButtonBehavior_optionPlayShuffled": "$t(player.shuffle)", "playButtonBehavior_optionPlayShuffled": "$t(player.shuffle)",
"replayGainMode_optionAlbum": "$t(entity.album, {\"count\": 1})", "replayGainMode_optionAlbum": "$t(entity.album, {\"count\": 1})",
"replayGainMode_optionNone": "$t(common.none)", "replayGainMode_optionNone": "$t(common.none)",
"replayGainMode_optionTrack": "$t(entity.track, {\"count\": 1})" "replayGainMode_optionTrack": "$t(entity.track, {\"count\": 1})",
"analyticsEnable": "Verstuur gebruiksstatistieken",
"analyticsEnable_description": "Geanonimiseerde gebruiksgegevens worden naar de ontwikkelaar gestuurd om te helpen de applicatie te verbeteren",
"automaticUpdates": "Automatisch bijwerken",
"automaticUpdates_description": "Zoek en installeer updates automatisch",
"releaseChannel_optionAlpha": "alfa (nachtelijk)",
"discordStateIcon": "toon afspeelicoon",
"discordStateIcon_description": "toon een klein afspeelicoon in de rich-presence-status. het gepauzeerde icoon wordt altijd getoond als \"rich presence tonen wanneer gepauzeerd\" is ingeschakeld",
"autosave": "afspeelwachtrij automatisch opslaan",
"autosave_description": "schakel in dat de afspeelwachtrij automatisch wordt opgeslagen op je server. dit is enkel mogelijk bij gebruik van Navidrome/Subsonic met een niet-gemengde afspeelwachtrij.",
"autosaveCount": "frequentie automatisch opslaan afspeelwachtrij",
"autosaveCount_description": "aantal nummerwisselingen voordat de wachtrij wordt opgeslagen. bij 1 (het minimum) treedt dit bij elke nummerwissel op",
"useThemePrimaryShade": "gebruikt primaire tint van thema",
"useThemePrimaryShade_description": "gebruik de primaire tint die in het geselecteerde thema is ingesteld voor hoofdkleurvarianten",
"primaryShade": "primaire tint",
"primaryShade_description": "overschrijf de primaire tint (0-9) die wordt gebruikt voor knoppen, links en andere elementen die de hoofdkleur gebruiken",
"listenbrainz_description": "toon links naar ListenBrainz op artiest- en albumpagina's",
"listenbrainz": "toon ListenBrainz-links",
"qobuz_description": "toon links naar Qobuz op artiest- en albumpagina's",
"qobuz": "toon Qobuz-links",
"spotify_description": "toon links naar Spotify op artiest- en albumpagina's",
"spotify": "toon Spotify-links",
"nativeSpotify_description": "open de Spotify app in plaats van de webbrowser",
"nativeSpotify": "gebruik Spotify app",
"playerItemConfiguration_description": "stel in welke items en in welke volgorde te tonen in de volledigschermspeler",
"playerItemConfiguration": "configuratie van afspeel-item",
"sidePlayQueueLayout": "uitlijning afspeelwachtrij aan zijkant",
"sidePlayQueueLayout_description": "stel de uitlijning in voor de afspeelwachtrij die aan de zijkant is gekoppeld",
"sidePlayQueueLayout_optionHorizontal": "horizontaal",
"sidePlayQueueLayout_optionVertical": "verticaal",
"playerbarWaveformStretch": "rekking van golfvorm",
"playerbarWaveformStretch_description": "rekt de golfvorm om de beschikbare ruimte op te vullen",
"waveformLoadingDelay": "laadvertraging van golfvorm",
"waveformLoadingDelay_description": "vertraging in seconden voordat de golfvorm wordt geladen. vergroot deze waarde als je stotteringen ervaart bij gebruik van de webspeler."
}, },
"form": { "form": {
"addServer": { "addServer": {
@@ -996,8 +1050,7 @@
"editPlaylist": { "editPlaylist": {
"title": "$t(entity.playlist, {\"count\": 1}) aanpassen", "title": "$t(entity.playlist, {\"count\": 1}) aanpassen",
"publicJellyfinNote": "Jellyfin laat niet weten of een playlist publiek of privaat is. Als u wilt dat dit publiek blijft, selecteer de volgende invoer", "publicJellyfinNote": "Jellyfin laat niet weten of een playlist publiek of privaat is. Als u wilt dat dit publiek blijft, selecteer de volgende invoer",
"success": "$t(entity.playlist, {\"count\": 1}) succesvol geüpdatet", "success": "$t(entity.playlist, {\"count\": 1}) succesvol geüpdatet"
"editNote": "Handmatige bewerking wordt afgeraden voor grote afspeellijsten. Weet je zeker dat je het risico op dataverlies wilt accepteren door de bestaande afspeellijst te overschrijven?"
}, },
"updateServer": { "updateServer": {
"title": "update server", "title": "update server",
@@ -1009,7 +1062,9 @@
"setExpiration": "stel vervaldatum in", "setExpiration": "stel vervaldatum in",
"success": "deel link gekopiëerd naar klembord (of klik hier om te openen)", "success": "deel link gekopiëerd naar klembord (of klik hier om te openen)",
"expireInvalid": "vervaldatum moet in de toekomst zijn", "expireInvalid": "vervaldatum moet in de toekomst zijn",
"createFailed": "kon share niet aanmaken (is delen aangezet?)" "createFailed": "kon share niet aanmaken (is delen aangezet?)",
"copyToClipboard": "Kopieer naar klembord: Ctrl+C, Enter",
"successMustClick": "gedeelde bron succesvol aangemaakt. klik hier om te openen"
}, },
"privateMode": { "privateMode": {
"enabled": "private modus ingeschakeld, afspeelstatus is nu verborgen voor externe integraties", "enabled": "private modus ingeschakeld, afspeelstatus is nu verborgen voor externe integraties",
@@ -1045,6 +1100,9 @@
}, },
"saveQueue": { "saveQueue": {
"success": "wachtrij opgeslagen op server" "success": "wachtrij opgeslagen op server"
},
"editRadioStation": {
"success": "radiozender succesvol bijgewerkt"
} }
}, },
"player": { "player": {
@@ -1086,7 +1144,17 @@
"trackRadio": "nummerradio", "trackRadio": "nummerradio",
"unfavorite": "verwijder favoriet", "unfavorite": "verwijder favoriet",
"pause": "pauzeren", "pause": "pauzeren",
"viewQueue": "toon wachtrij" "viewQueue": "toon wachtrij",
"sleepTimer": "slaaptimer",
"sleepTimer_endOfSong": "einde van huidige nummer",
"sleepTimer_minutes": "{{count}} min",
"sleepTimer_hours": "{{count}} uur",
"sleepTimer_custom": "afwijkend",
"sleepTimer_off": "uit",
"sleepTimer_timeRemaining": "{{time}} resterend",
"sleepTimer_setCustom": "timer instellen",
"sleepTimer_cancel": "timer annuleren",
"albumRadio": "albumradio"
}, },
"datetime": { "datetime": {
"minuteShort": "m", "minuteShort": "m",
@@ -1294,6 +1362,13 @@
"d": "D", "d": "D",
"z": "Z" "z": "Z"
} }
} },
"systemAudioConsentAllow": "Toestaan",
"systemAudioConsentBody": "De visualiseerder heeft toegang tot het audiosysteem nodig om te werken",
"systemAudioConsentDecline": "Weigeren",
"systemAudioConsentTitle": "Toegang tot audiosysteem toestaan?",
"systemAudioCaptureFailed": "Kon opname niet starten: {{message}}",
"systemAudioNoAudioTrack": "Geen geluidsspoor ontvangen. Verifieer dat audio-opname is ingeschakeld als daar om wordt gevraagd.",
"systemAudioExclusiveModeNotSupported": "De visualiseerder is niet beschikbaar als audio-exclusieve modus is ingeschakeld. Schakel audio-exclusieve modus in de MPV-instellingen uit en probeer het opnieuw."
} }
} }
+90 -18
View File
@@ -19,7 +19,10 @@
"setRating": "oceń", "setRating": "oceń",
"openIn": { "openIn": {
"lastfm": "Otwórz w Last.fm", "lastfm": "Otwórz w Last.fm",
"musicbrainz": "Otwórz w MusicBrainz" "musicbrainz": "Otwórz w MusicBrainz",
"listenbrainz": "Otwórz w ListenBrainz",
"qobuz": "Otwórz w Qobuz",
"spotify": "Otwórz w Spotify"
}, },
"moveToNext": "przesuń na następne", "moveToNext": "przesuń na następne",
"downloadStarted": "rozpoczęto pobieranie {{count}} elementów", "downloadStarted": "rozpoczęto pobieranie {{count}} elementów",
@@ -37,7 +40,8 @@
"addOrRemoveFromSelection": "dodaj lub usuń z wyboru", "addOrRemoveFromSelection": "dodaj lub usuń z wyboru",
"selectRangeOfItems": "wybierz zakres elementów", "selectRangeOfItems": "wybierz zakres elementów",
"selectAll": "wybierz wszystkie", "selectAll": "wybierz wszystkie",
"openApplicationDirectory": "otwórz katalog aplikacji" "openApplicationDirectory": "otwórz katalog aplikacji",
"goToCurrent": "przejdź do aktualnego elementu"
}, },
"common": { "common": {
"increase": "zwiększ", "increase": "zwiększ",
@@ -163,7 +167,10 @@
"example": "przykład", "example": "przykład",
"filter_multiple": "multi", "filter_multiple": "multi",
"filter_single": "single", "filter_single": "single",
"rename": "zmień nazwę" "rename": "zmień nazwę",
"newVersionAvailable": "nowa wersja jest dostępna",
"numberOfResults": "{{numberOfResults}} wyników",
"grouping": "grupowanie"
}, },
"entity": { "entity": {
"genre_one": "gatunek", "genre_one": "gatunek",
@@ -254,7 +261,10 @@
"saveQueueFailed": "nie udało się zapisać kolejki", "saveQueueFailed": "nie udało się zapisać kolejki",
"settingsSyncError": "zostały znalezione różnice pomiędzy ustawieniami w rendererze a głównym procesem. uruchom aplikację ponownie aby, zastosować zmiany", "settingsSyncError": "zostały znalezione różnice pomiędzy ustawieniami w rendererze a głównym procesem. uruchom aplikację ponownie aby, zastosować zmiany",
"noNetwork": "serwer niedostępny", "noNetwork": "serwer niedostępny",
"noNetworkDescription": "nie udało się połączyć z tym serwerem" "noNetworkDescription": "nie udało się połączyć z tym serwerem",
"invalidJson": "nieprawidłowy JSON",
"serverLockSingleServer": "dozwolony jest tylko jeden serwer gdy serwer jest zablokowany",
"playbackPausedDueToError": "odtwarzanie zostało wstrzymane z powodu błędu"
}, },
"filter": { "filter": {
"mostPlayed": "najczęściej odtwarzane", "mostPlayed": "najczęściej odtwarzane",
@@ -300,7 +310,9 @@
"isPublic": "jest publiczny", "isPublic": "jest publiczny",
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
"explicitStatus": "$t(common.explicitStatus)", "explicitStatus": "$t(common.explicitStatus)",
"sortName": "sortowanie po nazwie" "sortName": "sortowanie po nazwie",
"matchAnd": "i",
"matchOr": "lub"
}, },
"form": { "form": {
"deletePlaylist": { "deletePlaylist": {
@@ -340,7 +352,8 @@
"input_skipDuplicates": "pomiń duplikaty", "input_skipDuplicates": "pomiń duplikaty",
"input_playlists": "$t(entity.playlist, {\"count\": 2})", "input_playlists": "$t(entity.playlist, {\"count\": 2})",
"create": "utwórz $t(entity.playlist, {\"count\": 1}) {{playlist}}", "create": "utwórz $t(entity.playlist, {\"count\": 1}) {{playlist}}",
"searchOrCreate": "wyszukaj $t(entity.playlist, {\"count\": 2}) lub wpisz, aby utworzyć nową" "searchOrCreate": "wyszukaj $t(entity.playlist, {\"count\": 2}) lub wpisz, aby utworzyć nową",
"noneAdded": "nie dodano utworów do $t(entity.playlist, {\"count\": 1}) '{{playlist}}'"
}, },
"updateServer": { "updateServer": {
"title": "uaktualnij serwer", "title": "uaktualnij serwer",
@@ -363,8 +376,7 @@
"editPlaylist": { "editPlaylist": {
"title": "edytuj $t(entity.playlist, {\"count\": 1})", "title": "edytuj $t(entity.playlist, {\"count\": 1})",
"success": "$t(entity.playlist, {\"count\": 1}) zaktualizowana pomyślnie", "success": "$t(entity.playlist, {\"count\": 1}) zaktualizowana pomyślnie",
"publicJellyfinNote": "Z jakiegoś powodu Jellyfin nie udostępnia informacji na temat publiczności playlisty. Jeżeli chcesz, aby ta pozostała publiczna, mniej wybraną poniższą opcję", "publicJellyfinNote": "Z jakiegoś powodu Jellyfin nie udostępnia informacji na temat publiczności playlisty. Jeżeli chcesz, aby ta pozostała publiczna, mniej wybraną poniższą opcję"
"editNote": "manualne edytowanie nie jest zalecane dla dużych playlist. czy na pewno zgadzasz się na ryzyko utraty danych wywołane przez nadpisanie istniejącej playlisty?"
}, },
"shareItem": { "shareItem": {
"allowDownloading": "zezwól na pobieranie", "allowDownloading": "zezwól na pobieranie",
@@ -372,7 +384,9 @@
"setExpiration": "ustaw czas wygaśnięcia", "setExpiration": "ustaw czas wygaśnięcia",
"success": "link do udostępniania skopiowany do schowka (lub kliknij tutaj, aby otworzyć)", "success": "link do udostępniania skopiowany do schowka (lub kliknij tutaj, aby otworzyć)",
"createFailed": "nie udało się utworzyć linku do udostępniania (czy udostępnianie jest włączone?)", "createFailed": "nie udało się utworzyć linku do udostępniania (czy udostępnianie jest włączone?)",
"expireInvalid": "ustawiony czas wygaśnięcia musi być w przyszłości" "expireInvalid": "ustawiony czas wygaśnięcia musi być w przyszłości",
"copyToClipboard": "Skopiuj do schowka: Ctrl+C, Enter",
"successMustClick": "udostępnianie utworzone pomyślnie, kliknij tutaj żeby otworzyć"
}, },
"privateMode": { "privateMode": {
"enabled": "tryb prywatny włączony, status odtwarzania jest ukryty przed usługami zewnętrznymi", "enabled": "tryb prywatny włączony, status odtwarzania jest ukryty przed usługami zewnętrznymi",
@@ -408,6 +422,9 @@
"export": "eksportuj tekst", "export": "eksportuj tekst",
"input_synced": "eksportuj zsynchronizowany tekst", "input_synced": "eksportuj zsynchronizowany tekst",
"input_offset": "$t(setting.lyricOffset)" "input_offset": "$t(setting.lyricOffset)"
},
"editRadioStation": {
"success": "stacja radiowa zaktualizowana pomyślnie"
} }
}, },
"page": { "page": {
@@ -426,7 +443,9 @@
"lyricGap": "odstępy tekstu", "lyricGap": "odstępy tekstu",
"dynamicImageBlur": "rozmiar rozmycia obrazu", "dynamicImageBlur": "rozmiar rozmycia obrazu",
"dynamicIsImage": "włącz obraz w tle", "dynamicIsImage": "włącz obraz w tle",
"lyricOffset": "opóźnienie tekstów (ms)" "lyricOffset": "opóźnienie tekstów (ms)",
"lyricOpacityNonActive": "przezroczystość nieaktywnego tekstu",
"lyricScaleNonActive": "skala nieaktywnego tekstu"
}, },
"upNext": "następne", "upNext": "następne",
"lyrics": "tekst", "lyrics": "tekst",
@@ -661,12 +680,22 @@
"restoreQueueFromServer": "przywróć kolejkę z serwera", "restoreQueueFromServer": "przywróć kolejkę z serwera",
"saveQueueToServer": "zapisz kolejkę na serwerze", "saveQueueToServer": "zapisz kolejkę na serwerze",
"artistRadio": "radio wykonawcy", "artistRadio": "radio wykonawcy",
"trackRadio": "radio utworu" "trackRadio": "radio utworu",
"sleepTimer": "wyłącznik czasowy",
"sleepTimer_endOfSong": "do końca aktualnej piosenki",
"sleepTimer_minutes": "{{count}} min",
"sleepTimer_hours": "{{count}} godz",
"sleepTimer_custom": "niestandardowy",
"sleepTimer_off": "wyłączony",
"sleepTimer_timeRemaining": "pozostało {{time}}",
"sleepTimer_setCustom": "ustaw wyłącznik",
"sleepTimer_cancel": "anuluj wyłączanie",
"albumRadio": "radio albumu"
}, },
"setting": { "setting": {
"crossfadeStyle_description": "wybierz styl przenikania, który ma być używany do odtwarzania dźwięku", "crossfadeStyle_description": "wybierz styl przenikania, który ma być używany do odtwarzania dźwięku",
"hotkey_skipBackward": "przeskocz do tyłu", "hotkey_skipBackward": "przeskocz do tyłu",
"audioDevice_description": "wybierz urządzenie dźwiękowe używane do odtwarzania (tylko odtwarzacz przeglądarkowy)", "audioDevice_description": "wybierz urządzenie dźwiękowe używane do odtwarzania",
"hotkey_playbackPause": "wstrzymaj", "hotkey_playbackPause": "wstrzymaj",
"hotkey_volumeUp": "podgłoś", "hotkey_volumeUp": "podgłoś",
"discordIdleStatus_description": "kiedy włączony, aktualizuje stan kiedy odtwarzacz jest bezczynny", "discordIdleStatus_description": "kiedy włączony, aktualizuje stan kiedy odtwarzacz jest bezczynny",
@@ -676,7 +705,7 @@
"hotkey_favoriteCurrentSong": "ulubiona $t(common.currentSong)", "hotkey_favoriteCurrentSong": "ulubiona $t(common.currentSong)",
"hotkey_zoomIn": "przybliż", "hotkey_zoomIn": "przybliż",
"hotkey_browserForward": "przeglądarka w przód", "hotkey_browserForward": "przeglądarka w przód",
"audioExclusiveMode_description": "włącz wyłączny tryb wyjścia. W tym trybie, system zwykle jest zablokowany i może odtwarzać tylko poprzez mpv", "audioExclusiveMode_description": "włącz wyłączny tryb wyjścia. W tym trybie, system zwykle jest zablokowany i może odtwarzać tylko poprzez mpv. wizualizer i przechwytywanie audio przez sysytem nie będzie działać gdy jest to włączone",
"discordUpdateInterval": "{{discord}} interwał aktualizacji rich presence", "discordUpdateInterval": "{{discord}} interwał aktualizacji rich presence",
"fontType_optionBuiltIn": "wbudowana czcionka", "fontType_optionBuiltIn": "wbudowana czcionka",
"hotkey_playbackPlayPause": "odtwarzaj / wstrzymaj", "hotkey_playbackPlayPause": "odtwarzaj / wstrzymaj",
@@ -894,7 +923,7 @@
"releaseChannel_optionBeta": "beta", "releaseChannel_optionBeta": "beta",
"releaseChannel_optionLatest": "najnowsza", "releaseChannel_optionLatest": "najnowsza",
"releaseChannel": "kanał wydań", "releaseChannel": "kanał wydań",
"releaseChannel_description": "wybieraj pomiędzy stabilnymi wydaniami a wydaniami beta dla automatycznych aktualizacji", "releaseChannel_description": "wybieraj pomiędzy wydaniami stabilnymi, beta lub alpha (nightly) dla automatycznych aktualizacji",
"discordDisplayType_artistname": "nazwa(y) wykonawców", "discordDisplayType_artistname": "nazwa(y) wykonawców",
"discordDisplayType_description": "zmienia co jest pokazywane jako słuchane w twoim statusie", "discordDisplayType_description": "zmienia co jest pokazywane jako słuchane w twoim statusie",
"discordDisplayType_songname": "nazwa piosenki", "discordDisplayType_songname": "nazwa piosenki",
@@ -1008,14 +1037,49 @@
"sidebarPlaylistListFilterRegex": "filtr playlist regex", "sidebarPlaylistListFilterRegex": "filtr playlist regex",
"blurExplicitImages": "rozmazuj nieodpowiednie obrazy", "blurExplicitImages": "rozmazuj nieodpowiednie obrazy",
"blurExplicitImages_description": "obrazy piosenek oraz albumów oznaczone jako nieodpowiednie będą rozmazywane", "blurExplicitImages_description": "obrazy piosenek oraz albumów oznaczone jako nieodpowiednie będą rozmazywane",
"releaseChannel_optionAlpha": "alpha (nightly)" "releaseChannel_optionAlpha": "alpha (nightly)",
"analyticsEnable": "Wysyłaj statystyki na podstawie użytkowania",
"analyticsEnable_description": "Zanonimizowane statystki użytkowania będą wysyłane do twórcy, aby pomóc w poprawie aplikacji",
"automaticUpdates": "Automatyczne aktualizacje",
"automaticUpdates_description": "Automatycznie sprawdzaj i instaluj aktualizacje",
"discordStateIcon": "pokaż ikonę odtwarzania",
"discordStateIcon_description": "pokazuje małą ikonę odtwarzania w statusie. ikona pauzy jest zawsze pokazywana gdy \"Pokaż status podczas pauzy\" jest włączone",
"useThemePrimaryShade": "użyj głównego odcienia motywu",
"useThemePrimaryShade_description": "używaj głównego odcienia zdefiniowanego w wybranym motywie dla głównych wariantów kolorów",
"primaryShade": "główny odcień",
"primaryShade_description": "nadpisz główny odcień (0-9) używany dla przycisków, linków i innych głównie pokolorowanych elementów",
"playerItemConfiguration_description": "skonfiguruj jakie elementy są pokazywane i w jakiej kolejności, w odtwarzaczu pełnoekranowym",
"playerItemConfiguration": "konfiguracja elementów odtwarzacza",
"autosave": "automatycznie zapisuj kolejkę odtwarzania",
"autosave_description": "włącz automatyczne zapisywanie kolejki odtwarzania na twój serwer. to jest możliwe tylko gdy używane jest Navidrome/Subsonic, i nie masz zmixowanej kolejki odtwarzania.",
"autosaveCount": "częstotliwość automatycznego zapisywania kolejki odtwarzania",
"autosaveCount_description": "ile razy piosenka zostanie zmieniona przed zapisaniem kolejki. 1 (najmniejsze) oznacza zapisywanie kolejki po każdej zmianie piosenki",
"listenbrainz_description": "pokaż linki do ListenBrainz na stronach wykonawców/albumów",
"listenbrainz": "pokaż linki ListenBrainz",
"qobuz_description": "pokaż linki do Qobuz na stronach wykonawców/albumów",
"qobuz": "pokaż linki Qobuz",
"spotify_description": "pokaż linki do Spotify na stronach wykonawców/albumów",
"spotify": "pokaż linki Spotify",
"nativeSpotify_description": "otwieraj w aplikacji Spotify zamiast w twojej przeglądarce",
"nativeSpotify": "używaj aplikacji Spotify",
"sidePlayQueueLayout": "układ boczny kolejki odtwarzania",
"sidePlayQueueLayout_description": "ustawia układ przyczepionej z boku kolejki odtwarzania",
"sidePlayQueueLayout_optionHorizontal": "poziomy",
"sidePlayQueueLayout_optionVertical": "pionowy",
"waveformLoadingDelay": "opóźnienie załadowania fali",
"waveformLoadingDelay_description": "opóźnienie w sekundach przed załadowaniem fali. zwiększ tą wartość jeżeli doświadczasz zawieszania się odtwarzacza przeglądarkowego.",
"playerbarWaveformStretch": "rozciąganie przebiegu",
"playerbarWaveformStretch_description": "rozciąga przebieg aby wypełnić dostępną przestrzeń",
"preventSuspendOnPlayback_description": "powstrzymuj wstrzymanie podczas odtwarzania muzyki",
"preventSuspendOnPlayback": "powstrzymuje wstrzymanie przy odtwarzaniu"
}, },
"table": { "table": {
"config": { "config": {
"view": { "view": {
"table": "tabela", "table": "tabela",
"grid": "siatka", "grid": "siatka",
"list": "lista" "list": "lista",
"detail": "szczegół"
}, },
"general": { "general": {
"displayType": "typ wyświetlania", "displayType": "typ wyświetlania",
@@ -1084,7 +1148,8 @@
"bitDepth": "$t(common.bitDepth)", "bitDepth": "$t(common.bitDepth)",
"sampleRate": "$t(common.sampleRate)", "sampleRate": "$t(common.sampleRate)",
"composer": "kompozytor", "composer": "kompozytor",
"titleArtist": "$t(common.title) (wykonawca)" "titleArtist": "$t(common.title) (wykonawca)",
"albumGroup": "grupa albumu"
} }
}, },
"column": { "column": {
@@ -1323,6 +1388,13 @@
}, },
"pasteGradient": "Wklej Gradient", "pasteGradient": "Wklej Gradient",
"pasteGradientPlaceholder": "Wklej tutaj JSON gradientu...", "pasteGradientPlaceholder": "Wklej tutaj JSON gradientu...",
"ansiBands": "Paski ANSI" "ansiBands": "Paski ANSI",
"systemAudioConsentAllow": "Zezwól",
"systemAudioConsentBody": "Wizualizer wymaga dostępu do audio systemu do działania",
"systemAudioConsentDecline": "Odmów",
"systemAudioConsentTitle": "Przyznać dostęp do audio systemu?",
"systemAudioCaptureFailed": "Nie udało się rozpocząć przechwytywania: {{message}}",
"systemAudioNoAudioTrack": "Nie została zwrócona żadna ścieżka audio. Sprawdź czy przechwytywanie audio będzie włączone, gdy będzie o to prośba.",
"systemAudioExclusiveModeNotSupported": "Wizualizer jest niedostępny w gdy tryb wyłącznie z dźwiękiek jest włączony. Wyłącz tryb wyłącznie audio w ustawieniach MPV i spróbuj ponownie."
} }
} }
+15 -3
View File
@@ -84,13 +84,14 @@
"size": "tamanho", "size": "tamanho",
"note": "observação", "note": "observação",
"mbid": "ID no MusicBrainz", "mbid": "ID no MusicBrainz",
"grouping": "agrupamento",
"reload": "recarregar", "reload": "recarregar",
"codec": "codec", "codec": "codec",
"preview": "pré-visualizar", "preview": "pré-visualizar",
"share": "compartilhar", "share": "compartilhar",
"close": "fechar", "close": "fechar",
"translation": "tradução", "translation": "tradução",
"albumGain": "ganho do album", "albumGain": "ganho do álbum",
"trackPeak": "peak da faixa", "trackPeak": "peak da faixa",
"albumPeak": "pico do álbum", "albumPeak": "pico do álbum",
"trackGain": "ganho da faixa", "trackGain": "ganho da faixa",
@@ -120,10 +121,21 @@
"removeFromFavorites": "remover de $t(entity.favorite, {\"count\": 2})", "removeFromFavorites": "remover de $t(entity.favorite, {\"count\": 2})",
"openIn": { "openIn": {
"lastfm": "Abrir em Last.fm", "lastfm": "Abrir em Last.fm",
"musicbrainz": "Abrir em MusicBrainz" "musicbrainz": "Abrir em MusicBrainz",
"listenbrainz": "Abrir no ListenBrainz",
"qobuz": "Abrir no Qobuz"
}, },
"toggleSmartPlaylistEditor": "alternar editor $t(entity.smartPlaylist)", "toggleSmartPlaylistEditor": "alternar editor $t(entity.smartPlaylist)",
"moveToNext": "mover para o próximo" "moveToNext": "mover para o próximo",
"addOrRemoveFromSelection": "adicionar ou remover da seleção",
"goToCurrent": "ir para o item atual",
"createRadioStation": "criar $t(entity.radioStation, {\"count\": 1})",
"deleteRadioStation": "deletar $t(entity.radioStation, {\"count\": 1})",
"selectAll": "selecionar tudo",
"holdToMoveToTop": "segure para ir ao topo",
"moveItems": "mover itens",
"viewMore": "ver mais",
"openApplicationDirectory": "abrir a pasta do aplicativo"
}, },
"form": { "form": {
"deletePlaylist": { "deletePlaylist": {
+1
View File
@@ -72,6 +72,7 @@
"forceRestartRequired": "reinicie para aplicar as alterações… feche a notificação para reiniciar", "forceRestartRequired": "reinicie para aplicar as alterações… feche a notificação para reiniciar",
"forward": "para frente", "forward": "para frente",
"gap": "intervalo", "gap": "intervalo",
"grouping": "agrupamento",
"home": "início", "home": "início",
"increase": "incrementar", "increase": "incrementar",
"left": "esquerda", "left": "esquerda",
+246 -82
View File
@@ -18,26 +18,30 @@
"toggleSmartPlaylistEditor": "вкл./откл. редактор $t(entity.smartPlaylist)", "toggleSmartPlaylistEditor": "вкл./откл. редактор $t(entity.smartPlaylist)",
"removeFromFavorites": "удалить из $t(entity.favorite, {\"count\": 2})", "removeFromFavorites": "удалить из $t(entity.favorite, {\"count\": 2})",
"openIn": { "openIn": {
"lastfm": "открыть на Last.fm", "lastfm": "Открыть на Last.fm",
"musicbrainz": "открыть на MusicBrainz" "musicbrainz": "открыть на MusicBrainz",
"listenbrainz": "Открыть на ListenBrainz",
"qobuz": "Открыть в Qobuz",
"spotify": "Открыть в Spotify"
}, },
"moveToNext": "следующий", "moveToNext": "следующий",
"addOrRemoveFromSelection": "добавить или удалить из выделения", "addOrRemoveFromSelection": "добавить или удалить из выделения",
"createRadioStation": "создать $t(entity.radioStation, {\"count\": 1})", "createRadioStation": "создать $t(entity.radioStation, {\"count\": 1})",
"deleteRadioStation": "удалить $t(entity.radioStation, {\"count\": 1})", "deleteRadioStation": "удалить $t(entity.radioStation, {\"count\": 1})",
"selectAll": "выделить все", "selectAll": "выбрать все",
"downloadStarted": "Начата загрузка {{count}} предметов", "downloadStarted": "Начата загрузка {{count}} предметов",
"moveUp": "перейти наверх", "moveUp": "перейти вверх",
"moveDown": "Перейти вниз", "moveDown": "перейти вниз",
"holdToMoveToTop": "Удержать для перехода на верх", "holdToMoveToTop": "Удержать для перехода на верх",
"holdToMoveToBottom": "удержать для перехода вниз", "holdToMoveToBottom": "удержать для перехода вниз",
"moveItems": "переместить предметы", "moveItems": "переместить элементы",
"shuffle": "Перемешать", "shuffle": "Перемешать",
"shuffleAll": "перемешать все", "shuffleAll": "перемешать все",
"shuffleSelected": "Смешать выбранное", "shuffleSelected": "перемешать выбранные",
"viewMore": "Посмотреть больше", "viewMore": "Посмотреть больше",
"openApplicationDirectory": "открыть папку приложения", "openApplicationDirectory": "открыть папку приложения",
"selectRangeOfItems": "выбрать диапазон элементов" "selectRangeOfItems": "выбрать диапазон элементов",
"goToCurrent": "перейти к текущему элементу"
}, },
"common": { "common": {
"backward": "назад", "backward": "назад",
@@ -125,6 +129,7 @@
"note": "заметка", "note": "заметка",
"none": "нет", "none": "нет",
"mbid": "MusicBrainz ID", "mbid": "MusicBrainz ID",
"grouping": "группировка",
"reload": "перезагрузить", "reload": "перезагрузить",
"preview": "просмотр", "preview": "просмотр",
"codec": "кодек", "codec": "кодек",
@@ -136,7 +141,7 @@
"albumPeak": "пик альбома", "albumPeak": "пик альбома",
"trackPeak": "пик трека", "trackPeak": "пик трека",
"additionalParticipants": "Другие участники", "additionalParticipants": "Другие участники",
"newVersion": "новая версия приложения установлена ({{version}})", "newVersion": "установлена новая версия ({{version}})",
"viewReleaseNotes": "Список изменений", "viewReleaseNotes": "Список изменений",
"bitDepth": "Разрядность", "bitDepth": "Разрядность",
"sampleRate": "частота дискретизации", "sampleRate": "частота дискретизации",
@@ -163,7 +168,10 @@
"example": "пример", "example": "пример",
"rename": "переименовать", "rename": "переименовать",
"explicit": "нецензурная лексика", "explicit": "нецензурная лексика",
"externalLinks": "внешние ссылки" "externalLinks": "внешние ссылки",
"explicitStatus": "признак нецензурного контента",
"newVersionAvailable": "доступна новая версия",
"numberOfResults": "{{numberOfResults}} результатов"
}, },
"entity": { "entity": {
"album_one": "альбом", "album_one": "альбом",
@@ -182,8 +190,8 @@
"play_one": "{{count}} прослушивание", "play_one": "{{count}} прослушивание",
"play_few": "{{count}} прослушивание", "play_few": "{{count}} прослушивание",
"play_many": "{{count}} прослушивание", "play_many": "{{count}} прослушивание",
"artist_one": "автор", "artist_one": "исполнитель",
"artist_few": "автора", "artist_few": "исполнителя",
"artist_many": "исполнителей", "artist_many": "исполнителей",
"folderWithCount_one": "{{count}} папка", "folderWithCount_one": "{{count}} папка",
"folderWithCount_few": "{{count}} папки", "folderWithCount_few": "{{count}} папки",
@@ -203,9 +211,9 @@
"albumWithCount_one": "{{count}} альбом", "albumWithCount_one": "{{count}} альбом",
"albumWithCount_few": "{{count}} альбома", "albumWithCount_few": "{{count}} альбома",
"albumWithCount_many": "{{count}} альбомов", "albumWithCount_many": "{{count}} альбомов",
"favorite_one": "любимый", "favorite_one": "избранное",
"favorite_few": "любимых", "favorite_few": "избранное",
"favorite_many": "любимые", "favorite_many": "избранные",
"artistWithCount_one": "{{count}} автор", "artistWithCount_one": "{{count}} автор",
"artistWithCount_few": "{{count}} автора", "artistWithCount_few": "{{count}} автора",
"artistWithCount_many": "{{count}} авторов", "artistWithCount_many": "{{count}} авторов",
@@ -222,9 +230,9 @@
"radioStation_one": "радиостанция", "radioStation_one": "радиостанция",
"radioStation_few": "радиостанции", "radioStation_few": "радиостанции",
"radioStation_many": "радиостанции", "radioStation_many": "радиостанции",
"radioStationWithCount_one": "Радиостанция", "radioStationWithCount_one": "{{count}} радиостанция",
"radioStationWithCount_few": "Радиостанций", "radioStationWithCount_few": "{{count}} радиостанции",
"radioStationWithCount_many": "Радиостанции" "radioStationWithCount_many": "{{count}} радиостанций"
}, },
"table": { "table": {
"config": { "config": {
@@ -253,8 +261,6 @@
"trackNumber": "номер трека", "trackNumber": "номер трека",
"rowIndex": "номер строки", "rowIndex": "номер строки",
"rating": "$t(common.rating)", "rating": "$t(common.rating)",
"artist": "$t(entity.artist, {\"count\": 1})",
"album": "$t(entity.album, {\"count\": 1})",
"note": "$t(common.note)", "note": "$t(common.note)",
"biography": "$t(common.biography)", "biography": "$t(common.biography)",
"owner": "$t(common.owner)", "owner": "$t(common.owner)",
@@ -263,13 +269,10 @@
"playCount": "количество воспроизведений", "playCount": "количество воспроизведений",
"bitrate": "$t(common.bitrate)", "bitrate": "$t(common.bitrate)",
"actions": "$t(common.action_other)", "actions": "$t(common.action_other)",
"genre": "$t(entity.genre, {\"count\": 1})",
"discNumber": "номер диска", "discNumber": "номер диска",
"favorite": "$t(common.favorite)", "favorite": "$t(common.favorite)",
"year": "$t(common.year)", "year": "$t(common.year)",
"albumArtist": "$t(entity.albumArtist, {\"count\": 1})",
"codec": "$t(common.codec)", "codec": "$t(common.codec)",
"songCount": "$t(entity.track, {\"count\": 2})",
"titleArtist": "$t(common.title) (артист)" "titleArtist": "$t(common.title) (артист)"
} }
}, },
@@ -281,9 +284,7 @@
"lastPlayed": "последний", "lastPlayed": "последний",
"releaseDate": "дата выхода", "releaseDate": "дата выхода",
"title": "название", "title": "название",
"songCount": "$t(entity.track, {\"count\": 2})",
"trackNumber": "трек", "trackNumber": "трек",
"genre": "$t(entity.genre, {\"count\": 1})",
"path": "путь", "path": "путь",
"discNumber": "диск", "discNumber": "диск",
"size": "$t(common.size)", "size": "$t(common.size)",
@@ -293,8 +294,6 @@
"biography": "биография", "biography": "биография",
"codec": "$t(common.codec)", "codec": "$t(common.codec)",
"comment": "комментарий", "comment": "комментарий",
"albumCount": "$t(entity.album, {\"count\": 2})",
"artist": "$t(entity.artist, {\"count\": 1})",
"bitrate": "битрейт", "bitrate": "битрейт",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel_other)",
"bpm": "bpm" "bpm": "bpm"
@@ -308,7 +307,7 @@
"remotePortError": "произошла ошибка при попытке установить порт удаленного сервера", "remotePortError": "произошла ошибка при попытке установить порт удаленного сервера",
"serverRequired": "сервер не выбран", "serverRequired": "сервер не выбран",
"authenticationFailed": "не удалось авторизироваться", "authenticationFailed": "не удалось авторизироваться",
"apiRouteError": "невозможно выполнить запрос", "apiRouteError": "не удалось выполнить запрос",
"genericError": "произошла ошибка", "genericError": "произошла ошибка",
"credentialsRequired": "введите данные для входа", "credentialsRequired": "введите данные для входа",
"sessionExpiredError": "ваш сеанс истёк", "sessionExpiredError": "ваш сеанс истёк",
@@ -329,7 +328,10 @@
"noNetwork": "сервер недоступен", "noNetwork": "сервер недоступен",
"noNetworkDescription": "Не удалось подключиться к серверу", "noNetworkDescription": "Не удалось подключиться к серверу",
"saveQueueFailed": "Не удалось сохранить очередь", "saveQueueFailed": "Не удалось сохранить очередь",
"settingsSyncError": "обнаружены несоответствия между настройками рендерера и основным процессом. перезапустите приложение, чтобы изменения вступили в силу" "settingsSyncError": "обнаружены несоответствия между настройками рендерера и основным процессом. перезапустите приложение, чтобы изменения вступили в силу",
"invalidJson": "невалидный JSON",
"serverLockSingleServer": "при заблокированном сервере разрешается использовать только один сервер",
"playbackPausedDueToError": "воспроизведение было приостановлено из-за ошибки"
}, },
"filter": { "filter": {
"isCompilation": "сборник", "isCompilation": "сборник",
@@ -338,12 +340,10 @@
"dateAdded": "дата добавления", "dateAdded": "дата добавления",
"communityRating": "рейтинг сообщества", "communityRating": "рейтинг сообщества",
"favorited": "любимый", "favorited": "любимый",
"albumArtist": "$t(entity.albumArtist, {\"count\": 1})",
"isFavorited": "любимые", "isFavorited": "любимые",
"bpm": "уд./мин.", "bpm": "уд./мин.",
"disc": "диск", "disc": "диск",
"biography": "биография", "biography": "биография",
"artist": "$t(entity.artist, {\"count\": 1})",
"duration": "длительность", "duration": "длительность",
"fromYear": "год", "fromYear": "год",
"criticRating": "рейтинг критиков", "criticRating": "рейтинг критиков",
@@ -351,13 +351,11 @@
"comment": "комментировать", "comment": "комментировать",
"playCount": "количество воспроизведений", "playCount": "количество воспроизведений",
"recentlyUpdated": "обновленные недавно", "recentlyUpdated": "обновленные недавно",
"channels": "$t(common.channel_other)",
"recentlyPlayed": "проигрывались недавно", "recentlyPlayed": "проигрывались недавно",
"owner": "$t(common.owner)", "owner": "$t(common.owner)",
"title": "название", "title": "название",
"rating": "рейтинг", "rating": "рейтинг",
"search": "поиск", "search": "поиск",
"genre": "$t(entity.genre, {\"count\": 1})",
"recentlyAdded": "недавно добавленные", "recentlyAdded": "недавно добавленные",
"note": "заметка", "note": "заметка",
"name": "название", "name": "название",
@@ -373,7 +371,15 @@
"lastPlayed": "последний раз проигрывалась", "lastPlayed": "последний раз проигрывалась",
"toYear": "до года", "toYear": "до года",
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
"trackNumber": "трек" "trackNumber": "трек",
"matchAnd": "и",
"matchOr": "или",
"sortName": "сортировка по имени",
"albumArtist": "$t(entity.albumArtist, {\"count\": 1})",
"artist": "$t(entity.artist, {\"count\": 1})",
"channels": "$t(common.channel, {\"count\": 2})",
"genre": "$t(entity.genre, {\"count\": 1})",
"explicitStatus": "$t(common.explicitStatus)"
}, },
"player": { "player": {
"repeat_all": "повторять все", "repeat_all": "повторять все",
@@ -399,7 +405,7 @@
"pause": "пауза", "pause": "пауза",
"queue_clear": "очистить очередь", "queue_clear": "очистить очередь",
"muted": "звук отключён", "muted": "звук отключён",
"unfavorite": "убрать из любимых", "unfavorite": "убрать из избранного",
"queue_moveToTop": "переместить выделенное вниз", "queue_moveToTop": "переместить выделенное вниз",
"queue_moveToBottom": "переместить выделенное вверх", "queue_moveToBottom": "переместить выделенное вверх",
"shuffle_off": "перемешивание выключено", "shuffle_off": "перемешивание выключено",
@@ -414,24 +420,36 @@
"lyrics": "тексты песен", "lyrics": "тексты песен",
"restoreQueueFromServer": "восстановить очередь с сервера", "restoreQueueFromServer": "восстановить очередь с сервера",
"saveQueueToServer": "сохранить очередь на сервер", "saveQueueToServer": "сохранить очередь на сервер",
"trackRadio": "трек радио" "trackRadio": "трек радио",
"albumRadio": "Радио по альбому",
"sleepTimer": "таймер сна",
"sleepTimer_endOfSong": "конец текущей песни",
"sleepTimer_minutes": "{{count}} минут",
"sleepTimer_hours": "{{count}} часов",
"sleepTimer_off": "выключено",
"sleepTimer_timeRemaining": "{{time}} осталось",
"sleepTimer_setCustom": "установить таймер",
"sleepTimer_custom": "пользовательский",
"sleepTimer_cancel": "отменить таймер"
}, },
"page": { "page": {
"sidebar": { "sidebar": {
"nowPlaying": "сейчас играет", "nowPlaying": "сейчас играет",
"playlists": "$t(entity.playlist, {\"count\": 2})",
"search": "$t(common.search)", "search": "$t(common.search)",
"tracks": "$t(entity.track, {\"count\": 2})",
"albums": "$t(entity.album, {\"count\": 2})",
"genres": "$t(entity.genre, {\"count\": 2})",
"folders": "$t(entity.folder, {\"count\": 2})",
"settings": "$t(common.setting, {\"count\": 2})",
"home": "$t(common.home)", "home": "$t(common.home)",
"artists": "$t(entity.artist, {\"count\": 2})",
"albumArtists": "$t(entity.albumArtist, {\"count\": 2})",
"myLibrary": "Моя библиотека", "myLibrary": "Моя библиотека",
"shared": "Публичные плейлисты $t(entity.playlist, {\"count\": 2})", "shared": "Публичные плейлисты $t(entity.playlist, {\"count\": 2})",
"collections": "коллекции" "collections": "коллекции",
"albumArtists": "$t(entity.albumArtist, {\"count\": 2})",
"albums": "$t(entity.album, {\"count\": 2})",
"artists": "$t(entity.artist, {\"count\": 2})",
"favorites": "$t(entity.favorite, {\"count\": 2})",
"folders": "$t(entity.folder, {\"count\": 2})",
"genres": "$t(entity.genre, {\"count\": 2})",
"radio": "$t(entity.radioStation, {\"count\": 2})",
"playlists": "$t(entity.playlist, {\"count\": 2})",
"settings": "$t(common.setting, {\"count\": 2})",
"tracks": "$t(entity.track, {\"count\": 2})"
}, },
"fullscreenPlayer": { "fullscreenPlayer": {
"config": { "config": {
@@ -448,7 +466,9 @@
"useImageAspectRatio": "использовать соотношение сторон изображения", "useImageAspectRatio": "использовать соотношение сторон изображения",
"lyricGap": "пробел между словами", "lyricGap": "пробел между словами",
"dynamicIsImage": "включить фоновое изображение", "dynamicIsImage": "включить фоновое изображение",
"dynamicImageBlur": "сила размытия изображения" "dynamicImageBlur": "сила размытия изображения",
"lyricOpacityNonActive": "непрозрачность неактивных слов",
"lyricScaleNonActive": "размер неактивных слов"
}, },
"upNext": "играет", "upNext": "играет",
"lyrics": "слова", "lyrics": "слова",
@@ -459,7 +479,6 @@
"appMenu": { "appMenu": {
"selectServer": "список серверов", "selectServer": "список серверов",
"version": "версия {{version}}", "version": "версия {{version}}",
"settings": "$t(common.setting, {\"count\": 2})",
"manageServers": "редактировать список серверов", "manageServers": "редактировать список серверов",
"expandSidebar": "развернуть боковую панель", "expandSidebar": "развернуть боковую панель",
"collapseSidebar": "Скрыть боковую панель", "collapseSidebar": "Скрыть боковую панель",
@@ -472,7 +491,8 @@
"selectMusicFolder": "выбрать папку с музыкой", "selectMusicFolder": "выбрать папку с музыкой",
"noMusicFolder": "папка с музыкой не выбрана", "noMusicFolder": "папка с музыкой не выбрана",
"multipleMusicFolders": "{{count}} выбрано музыкальных папок", "multipleMusicFolders": "{{count}} выбрано музыкальных папок",
"commandPalette": "открыть командную строку" "commandPalette": "открыть командную строку",
"settings": "$t(common.setting, {\"count\": 2})"
}, },
"manageServers": { "manageServers": {
"title": "сервера", "title": "сервера",
@@ -504,7 +524,11 @@
"shareItem": "поделиться", "shareItem": "поделиться",
"goToAlbum": "Перейти к $t(entity.album, {\"count\": 1})", "goToAlbum": "Перейти к $t(entity.album, {\"count\": 1})",
"goToAlbumArtist": "Перейти к $t(entity.albumArtist, {\"count\": 1})", "goToAlbumArtist": "Перейти к $t(entity.albumArtist, {\"count\": 1})",
"goTo": "перейти в" "goTo": "перейти в",
"moveToNext": "$t(action.moveToNext)",
"playShuffled": "$t(player.shuffle)",
"moveItems": "$t(action.moveItems)",
"playSimilarSongs": "$t(player.playSimilarSongs)"
}, },
"home": { "home": {
"mostPlayed": "слушают чаще всего", "mostPlayed": "слушают чаще всего",
@@ -512,7 +536,8 @@
"title": "$t(common.home)", "title": "$t(common.home)",
"explore": "откройте новое", "explore": "откройте новое",
"recentlyPlayed": "игралось недавно", "recentlyPlayed": "игралось недавно",
"recentlyReleased": "Новинки" "recentlyReleased": "Новинки",
"genres": "$t(entity.genre, {\"count\": 2})"
}, },
"albumDetail": { "albumDetail": {
"moreFromArtist": "больше от $t(entity.artist, {\"count\": 1})", "moreFromArtist": "больше от $t(entity.artist, {\"count\": 1})",
@@ -540,20 +565,19 @@
"transcoding": "транскодирование", "transcoding": "транскодирование",
"scrobble": "скробблер", "scrobble": "скробблер",
"logger": "Отладка", "logger": "Отладка",
"playerFilters": "фильтры проигрывателя" "playerFilters": "фильтры проигрывателя",
}, "queryBuilder": "конструктор очереди",
"albumArtistList": { "discord": "дискорд"
"title": "$t(entity.albumArtist, {\"count\": 2})"
}, },
"genreList": { "genreList": {
"title": "$t(entity.genre, {\"count\": 2})",
"showAlbums": "показать $t(entity.genre, {\"count\": 1}) $t(entity.album, {\"count\": 2})", "showAlbums": "показать $t(entity.genre, {\"count\": 1}) $t(entity.album, {\"count\": 2})",
"showTracks": "показать $t(entity.genre, {\"count\": 1}) $t(entity.track, {\"count\": 2})" "showTracks": "показать $t(entity.genre, {\"count\": 1}) $t(entity.track, {\"count\": 2})",
"title": "$t(entity.genre, {\"count\": 2})"
}, },
"trackList": { "trackList": {
"title": "$t(entity.track, {\"count\": 2})", "artistTracks": "Треки {{artist}}",
"genreTracks": "\"{{genre}}\" $t(entity.track, {\"count\": 2})", "genreTracks": "\"{{genre}}\" $t(entity.track, {\"count\": 2})",
"artistTracks": "Треки {{artist}}" "title": "$t(entity.track, {\"count\": 2})"
}, },
"globalSearch": { "globalSearch": {
"commands": { "commands": {
@@ -566,13 +590,10 @@
"playlist": { "playlist": {
"reorder": "сортировка доступна только по ID" "reorder": "сортировка доступна только по ID"
}, },
"playlistList": {
"title": "$t(entity.playlist, {\"count\": 2})"
},
"albumList": { "albumList": {
"title": "$t(entity.album, {\"count\": 2})",
"artistAlbums": "альбомы {{artist}}", "artistAlbums": "альбомы {{artist}}",
"genreAlbums": "\"{{genre}}\" $t(entity.album, {\"count\": 2})" "genreAlbums": "\"{{genre}}\"\n$t(entity.album, {\"count\": 2})",
"title": "$t(entity.album, {\"count\": 2})"
}, },
"albumArtistDetail": { "albumArtistDetail": {
"topSongs": "популярные треки", "topSongs": "популярные треки",
@@ -585,7 +606,11 @@
"about": "О {{artist}}", "about": "О {{artist}}",
"topSongsFrom": "популярные треки из {{title}}", "topSongsFrom": "популярные треки из {{title}}",
"groupingTypeAll": "все типы выпусков", "groupingTypeAll": "все типы выпусков",
"groupingTypePrimary": "основные типы выпусков" "groupingTypePrimary": "основные типы выпусков",
"favoriteSongs": "любимые треки",
"topSongsCommunity": "сообщество",
"topSongsPersonal": "личное",
"favoriteSongsFrom": "любимые треки от {{title}}"
}, },
"itemDetail": { "itemDetail": {
"copyPath": "скопировать путь в буфер обмена", "copyPath": "скопировать путь в буфер обмена",
@@ -596,10 +621,29 @@
"title": "радиостанции" "title": "радиостанции"
}, },
"windowBar": { "windowBar": {
"privateMode": "(Режим приватности)" "privateMode": "(Режим приватности)",
"paused": "(Приостановлено) "
}, },
"collections": { "collections": {
"saveAsCollection": "сохранить коллекцией" "saveAsCollection": "сохранить коллекцией",
"overrideExisting": "переопределить существующий"
},
"releasenotes": {
"commitsSinceStable": "коммито после {{stable}}",
"noStableReleaseToCompare": "нет стабильной версии, с которой можно было бы сравнить",
"noNewCommits": "изменения в этом диапазоне отсутствуют"
},
"albumArtistList": {
"title": "$t(entity.albumArtist, {\"count\": 2})"
},
"favorites": {
"title": "$t(entity.favorite, {\"count\": 2})"
},
"folderList": {
"title": "$t(entity.folder, {\"count\": 2})"
},
"playlistList": {
"title": "$t(entity.playlist, {\"count\": 2})"
} }
}, },
"form": { "form": {
@@ -638,9 +682,10 @@
"success": "добавлено: $t(entity.trackWithCount, {\"count\": {{message}} }) в $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} })", "success": "добавлено: $t(entity.trackWithCount, {\"count\": {{message}} }) в $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} })",
"title": "добавить в $t(entity.playlist, {\"count\": 1})", "title": "добавить в $t(entity.playlist, {\"count\": 1})",
"input_skipDuplicates": "не добавлять дубликаты", "input_skipDuplicates": "не добавлять дубликаты",
"input_playlists": "$t(entity.playlist, {\"count\": 2})",
"create": "создать $t(entity.playlist, {\"count\": 1}) {{playlist}}", "create": "создать $t(entity.playlist, {\"count\": 1}) {{playlist}}",
"searchOrCreate": "для создания нового списка выполните поиск по $t(entity.playlist, {\"count\": 2}) или введите соответствующий текст" "searchOrCreate": "для создания нового списка выполните поиск по $t(entity.playlist, {\"count\": 2}) или введите соответствующий текст",
"input_playlists": "$t(entity.playlist, {\"count\": 2})",
"noneAdded": "в плейлист $t(entity.playlist, {\"count\": 1}) '{{playlist}}' не было добавлено ни одного трека"
}, },
"updateServer": { "updateServer": {
"title": "обновление сервера", "title": "обновление сервера",
@@ -657,14 +702,13 @@
}, },
"lyricSearch": { "lyricSearch": {
"input_name": "$t(common.name)", "input_name": "$t(common.name)",
"input_artist": "$t(entity.artist, {\"count\": 1})", "title": "поиск слов песни",
"title": "поиск слов песни" "input_artist": "$t(entity.artist, {\"count\": 1})"
}, },
"editPlaylist": { "editPlaylist": {
"title": "редактировать $t(entity.playlist, {\"count\": 1})", "title": "редактировать $t(entity.playlist, {\"count\": 1})",
"success": "$t(entity.playlist, {\"count\": 1}) обновлён успешно", "success": "$t(entity.playlist, {\"count\": 1}) обновлён успешно",
"publicJellyfinNote": "Jellyfin по какой-то причине не предоставляет информацию о том, публичный плейлист или нет. Если вы хотите, чтобы он остался публичным, выберите следующую опцию", "publicJellyfinNote": "Jellyfin по какой-то причине не предоставляет информацию о том, публичный плейлист или нет. Если вы хотите, чтобы он остался публичным, выберите следующую опцию"
"editNote": "редактирование больших плейлистов вручную не рекомендуется. Вы уверены, что готовы принять риск потери данных, который может возникнуть в результате перезаписи существующего плейлиста?"
}, },
"shareItem": { "shareItem": {
"success": "ссылка скопирована в буфер обмена (нажмите здесь, чтобы открыть)", "success": "ссылка скопирована в буфер обмена (нажмите здесь, чтобы открыть)",
@@ -672,7 +716,9 @@
"createFailed": "не удалось создать ссылку для общего доступа (проверьте, включен ли общий доступ?)", "createFailed": "не удалось создать ссылку для общего доступа (проверьте, включен ли общий доступ?)",
"allowDownloading": "разрешить скачивание", "allowDownloading": "разрешить скачивание",
"setExpiration": "установить срок действия", "setExpiration": "установить срок действия",
"description": "описание" "description": "описание",
"copyToClipboard": "Скопировано в буфер обмена: Ctrl+C, Enter",
"successMustClick": "Ссылка создана успешо. Нажимите, чтобы окрыть"
}, },
"privateMode": { "privateMode": {
"enabled": "Приватный режим включен. Статус воспроизведения скрыт от внешних интеграций", "enabled": "Приватный режим включен. Статус воспроизведения скрыт от внешних интеграций",
@@ -706,7 +752,11 @@
"input_played": "воспроизвести фильтр", "input_played": "воспроизвести фильтр",
"input_played_optionAll": "все треки", "input_played_optionAll": "все треки",
"input_played_optionUnplayed": "только не игранные треки", "input_played_optionUnplayed": "только не игранные треки",
"input_played_optionPlayed": "только игранные треки" "input_played_optionPlayed": "только воспроизведённые треки",
"input_genre": "$t(entity.genre, {\"count\": 1})"
},
"editRadioStation": {
"success": "радиостанция успешно обновлена"
} }
}, },
"setting": { "setting": {
@@ -745,7 +795,7 @@
"clearCache": "очистить кэш браузера", "clearCache": "очистить кэш браузера",
"clearQueryCache": "очистить кэш feishin", "clearQueryCache": "очистить кэш feishin",
"audioDevice": "устройство воспроизведения", "audioDevice": "устройство воспроизведения",
"audioDevice_description": "выберите устройство воспроизведения (только в режиме аудиоплеера web)", "audioDevice_description": "выберите устройство воспроизведения",
"buttonSize": "размер кнопок панели управления воспроизведением", "buttonSize": "размер кнопок панели управления воспроизведением",
"hotkey_volumeDown": "уменьшить громкость", "hotkey_volumeDown": "уменьшить громкость",
"playButtonBehavior_optionAddLast": "$t(player.addLast)", "playButtonBehavior_optionAddLast": "$t(player.addLast)",
@@ -759,9 +809,7 @@
"hotkey_zoomOut": "уменьшить масштаб", "hotkey_zoomOut": "уменьшить масштаб",
"playbackStyle_optionCrossFade": "затухание", "playbackStyle_optionCrossFade": "затухание",
"replayGainMode": "режим {{ReplayGain}}", "replayGainMode": "режим {{ReplayGain}}",
"replayGainMode_optionAlbum": "$t(entity.album, {\"count\": 1})",
"replayGainMode_optionNone": "$t(common.none)", "replayGainMode_optionNone": "$t(common.none)",
"replayGainMode_optionTrack": "$t(entity.track, {\"count\": 1})",
"clearQueryCache_description": "так называемая \"мягкая очистка\" feishin: обновляются плейлисты, метаданные треков, но сохранённые тексты треков сбрасываются. настройки, учётные данные и кэшированные изображения сохраняются", "clearQueryCache_description": "так называемая \"мягкая очистка\" feishin: обновляются плейлисты, метаданные треков, но сохранённые тексты треков сбрасываются. настройки, учётные данные и кэшированные изображения сохраняются",
"hotkey_favoriteCurrentSong": "добавить $t(common.currentSong) в избранное", "hotkey_favoriteCurrentSong": "добавить $t(common.currentSong) в избранное",
"globalMediaHotkeys": "глобальные мультимедийные горячие клавиши", "globalMediaHotkeys": "глобальные мультимедийные горячие клавиши",
@@ -922,11 +970,123 @@
"releaseChannel_optionBeta": "Бета", "releaseChannel_optionBeta": "Бета",
"releaseChannel_optionLatest": "последний", "releaseChannel_optionLatest": "последний",
"releaseChannel": "Тип релиза", "releaseChannel": "Тип релиза",
"releaseChannel_description": "Выберите между стабильной или бета версией для автоматического обновления", "releaseChannel_description": "Выберите между стабильной, бета или альфа (ночной) версией для автоматического обновления",
"discordDisplayType_artistname": "Имя (имена) исполнителя", "discordDisplayType_artistname": "Имя (имена) исполнителя",
"discordDisplayType_description": "это меняет то, что вы слушаете в своем статусе", "discordDisplayType_description": "это меняет то, что вы слушаете в своем статусе",
"discordDisplayType_songname": "имя песни", "discordDisplayType_songname": "имя песни",
"discordDisplayType": "{{discord}} тип отображения" "discordDisplayType": "{{discord}} тип отображения",
"autosave": "автоматическое сохранение очереди воспроизведения",
"autosave_description": "включите автоматическое сохранение очереди воспроизведения на вашем сервере. это возможно только при использовании Navidrome/Subsonic, и у вас не может быть смешанной очереди воспроизведения.",
"autosaveCount_description": "количество изменений трека перед сохранением очереди. 1 (минимум) означает каждое изменение песни",
"useThemePrimaryShade": "используйте основной оттенок темы",
"useThemePrimaryShade_description": "используйте основной оттенок, определенный в выбранной теме, для выбора основного цвета",
"primaryShade": "основной оттенок",
"primaryShade_description": "переопределите основной оттенок (0-9), используемый для кнопок, ссылок и других элементов основного цвета",
"analyticsEnable": "Отправлять аналитику использования",
"analyticsEnable_description": "Анонимные данные использования отправляются разработчику с целью улучшения приложения",
"artistReleaseTypeConfiguration": "настройка типов релизов исполнителя",
"artistReleaseTypeConfiguration_description": "настройте, какие типы релизов отображаются и в каком порядке на странице исполнителя",
"automaticUpdates": "Автообновления",
"automaticUpdates_description": "Проверять и устанавливать обновления автоматически",
"discordLinkType_description": "добавляет ссылки на {{lastfm}} / {{musicbrainz}} в Rich Presence {{discord}} для треков и исполнителей. {{musicbrainz}} точнее, но зависит от тегов и не даёт ссылок на артистов {{lastfm}} почти всегда предоставляет ссылку. Без дополнительных сетевых запросов.",
"blurExplicitImages": "скрывать нецензурные изображения размытием",
"blurExplicitImages_description": "обложки с нецензурным контентом будут размываются",
"autosaveCount": "частота автоматического сохранения очереди воспроизведения",
"discordLinkType_mbz_lastfm": "{{musicbrainz}} (запасной источник: {{lastfm}} )",
"discordLinkType": "интеграция {{discord}} статуса",
"discordListening_description": "Показывать статус \"Слушает\" вместо \"Играет\"",
"discordListening": "показывать статус \"Слушает\"",
"discordPausedStatus_description": "если включено, статус будет отображаться даже когда воспроизведение на паузе",
"discordPausedStatus": "показывать расширенный статус при паузе",
"discordRichPresence": "{{discord}}: расширенный статус",
"discordStateIcon": "показывать иконку воспроизведения",
"enableAutoTranslation_description": "включить автоматический перевод при получении текста",
"enableAutoTranslation": "включить автоперевод",
"exportImportSettings_control_description": "экспорт/импорт настроек в JSON",
"exportImportSettings_control_exportText": "экспорт настроек",
"exportImportSettings_control_importText": "импорт настроек",
"exportImportSettings_control_title": "импорт/экспорт настроек",
"exportImportSettings_destructiveWarning": "Импорт настроек полностью заменит ваши текущие настройки. Убедитесь, что все данные выше верны, перед тем как нажать кнопку «Импорт»!",
"exportImportSettings_importBtn": "Импорт настроек",
"exportImportSettings_importModalTitle": "Импорт настроек Feishin",
"exportImportSettings_importSuccess": "Настройки успешно импортированы!",
"exportImportSettings_notValidJSON": "Некорректный JSON-файл",
"exportImportSettings_offendingKeyError": "Неверный ключ \"{{offendingKey}}\": {{reason}}",
"followCurrentSong_description": "Автоматически прокручивать очередь до текущего трека",
"followCurrentSong": "следить за текущим треком",
"homeFeatureStyle_description": "настройка стиля карусели на главном экране",
"homeFeatureStyle": "стиль карусели на главной",
"homeFeatureStyle_optionMultiple": "несколько",
"language": "Язык интерфейса",
"autoDJ": "авто DJ",
"releaseChannel_optionAlpha": "альфа (ночная версия)",
"discordServeImage": "предоставить {{discord}} изображения с сервера",
"discordServeImage_description": "получать обложки треков для {{discord}} rich presence непосредственно с сервера, доступно только для Jellyfin и Navidrome. {{discord}} использует бота для получения картинок, поэтому ваш сервер должен быть доступен из общедоступной сети",
"discordStateIcon_description": "показывать иконку \"играет\" в статусе. иконка паузы показывается всегда когда опция \"Показывать расширенный статус при паузе\" включена",
"homeFeatureStyle_optionSingle": "одиночный",
"hotkey_navigateHome": "перейти на главную",
"lastfm_description": "показывать ссылки Last.fm на страницах артистов и альбомов",
"lastfm": "показывать ссылки last.fm",
"lastfmApiKey_description": "API ключ для {{lastfm}}. необходим для обложек",
"lastfmApiKey": "API ключ {{lastfm}}",
"logLevel": "детализация логов",
"logLevel_description": "определяет степень детализации логов. \"отладка\" отображает все логи, \"ошибка\" отображает только ошибки",
"logLevel_optionDebug": "отладка",
"logLevel_optionError": "ошибка",
"logLevel_optionInfo": "инфо",
"logLevel_optionWarn": "предупреждение",
"mpvExtraParameters": "дополнительные параметры mpv",
"mpvExtraParameters_description": "дополнительные аргументы, передаваемые mpv",
"musicbrainz_description": "показывать ссылки MusicBrainz на страницах артистов и альбомов, где есть ID MusicBrainz",
"musicbrainz": "показывать ссылки MusicBrainz",
"neteaseTranslation_description": "Если включено, получает и отображает переведённые текста песен с NetEase по возможности",
"neteaseTranslation": "Включить переводы NetEase",
"notify": "включить уведомления о песнях",
"notify_description": "показывать уведомления при смене песни",
"pathReplace": "замена пути к файлу",
"pathReplace_description": "заменяет стандартный путь сервера",
"pathReplace_optionRemovePrefix": "убрать префикс",
"pathReplace_optionAddPrefix": "добавить префикс",
"playerFilters": "Фильтр песен в очереди",
"playerFilters_description": "пропускает песни при добавлении в очередь, основываясь на заданном критерии",
"artistRadioCount_description": "определяет количество песен для добавления в радио по артисту/треку",
"artistRadioCount": "кол-во радио по артисту/треку",
"imageResolution": "разрешение изображения",
"imageResolution_description": "разрешение изображений, используемых в приложении. при значении \"0\" будет использоваться исходное разрешение",
"imageResolution_optionItemCard": "карточка элемента",
"imageResolution_optionSidebar": "боковая панель",
"imageResolution_optionHeader": "заголовок",
"imageResolution_optionFullScreenPlayer": "полноэкранный проигрыватель",
"playerbarSlider": "ползунок проигрывателя",
"playerbarSlider_description": "waveform не рекомендуется при слабом подключении к интернету",
"playerbarSliderType_optionSlider": "ползунок",
"playerbarSliderType_optionWaveform": "waveform",
"playerbarWaveformAlign": "положение waveform",
"playerbarWaveformAlign_optionTop": "верх",
"playerbarWaveformAlign_optionCenter": "центр",
"playerbarWaveformAlign_optionBottom": "низ",
"playerbarWaveformBarWidth": "ширина элемента waveform",
"playerbarWaveformGap": "промежутки waveform",
"playerbarWaveformRadius": "радиус waveform",
"preferLocalLyrics_description": "по возможности предпочитать локальные текста песен загружаемым",
"preferLocalLyrics": "предпочтитать локальные текста песен",
"showLyricsInSidebar_description": "к очереди воспроизведения будет добавлена панель, отображающая текст песни",
"showLyricsInSidebar": "показывать текст песни в боковой панели проигрывателя",
"showRatings_description": "определяет, отображается ли в интерфейсе функция звёздного рейтинга",
"showRatings": "показывать звёздный рейтинг",
"enableGridMultiSelect": "включить множественное выделение",
"enableGridMultiSelect_description": "если включено, то позволяет выделять несколько элементов в таблицах. если отключено, то нажатие на элемент таблицы откроет страницу элемента",
"showVisualizerInSidebar_description": "к боковой части проигрывателя будет добавлена панель, показывающая визуализатор",
"showVisualizerInSidebar": "показывать визуализатор в боковой панели",
"combinedLyricsAndVisualizer_description": "Объединяет текст песни и визуализатор в одну панель заместо двух",
"combinedLyricsAndVisualizer": "объединить текст и визуализатор в одну панель",
"preservePitch_description": "сохраняет тональность при изменении скорости воспроизведения",
"preservePitch": "сохранять тональность",
"audioFadeOnStatusChange": "плавное изменение звука",
"audioFadeOnStatusChange_description": "включает эффекты затухания и появления звука при изменении статуса (пауза/проигрывание)",
"preventSleepOnPlayback_description": "запрещает спящий режим экрана, пока играет музыка",
"preventSleepOnPlayback": "не переходить в спящий режим",
"discordLinkType_none": "$t(common.none)"
}, },
"releaseType": { "releaseType": {
"secondary": { "secondary": {
@@ -938,13 +1098,17 @@
"live": "прямой эфир", "live": "прямой эфир",
"soundtrack": "саундтрек", "soundtrack": "саундтрек",
"spokenWord": "Художественная декламация", "spokenWord": "Художественная декламация",
"audioDrama": "радиопостановка" "audioDrama": "радиопостановка",
"fieldRecording": "запись вне студии",
"mixtape": "сборник",
"djMix": "dj микс"
}, },
"primary": { "primary": {
"other": "другие", "other": "другие",
"broadcast": "транслировать", "broadcast": "транслировать",
"ep": "эп", "ep": "эп",
"single": "сингл" "single": "сингл",
"album": "$t(entity.album, {\"count\": 1})"
} }
}, },
"datetime": { "datetime": {
@@ -986,7 +1150,7 @@
"updatePreset": "Обновить пресет", "updatePreset": "Обновить пресет",
"copyConfiguration": "Копировать Конфигурацию", "copyConfiguration": "Копировать Конфигурацию",
"pasteConfiguration": "Вставить Конфигурацию", "pasteConfiguration": "Вставить Конфигурацию",
"pasteConfigurationPlaceholder": "Вставить JSON конфигурацию", "pasteConfigurationPlaceholder": "Вставить JSON конфигурацию...",
"pasteFromClipboard": "Вставить из буфера обмена", "pasteFromClipboard": "Вставить из буфера обмена",
"applyConfiguration": "Применить Конфигурацию", "applyConfiguration": "Применить Конфигурацию",
"configCopied": "Конфигурация скопирована в буфер обмена", "configCopied": "Конфигурация скопирована в буфер обмена",
+590 -39
View File
@@ -21,7 +21,23 @@
"openIn": { "openIn": {
"lastfm": "Last.fm இல் திறந்திருக்கும்", "lastfm": "Last.fm இல் திறந்திருக்கும்",
"musicbrainz": "மியூசிக் பிரைன்ச் திறந்திருக்கும்" "musicbrainz": "மியூசிக் பிரைன்ச் திறந்திருக்கும்"
} },
"addOrRemoveFromSelection": "தேர்வில் இருந்து சேர்க்கவும் அல்லது நீக்கவும்",
"selectRangeOfItems": "உருப்படிகளின் வரம்பைத் தேர்ந்தெடுக்கவும்",
"createRadioStation": "$t(entity.radioStation, {\"count\": 1}) உருவாக்கவும்",
"deleteRadioStation": "$t(entity.radioStation, {\"count\": 1}) நீக்கு",
"selectAll": "அனைத்தையும் தெரிவுசெய்",
"downloadStarted": "{{count}} உருப்படிகளின் பதிவிறக்கம் தொடங்கியது",
"moveUp": "மேலே செல்ல",
"moveDown": "கீழே நகர",
"holdToMoveToTop": "மேலே செல்ல அழுத்திப் பிடிக்கவும்",
"holdToMoveToBottom": "கீழே நகர்த்த பிடிக்கவும்",
"moveItems": "பொருட்களை நகர்த்த",
"shuffle": "கலக்கு",
"shuffleAll": "அனைத்தையும் கலக்கவும்",
"shuffleSelected": "கலக்கு தேர்ந்தெடுக்கப்பட்டது",
"viewMore": "மேலும் பார்க்க",
"openApplicationDirectory": "பயன்பாட்டு கோப்பகத்தைத் திறக்கவும்"
}, },
"common": { "common": {
"description": "விவரம்", "description": "விவரம்",
@@ -67,7 +83,7 @@
"expand": "விரிவாக்கு", "expand": "விரிவாக்கு",
"favorite": "பிடித்த", "favorite": "பிடித்த",
"filter_one": "வடிப்பி", "filter_one": "வடிப்பி",
"filter_other": "வடிப்பான்கள்", "filter_other": "வடிகட்டிகள்",
"filters": "வடிப்பான்கள்", "filters": "வடிப்பான்கள்",
"forceRestartRequired": "மாற்றங்களைப் பயன்படுத்த மறுதொடக்கம் செய்… மறுதொடக்கம் செய்ய அறிவிப்பை மூடு", "forceRestartRequired": "மாற்றங்களைப் பயன்படுத்த மறுதொடக்கம் செய்… மறுதொடக்கம் செய்ய அறிவிப்பை மூடு",
"forward": "முன்னோக்கி", "forward": "முன்னோக்கி",
@@ -101,7 +117,7 @@
"saveAndReplace": "சேமித்து மாற்றவும்", "saveAndReplace": "சேமித்து மாற்றவும்",
"search": "தேடல்", "search": "தேடல்",
"setting_one": "அமைத்தல்", "setting_one": "அமைத்தல்",
"setting_other": "", "setting_other": "அமைப்புகள்",
"share": "பங்கு", "share": "பங்கு",
"size": "அளவு", "size": "அளவு",
"sortOrder": "ஒழுங்கு", "sortOrder": "ஒழுங்கு",
@@ -119,7 +135,31 @@
"viewReleaseNotes": "வெளியீட்டு குறிப்புகளைக் காண்க", "viewReleaseNotes": "வெளியீட்டு குறிப்புகளைக் காண்க",
"bitDepth": "பிட் ஆழம்", "bitDepth": "பிட் ஆழம்",
"sampleRate": "மாதிரி வீதம்", "sampleRate": "மாதிரி வீதம்",
"tags": "குறிச்சொற்கள்" "tags": "குறிச்சொற்கள்",
"countSelected": "{{count}} தேர்ந்தெடுக்கப்பட்டது",
"explicitStatus": "வெளிப்படையான நிலை",
"doNotShowAgain": "இதை மீண்டும் காட்டாதே",
"view": "பார்வை",
"example": "சான்று",
"externalLinks": "வெளிப்புற இணைப்புகள்",
"faster": "வேகமாக",
"filter_single": "ஒற்றை",
"filter_multiple": "பல",
"mood": "மனநிலை",
"noFilters": "வடிப்பான்கள் எதுவும் கட்டமைக்கப்படவில்லை",
"private": "தனிப்பட்ட",
"public": "பொது",
"retry": "மீண்டும் முயற்சிக்கவும்",
"recordLabel": "பதிவு சிட்டை",
"releaseType": "வெளியீட்டு வகை",
"rename": "மறுபெயரிடுங்கள்",
"slower": "மெதுவாக",
"sort": "வரிசைப்படுத்து",
"explicit": "வெளிப்படையான",
"clean": "தூய்மையான",
"gridRows": "கட்டம் வரிசைகள்",
"tableColumns": "அட்டவணை நெடுவரிசைகள்",
"itemsMore": "மேலும் {{count}}"
}, },
"entity": { "entity": {
"folderWithCount_one": "{{count}} கோப்புறை", "folderWithCount_one": "{{count}} கோப்புறை",
@@ -128,8 +168,8 @@
"genre_other": "வகைகள்", "genre_other": "வகைகள்",
"genreWithCount_one": "{{count}} வகை", "genreWithCount_one": "{{count}} வகை",
"genreWithCount_other": "{{count}} வகைகள்", "genreWithCount_other": "{{count}} வகைகள்",
"album_one": "செருகேடு", "album_one": "ஆல்பம்",
"album_other": "செருகேடுகள்", "album_other": "ஆல்பம்",
"albumArtist_one": "ஆல்பம் கலைஞர்", "albumArtist_one": "ஆல்பம் கலைஞர்",
"albumArtist_other": "ஆல்பம் கலைஞர்கள்", "albumArtist_other": "ஆல்பம் கலைஞர்கள்",
"albumArtistCount_one": "{{count}} ஆல்பம் கலைஞர்", "albumArtistCount_one": "{{count}} ஆல்பம் கலைஞர்",
@@ -140,13 +180,13 @@
"artist_other": "கலைஞர்கள்", "artist_other": "கலைஞர்கள்",
"artistWithCount_one": "{{count}} கலைஞர்", "artistWithCount_one": "{{count}} கலைஞர்",
"artistWithCount_other": "{{count}} கலைஞர்கள்", "artistWithCount_other": "{{count}} கலைஞர்கள்",
"favorite_one": "பிடித்த", "favorite_one": "பிடித்தது",
"favorite_other": "பிடித்தவை", "favorite_other": "பிடித்தவை",
"folder_one": "கோப்புறை", "folder_one": "கோப்புறை",
"folder_other": "கோப்புறைகள்", "folder_other": "கோப்புறைகள்",
"playlist_one": "பிளேலிச்ட்", "playlist_one": "பிளேலிச்ட்",
"playlist_other": "பிளேலிச்ட்கள்", "playlist_other": "பிளேலிச்ட்கள்",
"play_one": "{{count}} நாடகம்", "play_one": "{{count}} விளையாடு",
"play_other": "{{count}} நாடகங்கள்", "play_other": "{{count}} நாடகங்கள்",
"playlistWithCount_one": "{{count}} பிளேலிச்ட்", "playlistWithCount_one": "{{count}} பிளேலிச்ட்",
"playlistWithCount_other": "{{count}} பிளேலிச்ட்கள்", "playlistWithCount_other": "{{count}} பிளேலிச்ட்கள்",
@@ -155,8 +195,12 @@
"track_other": "தடங்கள்", "track_other": "தடங்கள்",
"song_one": "பாடல்", "song_one": "பாடல்",
"song_other": "பாடல்கள்", "song_other": "பாடல்கள்",
"trackWithCount_one": "{{count}} டிராக்", "trackWithCount_one": "{{count}} தடம்",
"trackWithCount_other": "{{count}} தடங்கள்" "trackWithCount_other": "{{count}} தடங்கள்",
"radioStation_one": "வானொலி நிலையம்",
"radioStation_other": "வானொலி நிலையங்கள்",
"radioStationWithCount_one": "{{count}} வானொலி நிலையம்",
"radioStationWithCount_other": "{{count}} வானொலி நிலையங்கள்"
}, },
"error": { "error": {
"mpvRequired": "MPV தேவை", "mpvRequired": "MPV தேவை",
@@ -182,7 +226,14 @@
"sessionExpiredError": "உங்கள் அமர்வு காலாவதியானது", "sessionExpiredError": "உங்கள் அமர்வு காலாவதியானது",
"systemFontError": "கணினி எழுத்துருக்களைப் பெற முயற்சிக்கும்போது பிழை ஏற்பட்டது", "systemFontError": "கணினி எழுத்துருக்களைப் பெற முயற்சிக்கும்போது பிழை ஏற்பட்டது",
"badValue": "தவறான விருப்பம் \"{{value}}\". இந்த மதிப்பு இனி இல்லை", "badValue": "தவறான விருப்பம் \"{{value}}\". இந்த மதிப்பு இனி இல்லை",
"notificationDenied": "அறிவிப்புகளுக்கான அனுமதிகள் மறுக்கப்பட்டன. இந்த அமைப்பு எந்த விளைவையும் ஏற்படுத்தாது" "notificationDenied": "அறிவிப்புகளுக்கான அனுமதிகள் மறுக்கப்பட்டன. இந்த அமைப்பு எந்த விளைவையும் ஏற்படுத்தாது",
"invalidJson": "தவறான சாதொபொகு",
"multipleServerSaveQueueError": "நாடக வரிசையில் ஒன்று அல்லது அதற்கு மேற்பட்ட பாடல்கள் உள்ளன, அவை தற்போதைய சேவையகத்திலிருந்து இல்லை. இது ஆதரிக்கப்படவில்லை",
"noNetwork": "சர்வர் கிடைக்கவில்லை",
"noNetworkDescription": "இந்த சேவையகத்துடன் இணைக்க முடியவில்லை",
"saveQueueFailed": "வரிசையைச் சேமிக்க முடியவில்லை",
"serverLockSingleServer": "சேவையகம் பூட்டப்பட்டிருக்கும் போது ஒரு சேவையகம் மட்டுமே அனுமதிக்கப்படும்",
"settingsSyncError": "ரெண்டரரில் உள்ள அமைப்புகளுக்கும் முக்கிய செயல்முறைக்கும் இடையே முரண்பாடுகள் கண்டறியப்பட்டன. மாற்றங்களைப் பயன்படுத்த பயன்பாட்டை மறுதொடக்கம் செய்யுங்கள்"
}, },
"filter": { "filter": {
"albumArtist": "$t(entity.albumArtist, {\"count\": 1})", "albumArtist": "$t(entity.albumArtist, {\"count\": 1})",
@@ -191,7 +242,7 @@
"biography": "சுயசரிதை", "biography": "சுயசரிதை",
"bitrate": "பிட்ரேட்", "bitrate": "பிட்ரேட்",
"bpm": "பிபிஎம்", "bpm": "பிபிஎம்",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel, {\"count\": 2})",
"comment": "கருத்து", "comment": "கருத்து",
"communityRating": "சமூக மதிப்பீடு", "communityRating": "சமூக மதிப்பீடு",
"path": "பாதை", "path": "பாதை",
@@ -226,7 +277,11 @@
"songCount": "பாடல் எண்ணிக்கை", "songCount": "பாடல் எண்ணிக்கை",
"title": "தலைப்பு", "title": "தலைப்பு",
"toYear": "ஆண்டு", "toYear": "ஆண்டு",
"trackNumber": "மின்தடம்" "trackNumber": "மின்தடம்",
"matchAnd": "மற்றும்",
"matchOr": "அல்லது",
"sortName": "வரிசை பெயர்",
"explicitStatus": "$t(common.explicitStatus)"
}, },
"form": { "form": {
"addServer": { "addServer": {
@@ -240,7 +295,12 @@
"input_url": "முகவரி", "input_url": "முகவரி",
"input_username": "பயனர்பெயர்", "input_username": "பயனர்பெயர்",
"success": "சேவையகம் வெற்றிகரமாக சேர்க்கப்பட்டது", "success": "சேவையகம் வெற்றிகரமாக சேர்க்கப்பட்டது",
"title": "சேவையகத்தைச் சேர்க்கவும்" "title": "சேவையகத்தைச் சேர்க்கவும்",
"input_preferInstantMix": "உடனடி கலவையை விரும்புகிறது",
"input_preferInstantMixDescription": "ஒரே மாதிரியான பாடல்களைப் பெற உடனடி கலவையை மட்டுமே பயன்படுத்தவும். இந்த நடத்தையை மாற்றும் செருகுநிரல்கள் உங்களிடம் இருந்தால் பயனுள்ளதாக இருக்கும்",
"input_preferRemoteUrl": "பொது முகவரி ஐ விரும்பு",
"input_remoteUrl": "பொது முகவரி",
"input_remoteUrlPlaceholder": "விருப்பத்தேர்வு: வெளிப்புற அம்சங்களுக்கான பொது முகவரி"
}, },
"deletePlaylist": { "deletePlaylist": {
"input_confirm": "உறுதிப்படுத்த $t(entity.playlist, {\"count\": 1}) பெயரைத் தட்டச்சு செய்க", "input_confirm": "உறுதிப்படுத்த $t(entity.playlist, {\"count\": 1}) பெயரைத் தட்டச்சு செய்க",
@@ -260,7 +320,11 @@
"queryEditor": { "queryEditor": {
"input_optionMatchAll": "அனைத்தையும் பொருத்துங்கள்", "input_optionMatchAll": "அனைத்தையும் பொருத்துங்கள்",
"input_optionMatchAny": "எந்த பொருத்தவும்", "input_optionMatchAny": "எந்த பொருத்தவும்",
"title": "வினவல் ஆசிரியர்" "title": "வினவல் ஆசிரியர்",
"addRuleGroup": "விதி குழுவைச் சேர்க்கவும்",
"removeRuleGroup": "விதி குழுவை அகற்று",
"resetToDefault": "இயல்புநிலைக்கு மீட்டமைக்கவும்",
"clearFilters": "தெளிவான வடிகட்டிகள்"
}, },
"shareItem": { "shareItem": {
"description": "விவரம்", "description": "விவரம்",
@@ -268,7 +332,9 @@
"expireInvalid": "காலாவதி எதிர்காலத்தில் இருக்க வேண்டும்", "expireInvalid": "காலாவதி எதிர்காலத்தில் இருக்க வேண்டும்",
"allowDownloading": "பதிவிறக்க அனுமதிக்கவும்", "allowDownloading": "பதிவிறக்க அனுமதிக்கவும்",
"success": "இடைநிலைப்பலகைக்கு நகலெடுக்கப்பட்ட இணைப்பைப் பகிரவும் (அல்லது திறக்க இங்கே சொடுக்கு செய்க)", "success": "இடைநிலைப்பலகைக்கு நகலெடுக்கப்பட்ட இணைப்பைப் பகிரவும் (அல்லது திறக்க இங்கே சொடுக்கு செய்க)",
"createFailed": "பங்கை உருவாக்கத் தவறிவிட்டது (பகிர்வு இயக்கப்பட்டதா?)" "createFailed": "பங்கை உருவாக்கத் தவறிவிட்டது (பகிர்வு இயக்கப்பட்டதா?)",
"copyToClipboard": "இடைநிலைப்பலகைக்கு நகலெடு: Ctrl+C, உள்ளிடவும்",
"successMustClick": "பகிர்வு வெற்றிகரமாக உருவாக்கப்பட்டது. திறக்க இங்கே சொடுக்கு செய்யவும்"
}, },
"createPlaylist": { "createPlaylist": {
"success": "$t(entity.playlist, {\"count\": 1}) வெற்றிகரமாக உருவாக்கப்பட்டது", "success": "$t(entity.playlist, {\"count\": 1}) வெற்றிகரமாக உருவாக்கப்பட்டது",
@@ -282,11 +348,48 @@
"input_playlists": "$t(entity.playlist, {\"count\": 2})", "input_playlists": "$t(entity.playlist, {\"count\": 2})",
"input_skipDuplicates": "நகல்களைத் தவிர்க்கவும்", "input_skipDuplicates": "நகல்களைத் தவிர்க்கவும்",
"success": "$t(entity.trackWithCount, {\"count\": {{message}} }) இதற்கு $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} }) சேர்க்கப்பட்டது", "success": "$t(entity.trackWithCount, {\"count\": {{message}} }) இதற்கு $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} }) சேர்க்கப்பட்டது",
"title": "$t(entity.playlist, {\"count\": 1}) இல் சேர்" "title": "$t(entity.playlist, {\"count\": 1}) இல் சேர்",
"create": "$t(entity.playlist, {\"count\": 1}) {{playlist}} உருவாக்கு",
"searchOrCreate": "$t(entity.playlist, {\"count\": 2}) தேடவும் அல்லது புதிய ஒன்றை உருவாக்க தட்டச்சு செய்யவும்"
}, },
"updateServer": { "updateServer": {
"success": "சேவையகம் வெற்றிகரமாக புதுப்பிக்கப்பட்டது", "success": "சேவையகம் வெற்றிகரமாக புதுப்பிக்கப்பட்டது",
"title": "புதுப்பிப்பு சேவையகம்" "title": "புதுப்பிப்பு சேவையகம்"
},
"largeFetchConfirmation": {
"title": "பொருட்களை வரிசையில் சேர்க்கவும்",
"description": "இந்தச் செயல் தற்போதைய வடிகட்டப்பட்ட காட்சியில் உள்ள அனைத்து உருப்படிகளையும் சேர்க்கும்"
},
"createRadioStation": {
"success": "வானொலி நிலையம் வெற்றிகரமாக உருவாக்கப்பட்டது",
"title": "வானொலி நிலையத்தை உருவாக்குங்கள்",
"input_homepageUrl": "முகப்பு முகவரி",
"input_name": "பெயர்",
"input_streamUrl": "ச்ட்ரீம் முகவரி"
},
"lyricsExport": {
"export": "ஏற்றுமதி பாடல் வரிகள்",
"input_synced": "ஒத்திசைக்கப்பட்ட பாடல் வரிகளை ஏற்றுமதி செய்யவும்",
"input_offset": "$t(setting.lyricOffset)"
},
"saveQueue": {
"success": "சேவையகத்தில் விளையாடும் வரிசை சேமிக்கப்பட்டது"
},
"shuffleAll": {
"title": "சீரற்ற விளையாட",
"input_genre": "$t(entity.genre, {\"count\": 1})",
"input_limit": "எத்தனை பாடல்கள்?",
"input_minYear": "ஆண்டு முதல்",
"input_maxYear": "ஆண்டுக்கு",
"input_played": "விளையாடு வடிகட்டி",
"input_played_optionAll": "அனைத்து தடங்கள்",
"input_played_optionUnplayed": "இயக்கப்படாத தடங்கள் மட்டுமே",
"input_played_optionPlayed": "டிராக்குகளை மட்டுமே இயக்கியது"
},
"privateMode": {
"enabled": "தனிப்பட்ட பயன்முறை இயக்கப்பட்டது, பின்னணி நிலை இப்போது வெளிப்புற ஒருங்கிணைப்புகளிலிருந்து மறைக்கப்பட்டுள்ளது",
"disabled": "தனிப்பட்ட பயன்முறை முடக்கப்பட்டுள்ளது, இயக்கப்பட்ட வெளிப்புற ஒருங்கிணைப்புகளுக்கு இப்போது பின்னணி நிலை தெரியும்",
"title": "தனிப்பட்ட முறை"
} }
}, },
"page": { "page": {
@@ -299,7 +402,13 @@
"viewAllTracks": "அனைத்தையும் காண்க $t(entity.track, {\"count\": 2})", "viewAllTracks": "அனைத்தையும் காண்க $t(entity.track, {\"count\": 2})",
"relatedArtists": "தொடர்புடைய $t(entity.artist, {\"count\": 2})", "relatedArtists": "தொடர்புடைய $t(entity.artist, {\"count\": 2})",
"topSongsFrom": "{{title}} இலிருந்து சிறந்த பாடல்கள்", "topSongsFrom": "{{title}} இலிருந்து சிறந்த பாடல்கள்",
"viewAll": "அனைத்தையும் காண்க" "viewAll": "அனைத்தையும் காண்க",
"favoriteSongs": "பிடித்த பாடல்கள்",
"groupingTypeAll": "அனைத்து வகையான வெளியீடுகள்",
"groupingTypePrimary": "முதன்மை வெளியீட்டு வகைகள்",
"topSongsCommunity": "சமூகம்",
"topSongsPersonal": "தனிப்பட்ட",
"favoriteSongsFrom": "{{title}} இலிருந்து பிடித்த பாடல்கள்"
}, },
"appMenu": { "appMenu": {
"goBack": "திரும்பிச் செல்லுங்கள்", "goBack": "திரும்பிச் செல்லுங்கள்",
@@ -311,7 +420,13 @@
"quit": "$t(common.quit)", "quit": "$t(common.quit)",
"selectServer": "சேவையகத்தைத் தேர்ந்தெடுக்கவும்", "selectServer": "சேவையகத்தைத் தேர்ந்தெடுக்கவும்",
"settings": "$t(common.setting, {\"count\": 2})", "settings": "$t(common.setting, {\"count\": 2})",
"version": "பதிப்பு {{version}}" "version": "பதிப்பு {{version}}",
"commandPalette": "கட்டளை தட்டு திறக்க",
"privateModeOff": "தனிப்பட்ட பயன்முறையை அணைக்கவும்",
"privateModeOn": "தனிப்பட்ட பயன்முறையை இயக்கவும்",
"selectMusicFolder": "இசை கோப்புறையைத் தேர்ந்தெடுக்கவும்",
"noMusicFolder": "இசை கோப்புறை எதுவும் தேர்ந்தெடுக்கப்படவில்லை",
"multipleMusicFolders": "{{count}} இசை கோப்புறைகள் தேர்ந்தெடுக்கப்பட்டன"
}, },
"manageServers": { "manageServers": {
"url": "முகவரி", "url": "முகவரி",
@@ -343,7 +458,11 @@
"showDetails": "தகவலைப் பெறுங்கள்", "showDetails": "தகவலைப் பெறுங்கள்",
"addToFavorites": "$t(action.addToFavorites)", "addToFavorites": "$t(action.addToFavorites)",
"addToPlaylist": "$t(action.addToPlaylist)", "addToPlaylist": "$t(action.addToPlaylist)",
"createPlaylist": "$t(action.createPlaylist)" "createPlaylist": "$t(action.createPlaylist)",
"moveItems": "$t(action.moveItems)",
"goTo": "செல்",
"goToAlbum": "$t(entity.album, {\"count\": 1}) க்குச் செல்",
"goToAlbumArtist": "$t(entity.albumArtist, {\"count\": 1}) க்குச் செல்"
}, },
"fullscreenPlayer": { "fullscreenPlayer": {
"config": { "config": {
@@ -386,7 +505,9 @@
"mostPlayed": "அதிகம் விளையாடியது", "mostPlayed": "அதிகம் விளையாடியது",
"newlyAdded": "புதிதாக சேர்க்கப்பட்ட வெளியீடுகள்", "newlyAdded": "புதிதாக சேர்க்கப்பட்ட வெளியீடுகள்",
"recentlyPlayed": "அண்மைக் காலத்தில் விளையாடியது", "recentlyPlayed": "அண்மைக் காலத்தில் விளையாடியது",
"title": "$t(common.home)" "title": "$t(common.home)",
"genres": "$t(entity.genre, {\"count\": 2})",
"recentlyReleased": "அண்மைக் காலத்தில் வெளியானது"
}, },
"itemDetail": { "itemDetail": {
"copyPath": "இடைநிலைப்பலகைக்கு பாதையை நகலெடுக்கவும்", "copyPath": "இடைநிலைப்பலகைக்கு பாதையை நகலெடுக்கவும்",
@@ -404,7 +525,25 @@
"generalTab": "பொது", "generalTab": "பொது",
"hotkeysTab": "ஆட்கீச்", "hotkeysTab": "ஆட்கீச்",
"playbackTab": "பின்னணி", "playbackTab": "பின்னணி",
"windowTab": "சாளரம்" "windowTab": "சாளரம்",
"analytics": "பகுப்பாய்வு",
"updates": "புதுப்பிப்பு",
"cache": "தற்காலிக சேமிப்பு",
"application": "விண்ணப்பம்",
"queryBuilder": "வினவல் கட்டுபவர்",
"theme": "கருப்பொருள்",
"controls": "கட்டுப்பாடுகள்",
"sidebar": "பக்கப்பட்டி",
"remote": "தொலைவில்",
"exportImport": "இறக்குமதி/ஏற்றுமதி",
"scrobble": "சுருள்",
"audio": "ஆடியோ",
"lyrics": "பாடல் வரிகள்",
"lyricsDisplay": "பாடல் வரிகள் காட்சி",
"transcoding": "டிரான்ச்கோடிங்",
"discord": "முரண்பாடு",
"logger": "மரம் வெட்டுபவர்",
"playerFilters": "பிளேயர் வடிப்பான்கள்"
}, },
"sidebar": { "sidebar": {
"folders": "$t(entity.folder, {\"count\": 2})", "folders": "$t(entity.folder, {\"count\": 2})",
@@ -419,7 +558,10 @@
"artists": "$t(entity.artist, {\"count\": 2})", "artists": "$t(entity.artist, {\"count\": 2})",
"shared": "$t(entity.playlist, {\"count\": 2}) பகிரப்பட்டது", "shared": "$t(entity.playlist, {\"count\": 2}) பகிரப்பட்டது",
"tracks": "$t(entity.track, {\"count\": 2})", "tracks": "$t(entity.track, {\"count\": 2})",
"myLibrary": "எனது நூலகம்" "myLibrary": "எனது நூலகம்",
"collections": "சேகரிப்புகள்",
"favorites": "$t(entity.favorite, {\"count\": 2})",
"radio": "$t(entity.radioStation, {\"count\": 2})"
}, },
"trackList": { "trackList": {
"title": "$t(entity.track, {\"count\": 2})", "title": "$t(entity.track, {\"count\": 2})",
@@ -438,11 +580,33 @@
"artistAlbums": "ஆல்பங்கள் {{artist}}", "artistAlbums": "ஆல்பங்கள் {{artist}}",
"genreAlbums": "\"{{genre}}\" $t(entity.album, {\"count\": 2})", "genreAlbums": "\"{{genre}}\" $t(entity.album, {\"count\": 2})",
"title": "$t(entity.album, {\"count\": 2})" "title": "$t(entity.album, {\"count\": 2})"
},
"radioList": {
"title": "வானொலி நிலையங்கள்"
},
"releasenotes": {
"commitsSinceStable": "{{stable}} முதல் உறுதியளிக்கிறது",
"noNewCommits": "இந்த வரம்பில் புதிய பொறுப்புகள் எதுவும் இல்லை",
"noStableReleaseToCompare": "ஒப்பிடுவதற்கு நிலையான வெளியீடு இல்லை"
},
"favorites": {
"title": "$t(entity.favorite, {\"count\": 2})"
},
"windowBar": {
"paused": "(இடைநிறுத்தப்பட்டது) ",
"privateMode": "(தனிப்பட்ட முறை)"
},
"folderList": {
"title": "$t(entity.folder, {\"count\": 2})"
},
"collections": {
"overrideExisting": "ஏற்கனவே உள்ளதை மேலெழுதவும்",
"saveAsCollection": "சேகரிப்பாக சேமிக்கவும்"
} }
}, },
"player": { "player": {
"addLast": "கடைசியாக சேர்க்கவும்", "addLast": "கடைசி",
"addNext": "அடுத்து சேர்க்கவும்", "addNext": "அடுத்து",
"favorite": "பிடித்த", "favorite": "பிடித்த",
"mute": "ஒலிமுடக்கு", "mute": "ஒலிமுடக்கு",
"muted": "முடக்கிய", "muted": "முடக்கிய",
@@ -455,7 +619,7 @@
"repeat": "மீண்டும்", "repeat": "மீண்டும்",
"repeat_all": "அனைத்தையும் மீண்டும் செய்யவும்", "repeat_all": "அனைத்தையும் மீண்டும் செய்யவும்",
"repeat_off": "முடக்கப்பட்டதை மீண்டும் செய்யவும்", "repeat_off": "முடக்கப்பட்டதை மீண்டும் செய்யவும்",
"shuffle": "விளையாட்டு மாற்றப்பட்டது", "shuffle": "விளையாடு (குலைக்கப்பட்டது)",
"shuffle_off": "கலக்கு முடக்கப்பட்டது", "shuffle_off": "கலக்கு முடக்கப்பட்டது",
"skip": "தவிர்", "skip": "தவிர்",
"playbackFetchCancel": "இது சிறிது நேரம் ஆகும்… ரத்து செய்ய அறிவிப்பை மூடு", "playbackFetchCancel": "இது சிறிது நேரம் ஆகும்… ரத்து செய்ய அறிவிப்பை மூடு",
@@ -471,7 +635,25 @@
"toggleFullscreenPlayer": "முழுத்திரை பிளேயரை மாற்றவும்", "toggleFullscreenPlayer": "முழுத்திரை பிளேயரை மாற்றவும்",
"unfavorite": "மாறாத", "unfavorite": "மாறாத",
"pause": "இடைநிறுத்தம்", "pause": "இடைநிறுத்தம்",
"viewQueue": "வரிசையைக் காண்க" "viewQueue": "வரிசையைக் காண்க",
"addLastShuffled": "கடைசியாக (குறைக்கப்பட்டது)",
"addNextShuffled": "அடுத்தது (குலைக்கப்பட்டது)",
"albumRadio": "ஆல்பம் வானொலி",
"artistRadio": "கலைஞர் வானொலி",
"holdToShuffle": "கலக்க பிடி",
"lyrics": "பாடல் வரிகள்",
"restoreQueueFromServer": "சேவையகத்திலிருந்து வரிசையை மீட்டமை",
"saveQueueToServer": "சேவையகத்தில் வரிசையைச் சேமிக்கவும்",
"trackRadio": "டிராக் ரேடியோ",
"sleepTimer": "தூக்க நேரம்",
"sleepTimer_endOfSong": "தற்போதைய பாடலின் முடிவு",
"sleepTimer_minutes": "{{count}} மணித்துளி",
"sleepTimer_hours": "{{count}} மணி",
"sleepTimer_custom": "தனிப்பயன்",
"sleepTimer_off": "அணை",
"sleepTimer_timeRemaining": "{{time}} மீதமுள்ளது",
"sleepTimer_setCustom": "டைமரை அமைக்கவும்",
"sleepTimer_cancel": "நேரங்குறிகருவி ரத்து"
}, },
"setting": { "setting": {
"accentColor": "உச்சரிப்பு நிறம்", "accentColor": "உச்சரிப்பு நிறம்",
@@ -480,7 +662,7 @@
"applicationHotkeys": "பயன்பாட்டு ஆட்கீச்", "applicationHotkeys": "பயன்பாட்டு ஆட்கீச்",
"applicationHotkeys_description": "பயன்பாட்டு ஆட்கீசை உள்ளமைக்கவும். உலகளாவிய ஆட்ச்கியாக அமைக்க தேர்வுப்பெட்டியை மாற்றவும் (டெச்க்டாப் மட்டும்)", "applicationHotkeys_description": "பயன்பாட்டு ஆட்கீசை உள்ளமைக்கவும். உலகளாவிய ஆட்ச்கியாக அமைக்க தேர்வுப்பெட்டியை மாற்றவும் (டெச்க்டாப் மட்டும்)",
"artistConfiguration": "ஆல்பம் கலைஞர் பக்க உள்ளமைவு", "artistConfiguration": "ஆல்பம் கலைஞர் பக்க உள்ளமைவு",
"audioDevice_description": "பிளேபேக்கிற்கு பயன்படுத்த ஆடியோ சாதனத்தைத் தேர்ந்தெடுக்கவும் (வெப் பிளேயர் மட்டும்)", "audioDevice_description": "பிளேபேக்கிற்குப் பயன்படுத்த ஆடியோ சாதனத்தைத் தேர்ந்தெடுக்கவும்",
"audioExclusiveMode": "ஆடியோ பிரத்தியேக பயன்முறை", "audioExclusiveMode": "ஆடியோ பிரத்தியேக பயன்முறை",
"audioPlayer": "ஆடியோ பிளேயர்", "audioPlayer": "ஆடியோ பிளேயர்",
"audioPlayer_description": "பிளேபேக்கிற்கு பயன்படுத்த ஆடியோ பிளேயரைத் தேர்ந்தெடுக்கவும்", "audioPlayer_description": "பிளேபேக்கிற்கு பயன்படுத்த ஆடியோ பிளேயரைத் தேர்ந்தெடுக்கவும்",
@@ -531,7 +713,7 @@
"lastfmApiKey": "{{lastfm}} பநிஇ key", "lastfmApiKey": "{{lastfm}} பநிஇ key",
"lastfmApiKey_description": "{{lastfm}} க்கான பநிஇ விசை. கவர் கலைக்குத் தேவை", "lastfmApiKey_description": "{{lastfm}} க்கான பநிஇ விசை. கவர் கலைக்குத் தேவை",
"lyricFetch": "இணையத்திலிருந்து வரிகளை பெறுங்கள்", "lyricFetch": "இணையத்திலிருந்து வரிகளை பெறுங்கள்",
"lyricFetchProvider_description": "பாடல் பெற வழங்குநர்களைத் தேர்ந்தெடுக்கவும். வழங்குநர்களின் வரிசை அவர்கள் வினவப்படும் ஒழுங்கு", "lyricFetchProvider_description": "பாடல் வரிகளைப் பெற வழங்குநர்களைத் தேர்ந்தெடுக்கவும்",
"lyricOffset": "பாடல் ஆஃப்செட் (எம்.எச்)", "lyricOffset": "பாடல் ஆஃப்செட் (எம்.எச்)",
"minimizeToTray": "தட்டில் குறைக்கவும்", "minimizeToTray": "தட்டில் குறைக்கவும்",
"minimumScrobblePercentage": "குறைந்தபட்ச துணிச்சல் காலம் (சதவீதம்)", "minimumScrobblePercentage": "குறைந்தபட்ச துணிச்சல் காலம் (சதவீதம்)",
@@ -687,7 +869,7 @@
"discordPausedStatus": "இடைநிறுத்தப்படும்போது பணக்கார இருப்பைக் காட்டுங்கள்", "discordPausedStatus": "இடைநிறுத்தப்படும்போது பணக்கார இருப்பைக் காட்டுங்கள்",
"discordPausedStatus_description": "இயக்கப்பட்டால், பிளேயர் இடைநிறுத்தப்படும்போது நிலை காண்பிக்கப்படும்", "discordPausedStatus_description": "இயக்கப்பட்டால், பிளேயர் இடைநிறுத்தப்படும்போது நிலை காண்பிக்கப்படும்",
"discordServeImage": "சேவையகத்திலிருந்து {{discord}} படங்களை பரிமாறவும்", "discordServeImage": "சேவையகத்திலிருந்து {{discord}} படங்களை பரிமாறவும்",
"discordServeImage_description": "{{discord}} சேவையகத்திலிருந்தே பணக்கார இருப்புக்கான கவர் கலையைப் பகிரவும், செலிஃபின் மற்றும் நுடிட்ரோம மட்டுமே கிடைக்கும்", "discordServeImage_description": "சேவையகத்திலிருந்தே {{discord}} சிறந்த இருப்புக்கான கவர் ஆர்ட்டைப் பகிரவும், செல்லிஃபின் மற்றும் நிட்ரோமுக்கு மட்டுமே கிடைக்கும். படங்களைப் பெற {{discord}} ஒரு போட்டைப் பயன்படுத்துகிறது, எனவே உங்கள் சர்வர் பொது இணையத்திலிருந்து அணுகக்கூடியதாக இருக்க வேண்டும்",
"preferLocalLyrics": "உள்ளக பாடல்களை விரும்புங்கள்", "preferLocalLyrics": "உள்ளக பாடல்களை விரும்புங்கள்",
"preferLocalLyrics_description": "கிடைக்கும்போது தொலைநிலை பாடல்களை விட உள்ளக பாடல்களை விரும்புங்கள்", "preferLocalLyrics_description": "கிடைக்கும்போது தொலைநிலை பாடல்களை விட உள்ளக பாடல்களை விரும்புங்கள்",
"lastfm": "last.fm இணைப்புகளைக் காட்டு", "lastfm": "last.fm இணைப்புகளைக் காட்டு",
@@ -697,7 +879,134 @@
"neteaseTranslation": "நெட்ச் மொழிபெயர்ப்புகளை இயக்கவும்", "neteaseTranslation": "நெட்ச் மொழிபெயர்ப்புகளை இயக்கவும்",
"neteaseTranslation_description": "இயக்கப்பட்டால், கிடைத்தால் நெட்சிலிருந்து மொழிபெயர்க்கப்பட்ட பாடல்களைப் பெறுகிறது மற்றும் காட்சிப்படுத்துகிறது", "neteaseTranslation_description": "இயக்கப்பட்டால், கிடைத்தால் நெட்சிலிருந்து மொழிபெயர்க்கப்பட்ட பாடல்களைப் பெறுகிறது மற்றும் காட்சிப்படுத்துகிறது",
"preservePitch": "சுருதியைப் பாதுகாக்கவும்", "preservePitch": "சுருதியைப் பாதுகாக்கவும்",
"preservePitch_description": "பின்னணி வேகத்தை மாற்றும்போது சுருதியைப் பாதுகாக்கிறது" "preservePitch_description": "பின்னணி வேகத்தை மாற்றும்போது சுருதியைப் பாதுகாக்கிறது",
"autoDJ": "ஆட்டோ டி.சே",
"autoDJ_description": "தானாக வரிசையில் ஒத்த பாடல்களைச் சேர்க்கவும்",
"autoDJ_itemCount": "பொருள் எண்ணிக்கை",
"autoDJ_itemCount_description": "ஆட்டோ DJ இயக்கப்பட்டிருக்கும் போது, வரிசையில் சேர்க்க முயற்சிக்கும் உருப்படிகளின் எண்ணிக்கை",
"autoDJ_timing": "நேரவிவரம்",
"autoDJ_timing_description": "ஆட்டோ டிசேக்கு முன் வரிசையில் மீதமுள்ள பாடல்களின் எண்ணிக்கை தூண்டப்படுகிறது",
"useThemeAccentColor": "கருப்பொருள் உச்சரிப்பு நிறத்தைப் பயன்படுத்தவும்",
"useThemeAccentColor_description": "தனிப்பயன் உச்சரிப்பு நிறத்திற்குப் பதிலாக தேர்ந்தெடுக்கப்பட்ட தீமில் வரையறுக்கப்பட்ட முதன்மை வண்ணத்தைப் பயன்படுத்தவும்",
"analyticsDisable": "பயன்பாடு அடிப்படையிலான பகுப்பாய்வுகளில் இருந்து விலகுதல்",
"analyticsDisable_description": "பயன்பாட்டை மேம்படுத்த உதவ டெவெலப்பருக்கு அநாமதேய பயன்பாட்டுத் தரவு அனுப்பப்படுகிறது",
"analyticsEnable": "பயன்பாட்டு அடிப்படையிலான பகுப்பாய்வுகளை அனுப்பவும்",
"analyticsEnable_description": "பயன்பாட்டை மேம்படுத்த உதவ டெவெலப்பருக்கு அநாமதேய பயன்பாட்டுத் தரவு அனுப்பப்படுகிறது",
"artistBackground": "கலைஞர் பின்னணி படம்",
"artistBackground_description": "கலைஞர் கலையை உள்ளடக்கிய கலைஞர் பக்கங்களுக்கு பின்னணி படத்தை சேர்க்கிறது",
"artistBackgroundBlur": "கலைஞர் பின்னணி படம் மங்கலான அளவு",
"artistBackgroundBlur_description": "கலைஞரின் பின்னணி படத்தில் பயன்படுத்தப்படும் மங்கலின் அளவை சரிசெய்கிறது",
"artistReleaseTypeConfiguration": "கலைஞர் வெளியீட்டு வகை கட்டமைப்பு",
"artistReleaseTypeConfiguration_description": "ஆல்பம் கலைஞர் பக்கத்தில் என்ன வெளியீட்டு வகைகள் காட்டப்படுகின்றன, எந்த வரிசையில் உள்ளன என்பதை உள்ளமைக்கவும்",
"crossfadeStyle": "குறுக்குவழி பாணி",
"automaticUpdates": "தானியங்கி புதுப்பிப்புகள்",
"automaticUpdates_description": "புதுப்பிப்புகளை தானாக சரிபார்த்து நிறுவவும்",
"releaseChannel_optionAlpha": "ஆல்பா (இரவு)",
"releaseChannel_optionBeta": "பீட்டா",
"releaseChannel_optionLatest": "அண்மைக் கால",
"releaseChannel": "வெளியீடு சேனல்",
"releaseChannel_description": "தானியங்கி புதுப்பிப்புகளுக்கு நிலையான, பீட்டா அல்லது ஆல்பா (இரவு) வெளியீடுகளுக்கு இடையே தேர்வு செய்யவும்",
"discordDisplayType_artistname": "கலைஞர் பெயர்(கள்)",
"discordDisplayType_description": "உங்கள் நிலையில் நீங்கள் கேட்பதை மாற்றுகிறது",
"discordDisplayType_songname": "பாடல் பெயர்",
"discordDisplayType": "{{discord}} இருப்பு காட்சி வகை",
"discordLinkType_description": "{{discord}} சிறந்த முன்னிலையில் பாடல் மற்றும் கலைஞர் புலங்களுக்கு {{lastfm}} அல்லது {{musicbrainz}} வெளிப்புற இணைப்புகளைச் சேர்க்கிறது. {{musicbrainz}} மிகவும் துல்லியமானது ஆனால் குறிச்சொற்கள் தேவை மற்றும் கலைஞர் இணைப்புகளை வழங்காது, {{lastfm}} எப்போதும் இணைப்பை வழங்க வேண்டும். கூடுதல் பிணைய கோரிக்கைகளை செய்யாது",
"discordLinkType_mbz_lastfm": "{{musicbrainz}} உடன் {{lastfm}} ஃபால்பேக்",
"discordLinkType_none": "$t(common.none)",
"discordLinkType": "{{discord}} இருப்பு இணைப்புகள்",
"discordRichPresence": "{{discord}} பணக்கார இருப்பு",
"discordStateIcon": "விளையாடும் ஐகானைக் காட்டு",
"discordStateIcon_description": "பணக்கார இருப்பு நிலையில் சிறிய விளையாடும் ஐகானைக் காட்டு. இடைநிறுத்தப்பட்ட படவுரு எப்போதும் \"இடைநிறுத்தப்பட்ட போது பணக்கார இருப்பைக் காட்டு\" இயக்கப்பட்டிருக்கும் போது காண்பிக்கப்படும்",
"enableAutoTranslation_description": "பாடல் வரிகள் ஏற்றப்படும் போது தானாகவே மொழிபெயர்ப்பை இயக்கவும்",
"enableAutoTranslation": "தானியங்கு மொழிபெயர்ப்பை இயக்கு",
"exportImportSettings_control_description": "சாதொபொகு வழியாக ஏற்றுமதி மற்றும் இறக்குமதி அமைப்புகளை",
"exportImportSettings_control_exportText": "ஏற்றுமதி அமைப்புகள்",
"exportImportSettings_control_importText": "இறக்குமதி அமைப்புகள்",
"exportImportSettings_control_title": "இறக்குமதி / ஏற்றுமதி அமைப்புகள்",
"exportImportSettings_destructiveWarning": "அமைப்புகளை இறக்குமதி செய்வது அழிவுகரமானது, கீழே உள்ள \"இறக்குமதி\" என்பதைக் சொடுக்கு செய்வதற்கு முன் மேலே உள்ளவற்றை மதிப்பாய்வு செய்யவும்!",
"exportImportSettings_importBtn": "இறக்குமதி அமைப்புகள்",
"exportImportSettings_importModalTitle": "feishin அமைப்புகளை இறக்குமதி செய்யவும்",
"exportImportSettings_importSuccess": "அமைப்புகள் வெற்றிகரமாக இறக்குமதி செய்யப்பட்டன!",
"exportImportSettings_notValidJSON": "அனுப்பப்பட்ட கோப்பு சாதொபொகு செல்லுபடியாகாது",
"exportImportSettings_offendingKeyError": "\"{{offendingKey}}\" தவறானது - {{reason}}",
"followCurrentSong_description": "தானாக விளையாடும் வரிசையை தற்போதைய பாடலுக்கு உருட்டும்",
"followCurrentSong": "தற்போதைய பாடலைப் பின்பற்றவும்",
"homeFeatureStyle_description": "வீட்டில் இடம்பெற்றுள்ள கொணர்வியின் பாணியைக் கட்டுப்படுத்துகிறது",
"homeFeatureStyle": "வீட்டில் இடம்பெற்றது கொணர்வி பாணி",
"homeFeatureStyle_optionMultiple": "பல",
"homeFeatureStyle_optionSingle": "ஒற்றை",
"hotkey_listNavigateToPage": "பட்டியல் உருப்படி பக்கத்திற்கு செல்லவும்",
"hotkey_listPlayDefault": "பட்டியல் நாடகம்",
"hotkey_listPlayLast": "பட்டியல் கடைசியாக விளையாடு",
"hotkey_listPlayNext": "பட்டியல் அடுத்து விளையாடு",
"hotkey_listPlayNow": "பட்டியல் விளையாட இப்போது",
"hotkey_navigateHome": "வீட்டிற்கு செல்லவும்",
"language": "மொழி",
"logLevel": "பதிவு நிலை",
"logLevel_description": "காண்பிக்க குறைந்தபட்ச பதிவு அளவை அமைக்கிறது. பிழைத்திருத்தம் அனைத்து பதிவுகளையும் காட்டுகிறது, பிழை பிழைகளை மட்டுமே காட்டுகிறது",
"logLevel_optionDebug": "பிழைத்திருத்தம்",
"logLevel_optionError": "பிழை",
"logLevel_optionInfo": "தகவல்",
"logLevel_optionWarn": "முன்னறிவிப்பு",
"mpvExtraParameters": "mpv கூடுதல் அளவுருக்கள்",
"mpvExtraParameters_description": "mpv க்கு அனுப்ப கூடுதல் வாதங்கள்",
"notify": "பாடல் அறிவிப்புகளை இயக்கவும்",
"notify_description": "தற்போதைய பாடலை மாற்றும்போது அறிவிப்புகளைக் காட்டு",
"pathReplace": "கோப்பு பாதை மாற்று",
"pathReplace_description": "உங்கள் சேவையகத்தின் இயல்புநிலை கோப்பு பாதையை மாற்றவும்",
"pathReplace_optionRemovePrefix": "முன்னொட்டை அகற்று",
"pathReplace_optionAddPrefix": "முன்னொட்டு சேர்க்கவும்",
"playerFilters": "வரிசையில் இருந்து பாடல்களை வடிகட்டவும்",
"playerFilters_description": "பின்வரும் அளவுகோல்களின் அடிப்படையில் பாடல்களை வரிசையில் சேர்க்காமல் தவிர்க்கவும்",
"artistRadioCount_description": "கலைஞர் வானொலி மற்றும் ட்ராக் வானொலிக்கான பாடல்களின் எண்ணிக்கையை அமைக்கிறது",
"artistRadioCount": "கலைஞர்/டிராக் ரேடியோ எண்ணிக்கை",
"imageResolution": "படத்தின் தீர்மானம்",
"imageResolution_description": "பயன்பாட்டைச் சுற்றிப் பயன்படுத்தப்படும் படங்களுக்கான தீர்மானம். 0 இன் மதிப்பைப் பயன்படுத்துவது இயல்பான படத் தீர்மானத்திற்கு இயல்புநிலையாக இருக்கும்",
"imageResolution_optionTable": "அட்டவணை",
"imageResolution_optionItemCard": "பொருள் அட்டை",
"imageResolution_optionSidebar": "பக்கப்பட்டி",
"imageResolution_optionHeader": "தலைப்பி",
"imageResolution_optionFullScreenPlayer": "முழுத்திரை பிளேயர்",
"playerbarSlider": "பிளேயர்பார் ச்லைடர்",
"playerbarSlider_description": "மெதுவான அல்லது மீட்டர் இணைய இணைப்பில் இருந்தால் அலைவடிவம் பரிந்துரைக்கப்படுவதில்லை",
"playerbarSliderType_optionSlider": "ச்லைடர்",
"playerbarSliderType_optionWaveform": "அலைவடிவம், அலைப்படம்",
"playerbarWaveformAlign": "அலை வடிவ சீரமைப்பு",
"playerbarWaveformAlign_optionTop": "மேலே",
"playerbarWaveformAlign_optionCenter": "நடுவண்",
"playerbarWaveformAlign_optionBottom": "கீழே",
"playerbarWaveformBarWidth": "அலைவடிவ பட்டை அகலம்",
"playerbarWaveformGap": "அலைவடிவ இடைவெளி",
"playerbarWaveformRadius": "அலைவடிவ ஆரம்",
"showLyricsInSidebar_description": "பாடல் வரிகளைக் காண்பிக்கும் இணைக்கப்பட்ட நாடக வரிசையில் ஒரு குழு சேர்க்கப்படும்",
"showLyricsInSidebar": "பிளேயர் பக்கப்பட்டியில் பாடல் வரிகளைக் காட்டு",
"showRatings_description": "நட்சத்திர மதிப்பீடு நற்பொருத்தம் இடைமுகத்தில் காட்டப்பட்டால் கட்டுப்படுத்துகிறது",
"showRatings": "நட்சத்திர மதிப்பீடுகளைக் காட்டு",
"blurExplicitImages": "வெளிப்படையான படங்களை மங்கலாக்கும்",
"blurExplicitImages_description": "வெளிப்படையாகக் குறியிடப்பட்ட ஆல்பம் மற்றும் பாடல் கலைப்படைப்புகள் மங்கலாக்கப்படும்",
"enableGridMultiSelect": "கட்டம் பல தேர்வை இயக்கவும்",
"enableGridMultiSelect_description": "இயக்கப்பட்டால், கட்டக் காட்சிகளில் பல உருப்படிகளைத் தேர்ந்தெடுக்க அனுமதிக்கிறது. முடக்கப்பட்டிருக்கும் போது, கிரிட் உருப்படி படங்களைக் சொடுக்கு செய்வதன் மூலம் உருப்படி பக்கத்திற்குச் செல்லும்",
"showVisualizerInSidebar_description": "விசுவலைசரைக் காட்டும் பிளேயர் பக்கப்பட்டியில் ஒரு பேனல் சேர்க்கப்படும்",
"showVisualizerInSidebar": "பிளேயர் பக்கப்பட்டியில் காட்சிப்படுத்தலைக் காட்டு",
"combinedLyricsAndVisualizer_description": "பாடல் வரிகளையும் காட்சிப்படுத்தலையும் ஒரே பேனலில் இணைக்கவும்",
"combinedLyricsAndVisualizer": "பிளேயர் பக்கப்பட்டியில் பாடல் வரிகள் மற்றும் காட்சிப்படுத்தல் ஆகியவற்றை இணைக்கவும்",
"audioFadeOnStatusChange": "நிலை மாறும்போது ஆடியோ மங்குகிறது",
"audioFadeOnStatusChange_description": "ப்ளே/இடைநிறுத்தம் நிலை மாறும்போது ஃபேட் அவுட் மற்றும் ஃபேட் இன் செயல்படுத்துகிறது",
"preventSleepOnPlayback_description": "இசை இயங்கும் போது காட்சி தூங்குவதைத் தடுக்கிறது",
"preventSleepOnPlayback": "பிளேபேக்கில் தூக்கத்தைத் தடுக்கவும்",
"sidebarPlaylistSorting_description": "இயல்புநிலை சர்வர் ஆர்டருக்குப் பதிலாக இழுத்து விடுவதைப் பயன்படுத்தி பக்கப்பட்டியில் கைமுறையாக பிளேலிச்ட்டை வரிசைப்படுத்த அனுமதிக்கிறது",
"sidebarPlaylistSorting": "பக்கப்பட்டி பிளேலிச்ட் வரிசையாக்கம்",
"sidebarPlaylistListFilterRegex_description": "இந்த வழக்கமான வெளிப்பாட்டுடன் பொருந்தக்கூடிய பிளேலிச்ட்களை பக்கப்பட்டியில் மறைக்கவும்",
"sidebarPlaylistListFilterRegex_placeholder": "எ.கா. ^தினசரி கலவை.*",
"sidebarPlaylistListFilterRegex": "பிளேலிச்ட் வடிகட்டி வழக்கவெளி",
"mediaSession_description": "மீடியா அமர்வு ஒருங்கிணைப்பை செயல்படுத்துகிறது, மீடியா கட்டுப்பாடுகள் மற்றும் மெட்டாடேட்டாவை கணினி தொகுதி மேலடுக்கு மற்றும் பூட்டுத் திரையில் காண்பிக்கும்",
"mediaSession": "ஊடக அமர்வை இயக்கவும்",
"transcode": "டிரான்ச்கோடிங்கை இயக்கவும்",
"queryBuilder": "வினவல் கட்டுபவர்",
"queryBuilderCustomFields_inputLabel": "சிட்டை",
"queryBuilderCustomFields_inputTag": "குறிச்சொல்",
"queryBuilderCustomFields": "விருப்ப புலங்கள்",
"queryBuilderCustomFields_description": "வினவல் பில்டர்களில் பயன்படுத்த தனிப்பயன் புலங்களைச் சேர்க்கவும்"
}, },
"table": { "table": {
"config": { "config": {
@@ -707,7 +1016,7 @@
"biography": "$t(common.biography)", "biography": "$t(common.biography)",
"bitrate": "$t(common.bitrate)", "bitrate": "$t(common.bitrate)",
"bpm": "$t(common.bpm)", "bpm": "$t(common.bpm)",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel, {\"count\": 2})",
"codec": "$t(common.codec)", "codec": "$t(common.codec)",
"dateAdded": "தேதி சேர்க்கப்பட்டது", "dateAdded": "தேதி சேர்க்கப்பட்டது",
"rating": "$t(common.rating)", "rating": "$t(common.rating)",
@@ -719,22 +1028,31 @@
"lastPlayed": "கடைசியாக விளையாடியது", "lastPlayed": "கடைசியாக விளையாடியது",
"note": "$t(common.note)", "note": "$t(common.note)",
"owner": "$t(common.owner)", "owner": "$t(common.owner)",
"actions": "$t(common.action_other)", "actions": "$t(common.action, {\"count\": 2})",
"albumArtist": "$t(entity.albumArtist, {\"count\": 1})", "albumArtist": "$t(entity.albumArtist, {\"count\": 1})",
"discNumber": "வட்டு எண்", "discNumber": "வட்டு எண்",
"duration": "$t(common.duration)", "duration": "$t(common.duration)",
"favorite": "$t(common.favorite)", "favorite": "$t(common.favourite)",
"genre": "$t(entity.genre, {\"count\": 1})", "genre": "$t(entity.genre, {\"count\": 1})",
"path": "$t(common.path)", "path": "$t(common.path)",
"playCount": "விளையாட்டு எண்ணிக்கை", "playCount": "விளையாட்டு எண்ணிக்கை",
"songCount": "$t(entity.track, {\"count\": 2})", "songCount": "$t(entity.track, {\"count\": 2})",
"title": "$t(common.title)", "title": "$t(common.title)",
"titleCombined": "$t(common.title) (இணைந்தது)" "titleCombined": "$t(common.title) (இணைந்தது)",
"albumGroup": "ஆல்பம் குழு",
"albumCount": "$t(entity.album, {\"count\": 2})",
"bitDepth": "$t(common.bitDepth)",
"composer": "இசையமைப்பாளர்",
"genreBadge": "$t(entity.genre, {\"count\": 1}) (பேட்ச்கள்)",
"image": "படம்",
"sampleRate": "$t(common.sampleRate)",
"titleArtist": "$t(common.title) (கலைஞர்)"
}, },
"view": { "view": {
"table": "அட்டவணை", "table": "அட்டவணை",
"grid": "வலைவாய்", "grid": "வலைவாய்",
"list": "பட்டியல்" "list": "பட்டியல்",
"detail": "விவரம்"
}, },
"general": { "general": {
"autoFitColumns": "ஆட்டோ பொருத்தம் நெடுவரிசைகள்", "autoFitColumns": "ஆட்டோ பொருத்தம் நெடுவரிசைகள்",
@@ -744,7 +1062,29 @@
"itemGap": "உருப்படி இடைவெளி (பிஎக்ச்)", "itemGap": "உருப்படி இடைவெளி (பிஎக்ச்)",
"itemSize": "உருப்படி அளவு (பிஎக்ச்)", "itemSize": "உருப்படி அளவு (பிஎக்ச்)",
"size": "$t(common.size)", "size": "$t(common.size)",
"tableColumns": "அட்டவணை நெடுவரிசைகள்" "tableColumns": "அட்டவணை நெடுவரிசைகள்",
"advancedSettings": "மேம்பட்ட அமைப்புகள்",
"autosize": "தானியங்கு அளவு",
"moveUp": "மேலே செல்ல",
"moveDown": "கீழே நகர",
"pinToLeft": "இடப்புறம் முள்",
"pinToRight": "வலதுபுறமாக முள்",
"alignLeft": "இடதுபுறம் சீரமைக்கவும்",
"alignCenter": "மையத்தை சீரமைக்கவும்",
"alignRight": "வலது சீரமை",
"itemsPerRow": "ஒரு வரிசைக்கு பொருட்கள்",
"size_default": "இயல்புநிலை",
"size_compact": "கச்சிதமான",
"size_large": "பெரிய",
"pagination": "பேசினேசன்",
"pagination_itemsPerPage": "ஒரு பக்கத்திற்கு உருப்படிகள்",
"pagination_infinite": "கந்தழி, முடிவிலி",
"pagination_paginate": "பக்கமாக",
"alternateRowColors": "மாற்று வரிசை வண்ணங்கள்",
"horizontalBorders": "வரிசை எல்லைகள்",
"rowHoverHighlight": "வரிசை மிதவை ஐலைட்",
"showHeader": "தலைப்பு நிகழ்ச்சி",
"verticalBorders": "நெடுவரிசை எல்லைகள்"
} }
}, },
"column": { "column": {
@@ -755,7 +1095,7 @@
"biography": "சுயசரிதை", "biography": "சுயசரிதை",
"bitrate": "பிட்ரேட்", "bitrate": "பிட்ரேட்",
"bpm": "பிபிஎம்", "bpm": "பிபிஎம்",
"channels": "$t(common.channel_other)", "channels": "$t(common.channel, {\"count\": 2})",
"codec": "$t(common.codec)", "codec": "$t(common.codec)",
"comment": "கருத்து", "comment": "கருத்து",
"dateAdded": "தேதி சேர்க்கப்பட்டது", "dateAdded": "தேதி சேர்க்கப்பட்டது",
@@ -771,7 +1111,218 @@
"size": "$t(common.size)", "size": "$t(common.size)",
"songCount": "$t(entity.track, {\"count\": 2})", "songCount": "$t(entity.track, {\"count\": 2})",
"title": "தலைப்பு", "title": "தலைப்பு",
"trackNumber": "மின்தடம்" "trackNumber": "மின்தடம்",
"bitDepth": "$t(common.bitDepth)",
"sampleRate": "$t(common.sampleRate)",
"owner": "உரிமையாளர்"
}
},
"datetime": {
"minuteShort": "மீ",
"secondShort": "கள்",
"hourShort": "ம",
"dayShort": "டி"
},
"filterOperator": {
"after": "பிறகு உள்ளது",
"afterDate": "பிறகு (தேதி)",
"before": "முன்பு உள்ளது",
"beforeDate": "முன் (தேதி)",
"contains": "கொண்டுள்ளது",
"endsWith": "உடன் முடிகிறது",
"inPlaylist": "உள்ளது",
"inTheLast": "கடைசியில் உள்ளது",
"inTheRange": "வரம்பில் உள்ளது",
"inTheRangeDate": "வரம்பில் உள்ளது (தேதி)",
"is": "உள்ளது",
"isNot": "இல்லை",
"isGreaterThan": "விட அதிகமாக உள்ளது",
"isLessThan": "விட குறைவாக உள்ளது",
"matchesRegex": "ரெசெக்சுடன் பொருந்துகிறது",
"notContains": "கொண்டிருக்கவில்லை",
"notInPlaylist": "உள்ளே இல்லை",
"notInTheLast": "கடைசியில் இல்லை",
"startsWith": "உடன் தொடங்குகிறது"
},
"queryBuilder": {
"standardTags": "நிலையான குறிச்சொற்கள்",
"customTags": "விருப்ப குறிச்சொற்கள்"
},
"releaseType": {
"primary": {
"album": "$t(entity.album, {\"count\": 1})",
"broadcast": "ஒளிபரப்பு",
"ep": "எபி",
"other": "மற்றொன்று",
"single": "ஒற்றை"
},
"secondary": {
"audiobook": "ஒலிப்புத்தகம்",
"audioDrama": "ஆடியோ நாடகம்",
"compilation": "தொகுத்தல்",
"djMix": "dj கலவை",
"demo": "டெமோ",
"fieldRecording": "களப்பதிவு",
"interview": "நேர்காணல்",
"live": "வாழ்க",
"mixtape": "கலவை",
"remix": "ரீமிக்ச்",
"soundtrack": "ஒலிப்பதிவு",
"spokenWord": "பேசப்பட்ட சொல்"
}
},
"dragDropZone": {
"error_oneFileOnly": "1 கோப்பை மட்டும் தேர்ந்தெடுக்கவும்",
"error_readingFile": "கோப்பைப் படிப்பதில் சிக்கல் உள்ளது: {{errorMessage}}",
"mainText": "ஒரு கோப்பை இங்கே விடுங்கள்"
},
"visualizer": {
"visualizerType": "விசுவலைசர் வகை",
"cyclePresets": "சுழற்சி முன்னமைவுகள்",
"cycleTime": "சுழற்சி நேரம் (வினாடிகள்)",
"includeAllPresets": "அனைத்து முன்னமைவுகளையும் சேர்க்கவும்",
"ignoredPresets": "புறக்கணிக்கப்பட்ட முன்னமைவுகள்",
"selectedPresets": "தேர்ந்தெடுக்கப்பட்ட முன்னமைவுகள்",
"randomizeNextPreset": "அடுத்த முன்னமைவை சீரமைக்கவும்",
"blendTime": "கலப்பு நேரம்",
"presets": "முன்னமைவுகள்",
"selectPreset": "முன்னமைவைத் தேர்ந்தெடுக்கவும்",
"applyPreset": "முன்னமைவைப் பயன்படுத்தவும்",
"saveAsPreset": "முன்னமைவாக சேமிக்கவும்",
"updatePreset": "முன்னமைவைப் புதுப்பிக்கவும்",
"copyConfiguration": "நகல் கட்டமைப்பு",
"pasteConfiguration": "ஒட்டு கட்டமைப்பு",
"pasteConfigurationPlaceholder": "சாதொபொகு உள்ளமைவை இங்கே ஒட்டவும்...",
"pasteFromClipboard": "கிளிப்போர்டில் இருந்து ஒட்டவும்",
"applyConfiguration": "உள்ளமைவைப் பயன்படுத்து",
"configCopied": "உள்ளமைவு இடைநிலைப்பலகைக்கு நகலெடுக்கப்பட்டது",
"configCopyFailed": "உள்ளமைவை நகலெடுக்க முடியவில்லை",
"configPasted": "உள்ளமைவு வெற்றிகரமாக பயன்படுத்தப்பட்டது",
"configPasteFailed": "உள்ளமைவைப் பயன்படுத்துவதில் தோல்வி. தயவுசெய்து வடிவமைப்பைச் சரிபார்க்கவும்.",
"configPasteReadFailed": "கிளிப்போர்டில் இருந்து படிக்க முடியவில்லை",
"presetName": "முன்னமைக்கப்பட்ட பெயர்",
"presetNamePlaceholder": "முன்னமைக்கப்பட்ட பெயரை உள்ளிடவும்",
"general": "பொது",
"mode": "பயன்முறை",
"mode1To8": "முறை 1 - 8",
"mode10": "முறை 10",
"barSpace": "பார் இடம்",
"lineWidth": "வரி அகலம்",
"fillAlpha": "ஆல்ஃபாவை நிரப்பவும்",
"channelLayout": "சேனல் தளவமைப்பு",
"maxFPS": "அதிகபட்ச FPS",
"opacity": "ஒளிபுகாநிலை",
"customGradients": "தனிப்பயன் சாய்வு",
"addCustomGradient": "தனிப்பயன் சாய்வு சேர்க்கவும்",
"gradientName": "சாய்வு பெயர்",
"gradientNamePlaceholder": "சாய்வு பெயர்",
"vertical": "செங்குத்து",
"horizontal": "கிடைமட்ட",
"colorStops": "வண்ண நிறுத்தங்கள்",
"addColor": "வண்ணத்தைச் சேர்க்கவும்",
"position": "பதவி",
"level": "நிலை",
"remove": "அகற்று",
"pasteGradient": "சாய்வு ஒட்டவும்",
"pasteGradientPlaceholder": "இங்கே சாய்வு சாதொபொகு ஒட்டவும்...",
"custom": "தனிப்பயன்",
"builtIn": "உள்ளமைக்கப்பட்ட",
"colors": "நிறங்கள்",
"colorMode": "வண்ண முறை",
"gradient": "சரிவு",
"gradientLeft": "கிரேடியன்ட் இடது",
"gradientRight": "கிரேடியன்ட் ரைட்",
"fft": "FFT",
"fftSize": "FFT அளவு",
"smoothing": "மென்மையாக்கும்",
"frequencyRangeAndScaling": "அதிர்வெண் வரம்பு மற்றும் அளவிடுதல்",
"minimumFrequency": "குறைந்தபட்ச அதிர்வெண்",
"maximumFrequency": "அதிகபட்ச அதிர்வெண்",
"frequencyScale": "அதிர்வெண் அளவுகோல்",
"sensitivity": "உணர்திறன்",
"weightingFilter": "எடை வடிகட்டி",
"minimumDecibels": "குறைந்தபட்ச டெசிபல்கள்",
"maximumDecibels": "அதிகபட்ச டெசிபல்கள்",
"linearAmplitude": "நேரியல் அலைவீச்சு",
"linearBoost": "லீனியர் பூச்ட்",
"peakBehavior": "உச்ச நடத்தை",
"showPeaks": "சிகரங்களைக் காட்டு",
"fadePeaks": "மங்கலான சிகரங்கள்",
"peakLine": "உச்சக் கோடு",
"gravity": "புவியீர்ப்பு",
"peakFadeTime": "பீக் ஃபேட் நேரம் (மிவி)",
"peakHoldTime": "பீக் ஓல்ட் நேரம் (மிவி)",
"radialSpectrum": "ரேடியல் ச்பெக்ட்ரம்",
"radial": "ரேடியல்",
"radialInvert": "ரேடியல் தலைகீழ்",
"spinSpeed": "சுழல் விரைவு",
"radius": "ஆரம்",
"reflexMirror": "ரிஃப்ளெக்ச் மிரர்",
"reflexFit": "ரிஃப்ளெக்ச் ஃபிட்",
"reflexRatio": "பிரதிபலிப்பு விகிதம்",
"reflexAlpha": "ரிஃப்ளெக்ச் ஆல்பா",
"reflexBrightness": "ரிஃப்ளெக்ச் ஒளி",
"mirror": "கண்ணாடி",
"miscellaneousSettings": "இதர அமைப்புகள்",
"alphaBars": "ஆல்பா பார்கள்",
"ansiBands": "ANSI பட்டைகள்",
"ledBars": "LED பார்கள்",
"trueLeds": "உண்மையான எல்.ஈ",
"lumiBars": "லுமி பார்கள்",
"outlineBars": "அவுட்லைன் பார்கள்",
"roundBars": "சுற்று பார்கள்",
"lowResolution": "குறைந்த தெளிவுத்திறன்",
"splitGradient": "பிளவு சாய்வு",
"showFPS": "FPS ஐக் காட்டு",
"showScaleX": "ஃச் அளவைக் காட்டு",
"noteLabels": "குறிப்பு லேபிள்கள்",
"showScaleY": "ஒய் அளவைக் காட்டு",
"options": {
"mode": {
"0": "[0] தனித்துவமான அதிர்வெண்கள்",
"1": "[1] 1/24வது ஆக்டேவ் / 240 பட்டைகள்",
"2": "[2] 1/12வது ஆக்டேவ் / 120 பட்டைகள்",
"3": "[3] 1/8 ஆக்டேவ் / 80 பட்டைகள்",
"4": "[4] 1/6வது ஆக்டேவ் / 60 பட்டைகள்",
"5": "[5] 1/4வது ஆக்டேவ் / 40 பட்டைகள்",
"6": "[6] 1/3 ஆக்டேவ் / 30 பட்டைகள்",
"7": "[7] அரை ஆக்டேவ் / 20 பட்டைகள்",
"8": "[8] முழு ஆக்டேவ் / 10 பட்டைகள்",
"10": "[10] கோடு / பகுதி வரைபடம்"
},
"colorMode": {
"gradient": "சரிவு",
"barIndex": "பார்-இண்டெக்ச்",
"barLevel": "பட்டை-நிலை"
},
"gradient": {
"classic": "கிளாசிக்",
"prism": "அரியம், பட்டகம்",
"rainbow": "வானவில்",
"steelblue": "இரும்புநீலம்",
"orangered": "ஆரஞ்சுசிவப்பு"
},
"channelLayout": {
"single": "ஒற்றை",
"dualCombined": "இரட்டை-இணைந்த",
"dualHorizontal": "இரட்டை-கிடைமட்ட",
"dualVertical": "இரட்டை-செங்குத்து"
},
"frequencyScale": {
"none": "எதுவுமில்லை",
"bark": "பட்டை அளவு",
"linear": "நேரியல் அளவுகோல்",
"log": "பதிவு அளவுகோல்",
"mel": "மெல் அளவுகோல்"
},
"weightingFilter": {
"none": "எதுவுமில்லை",
"a": "ஏ",
"b": "பி",
"c": "சி",
"d": "டி",
"z": "சட்"
}
} }
} }
} }
+1
View File
@@ -0,0 +1 @@
{}
+189 -8
View File
@@ -22,7 +22,7 @@
"holdToMoveToTop": "утримуйте, щоб перемістити вгору", "holdToMoveToTop": "утримуйте, щоб перемістити вгору",
"holdToMoveToBottom": "утримувати, щоб перемістити вниз", "holdToMoveToBottom": "утримувати, щоб перемістити вниз",
"moveItems": "перемістити елементи", "moveItems": "перемістити елементи",
"shuffle": "відтворити випадково", "shuffle": "перемішати",
"shuffleAll": "все випадково", "shuffleAll": "все випадково",
"shuffleSelected": "вибране випадково", "shuffleSelected": "вибране випадково",
"refresh": "$t(common.refresh)", "refresh": "$t(common.refresh)",
@@ -36,7 +36,10 @@
"openApplicationDirectory": "відкрити каталог додатків", "openApplicationDirectory": "відкрити каталог додатків",
"openIn": { "openIn": {
"lastfm": "Відкрити в Last.fm", "lastfm": "Відкрити в Last.fm",
"musicbrainz": "Відкрити в MusicBrainz" "musicbrainz": "Відкрити в MusicBrainz",
"listenbrainz": "Відкрити у ListenBrainz",
"qobuz": "Відкрити у Qobuz",
"spotify": "Відкрити у Spotify"
} }
}, },
"common": { "common": {
@@ -98,6 +101,7 @@
"forceRestartRequired": "перезапустіть, щоб застосувати зміни… закрийте повідомлення, щоб перезапустити", "forceRestartRequired": "перезапустіть, щоб застосувати зміни… закрийте повідомлення, щоб перезапустити",
"forward": "уперед", "forward": "уперед",
"gap": "прогалина", "gap": "прогалина",
"grouping": "групування",
"home": "додому", "home": "додому",
"increase": "збільшити", "increase": "збільшити",
"left": "ліво", "left": "ліво",
@@ -163,7 +167,9 @@
"explicit": "Експліцитний зміст", "explicit": "Експліцитний зміст",
"gridRows": "рядки сітки", "gridRows": "рядки сітки",
"tableColumns": "стовпці таблиці", "tableColumns": "стовпці таблиці",
"itemsMore": "{{count}} більше" "itemsMore": "{{count}} більше",
"numberOfResults": "{{numberOfResults}} результатів",
"newVersionAvailable": "доступна нова версія"
}, },
"entity": { "entity": {
"album_one": "альбом", "album_one": "альбом",
@@ -254,7 +260,9 @@
"serverRequired": "потрібен сервер", "serverRequired": "потрібен сервер",
"sessionExpiredError": "ваша сесія закінчилася", "sessionExpiredError": "ваша сесія закінчилася",
"systemFontError": "сталася помилка під час спроби отримати системні шрифти", "systemFontError": "сталася помилка під час спроби отримати системні шрифти",
"settingsSyncError": "виявлено розбіжності між налаштуваннями в рендерері та основним процесом. перезапустіть програму, щоб застосувати зміни" "settingsSyncError": "виявлено розбіжності між налаштуваннями в рендерері та основним процесом. перезапустіть програму, щоб застосувати зміни",
"invalidJson": "недійсний JSON",
"playbackPausedDueToError": "відтворення було призупинено через помилку"
}, },
"filter": { "filter": {
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
@@ -280,7 +288,7 @@
"isPublic": "є публічним", "isPublic": "є публічним",
"isRated": "є оціненим", "isRated": "є оціненим",
"isRecentlyPlayed": "нещодавно відтворено", "isRecentlyPlayed": "нещодавно відтворено",
"lastPlayed": "нещодавно відтворені", "lastPlayed": "останнє відтворене",
"mostPlayed": "найбільш відтворювані", "mostPlayed": "найбільш відтворювані",
"name": "назва", "name": "назва",
"note": "примітка", "note": "примітка",
@@ -300,7 +308,9 @@
"title": "назва", "title": "назва",
"toYear": "до року", "toYear": "до року",
"trackNumber": "трек", "trackNumber": "трек",
"explicitStatus": "$t(common.explicitStatus)" "explicitStatus": "$t(common.explicitStatus)",
"matchAnd": "і",
"matchOr": "або"
}, },
"datetime": { "datetime": {
"minuteShort": "хв.", "minuteShort": "хв.",
@@ -382,7 +392,6 @@
}, },
"editPlaylist": { "editPlaylist": {
"publicJellyfinNote": "Jellyfin з якоїсь причини не показує, чи є плейлист публічним чи ні. Якщо ви хочете, щоб він залишався публічним, виберіть варіант нижче", "publicJellyfinNote": "Jellyfin з якоїсь причини не показує, чи є плейлист публічним чи ні. Якщо ви хочете, щоб він залишався публічним, виберіть варіант нижче",
"editNote": "ручне редагування не рекомендується для великих плейлистів. ви впевнені, що готові прийняти ризик втрати даних, який виникає при перезапису існуючого плейлисту?",
"success": "$t(entity.playlist, {\"count\": 1}) успішно оновлено", "success": "$t(entity.playlist, {\"count\": 1}) успішно оновлено",
"title": "змінити $t(entity.playlist, {\"count\": 1})" "title": "змінити $t(entity.playlist, {\"count\": 1})"
}, },
@@ -414,10 +423,182 @@
"setExpiration": "встановити термін дії", "setExpiration": "встановити термін дії",
"success": "посилання для спільного використання скопійовано в буфер обміну (натисніть тут, щоб відкрити)", "success": "посилання для спільного використання скопійовано в буфер обміну (натисніть тут, щоб відкрити)",
"expireInvalid": "термін дії повинен бути в майбутньому", "expireInvalid": "термін дії повинен бути в майбутньому",
"createFailed": "не вдалося створити спільний доступ (чи ввімкнено спільний доступ?)" "createFailed": "не вдалося створити спільний доступ (чи ввімкнено спільний доступ?)",
"copyToClipboard": "Скопіювати до буфера обміну: Ctrl+C, Enter",
"successMustClick": "посилання успішно створено, натисніть сюди, щоб відкрити"
},
"shuffleAll": {
"title": "відтворити випадково",
"input_genre": "$t(entity.genre, {\"count\": 1})",
"input_limit": "скільки пісень?",
"input_minYear": "від року",
"input_maxYear": "до року",
"input_played": "відтворити фільтр",
"input_played_optionAll": "всі треки",
"input_played_optionUnplayed": "тільки не відтворені треки",
"input_played_optionPlayed": "тільки відтворені треки"
},
"updateServer": {
"success": "сервер успішно оновлено",
"title": "оновити сервер"
},
"privateMode": {
"enabled": "приватний режим увімкнено, стан відтворення тепер приховано від зовнішніх інтеграцій",
"disabled": "приватний режим вимкнено, стан відтворення тепер видно для увімкнених зовнішніх інтеграцій",
"title": "приватний режим"
},
"editRadioStation": {
"success": "радіо станція успішно оновлена"
} }
}, },
"player": { "player": {
"skip": "пропустити" "skip": "пропустити"
},
"page": {
"albumArtistDetail": {
"about": "Про {{artist}}",
"appearsOn": "з'являється на",
"favoriteSongs": "улюблені пісні",
"groupingTypeAll": "всі типи випуску",
"groupingTypePrimary": "основні типи випуску",
"recentReleases": "останні випуски",
"viewDiscography": "переглянути дискографію",
"relatedArtists": "подібні $t(entity.artist, {\"count\": 2})",
"topSongs": "найкращі пісні",
"topSongsCommunity": "спільнота",
"topSongsFrom": "найкращі пісні від {{title}}",
"topSongsPersonal": "особисте",
"favoriteSongsFrom": "улюблені пісні від {{title}}",
"viewAll": "показати все",
"viewAllTracks": "показати усі $t(entity.track, {\"count\": 2})"
},
"albumArtistList": {
"title": "$t(entity.albumArtist, {\"count\": 2})"
},
"albumDetail": {
"moreFromArtist": "більше від цього $t(entity.artist, {\"count\": 1})",
"moreFromGeneric": "більше від {{item}}",
"released": "видано"
},
"albumList": {
"artistAlbums": "альбоми виконавця {{artist}}",
"genreAlbums": "\"{{genre}}\" $t(entity.album, {\"count\": 2})",
"title": "$t(entity.album, {\"count\": 2})"
},
"radioList": {
"title": "радіостанції"
},
"releasenotes": {
"commitsSinceStable": "комміти від {{stable}}",
"noNewCommits": "немає нових коммітів у цьому періоді",
"noStableReleaseToCompare": "немає доступної стабільної версії для порівняння"
},
"favorites": {
"title": "$t(entity.favorite, {\"count\": 2})"
},
"windowBar": {
"paused": "(Призупинено) ",
"privateMode": "(Приватний режим)"
},
"appMenu": {
"collapseSidebar": "згорнути бічну панель",
"commandPalette": "відкрити палітру команд",
"expandSidebar": "розгорнути бічну панель",
"goBack": "повернутися назад",
"goForward": "перейти вперед",
"manageServers": "управління серверами",
"privateModeOff": "вимкнути приватний режим",
"privateModeOn": "увімкнути приватний режим",
"openBrowserDevtools": "відкрити інструменти розробника",
"quit": "$t(common.quit)",
"selectServer": "вибрати сервер",
"selectMusicFolder": "вибрати папку з музикою",
"noMusicFolder": "не вибрано папку з музикою",
"multipleMusicFolders": "Вибрано {{count}} папок з музикою",
"settings": "$t(common.setting, {\"count\": 2})",
"version": "версія {{version}}"
},
"manageServers": {
"title": "управління серверами",
"serverDetails": "інформація про сервер",
"url": "URL-адреса",
"username": "Ім'я користувача",
"editServerDetailsTooltip": "редагувати дані сервера",
"removeServer": "видалити сервер"
},
"contextMenu": {
"addFavorite": "$t(action.addToFavorites)",
"addLast": "$t(player.addLast)",
"addNext": "$t(player.addNext)",
"addToFavorites": "$t(action.addToFavorites)",
"addToPlaylist": "$t(action.addToPlaylist)",
"createPlaylist": "$t(action.createPlaylist)",
"deletePlaylist": "$t(action.deletePlaylist)",
"deselectAll": "$t(action.deselectAll)",
"download": "завантажити",
"moveItems": "$t(action.moveItems)",
"moveToNext": "$t(action.moveToNext)",
"moveToBottom": "$t(action.moveToBottom)",
"moveToTop": "$t(action.moveToTop)",
"numberSelected": "{{count}} вибрано",
"play": "$t(player.play)",
"playSimilarSongs": "$t(player.playSimilarSongs)",
"removeFromFavorites": "$t(action.removeFromFavorites)",
"removeFromPlaylist": "$t(action.removeFromPlaylist)",
"removeFromQueue": "$t(action.removeFromQueue)",
"setRating": "$t(action.setRating)",
"playShuffled": "$t(player.shuffle)",
"shareItem": "поділитися елементом",
"goTo": "перейти до",
"goToAlbum": "перейти до $t(entity.album, {\"count\": 1})",
"goToAlbumArtist": "перейти до $t(entity.albumArtist, {\"count\": 1})",
"showDetails": "отримати інформацію"
},
"fullscreenPlayer": {
"config": {
"dynamicBackground": "динамічний фон",
"dynamicImageBlur": "розмір розмиття зображення",
"dynamicIsImage": "включити фонове зображення",
"followCurrentLyric": "слідкувати за поточним рядком",
"lyricAlignment": "вирівнювання тексту",
"lyricOffset": "затримка тексту (мс)",
"lyricGap": "розмір між рядками",
"lyricSize": "розмір тексту",
"opacity": "непрозорість",
"showLyricMatch": "показувати збіг тексту пісень",
"showLyricProvider": "показувати джерело тексту пісень",
"synchronized": "синхронізовано",
"unsynchronized": "несинхронізовано",
"useImageAspectRatio": "використовувати співвідношення сторін зображення"
},
"lyrics": "текст пісні",
"related": "пов'язані",
"upNext": "далі",
"visualizer": "візуалізатор",
"noLyrics": "текст пісні не знайдено"
},
"genreList": {
"showAlbums": "показати $t(entity.genre, {\"count\": 1}) $t(entity.album, {\"count\": 2})",
"showTracks": "показати $t(entity.genre, {\"count\": 1}) $t(entity.track, {\"count\": 2})",
"title": "$t(entity.genre, {\"count\": 2})"
},
"folderList": {
"title": "$t(entity.folder, {\"count\": 2})"
},
"globalSearch": {
"commands": {
"goToPage": "перейти до сторінки",
"searchFor": "шукати на {{query}}",
"serverCommands": "команди сервера"
},
"title": "команди"
},
"home": {
"explore": "дослідити з вашої бібліотеки",
"genres": "$t(entity.genre, {\"count\": 2})",
"mostPlayed": "найбільш відтворені",
"newlyAdded": "нещодавно додані релізи",
"recentlyPlayed": "нещодавно відтворені"
}
} }
} }
+121 -24
View File
@@ -19,7 +19,10 @@
"goToPage": "前往页面", "goToPage": "前往页面",
"openIn": { "openIn": {
"lastfm": "在 Last.fm 中打开", "lastfm": "在 Last.fm 中打开",
"musicbrainz": "在 MusicBrainz 中打开" "musicbrainz": "在 MusicBrainz 中打开",
"listenbrainz": "在 ListenBrainz 中打开",
"qobuz": "在 Qobuz 中打开",
"spotify": "在 Spotify 中打开"
}, },
"moveToNext": "移至下一首", "moveToNext": "移至下一首",
"downloadStarted": "开始下载 {{count}} 个项目", "downloadStarted": "开始下载 {{count}} 个项目",
@@ -37,7 +40,8 @@
"selectAll": "全选", "selectAll": "全选",
"createRadioStation": "创建$t(entity.radioStation, {\"count\": 1})", "createRadioStation": "创建$t(entity.radioStation, {\"count\": 1})",
"deleteRadioStation": "删除$t(entity.radioStation, {\"count\": 1})", "deleteRadioStation": "删除$t(entity.radioStation, {\"count\": 1})",
"openApplicationDirectory": "打开应用程序目录" "openApplicationDirectory": "打开应用程序目录",
"goToCurrent": "转到当前项目"
}, },
"common": { "common": {
"increase": "增高", "increase": "增高",
@@ -74,7 +78,7 @@
"forward": "前进", "forward": "前进",
"delete": "删除", "delete": "删除",
"cancel": "取消", "cancel": "取消",
"forceRestartRequired": "重启应用使更改生效…关闭通知即可重启", "forceRestartRequired": "重启应用使更改生效…关闭通知即可重启",
"setting_other": "设置", "setting_other": "设置",
"version": "版本", "version": "版本",
"title": "标题", "title": "标题",
@@ -107,7 +111,7 @@
"duration": "时长", "duration": "时长",
"ok": "好", "ok": "好",
"no": "否", "no": "否",
"playerMustBePaused": "播放器必须暂停", "playerMustBePaused": "播放器必须暂停",
"channel_other": "频道", "channel_other": "频道",
"none": "无", "none": "无",
"disc": "碟片", "disc": "碟片",
@@ -155,7 +159,10 @@
"filter_single": "单项", "filter_single": "单项",
"mood": "氛围", "mood": "氛围",
"rename": "重命名", "rename": "重命名",
"filter_multiple": "多项" "filter_multiple": "多项",
"newVersionAvailable": "新版本现已可用",
"numberOfResults": "{{numberOfResults}} 结果",
"grouping": "分组"
}, },
"entity": { "entity": {
"albumArtist_other": "专辑艺术家", "albumArtist_other": "专辑艺术家",
@@ -218,7 +225,17 @@
"addNextShuffled": "下一个(随机)", "addNextShuffled": "下一个(随机)",
"artistRadio": "艺术家电台", "artistRadio": "艺术家电台",
"holdToShuffle": "按住即可随机", "holdToShuffle": "按住即可随机",
"trackRadio": "追踪广播" "trackRadio": "追踪广播",
"sleepTimer": "睡眠定时器",
"sleepTimer_endOfSong": "当前歌曲结束时",
"sleepTimer_minutes": "{{count}} 分钟",
"sleepTimer_hours": "{{count}} 小时",
"sleepTimer_custom": "自定义",
"sleepTimer_off": "关闭",
"sleepTimer_timeRemaining": "剩余时间 {{time}}",
"sleepTimer_setCustom": "设置定时器",
"sleepTimer_cancel": "取消定时器",
"albumRadio": "专辑电台"
}, },
"setting": { "setting": {
"crossfadeStyle_description": "选择用于音频播放器的淡入淡出风格", "crossfadeStyle_description": "选择用于音频播放器的淡入淡出风格",
@@ -249,7 +266,7 @@
"customFontPath_description": "设置应用使用的自定义字体路径", "customFontPath_description": "设置应用使用的自定义字体路径",
"gaplessAudio_optionWeak": "弱(推荐)", "gaplessAudio_optionWeak": "弱(推荐)",
"font_description": "设置应用使用的字体", "font_description": "设置应用使用的字体",
"audioDevice_description": "选择用于播放的音频设备(仅 web 播放器)", "audioDevice_description": "选择用于播放的音频设备",
"enableRemote_description": "启用远程控制服务器,以允许其他设备控制此应用", "enableRemote_description": "启用远程控制服务器,以允许其他设备控制此应用",
"remotePort_description": "设置远程服务器端口", "remotePort_description": "设置远程服务器端口",
"hotkey_skipBackward": "向后跳过", "hotkey_skipBackward": "向后跳过",
@@ -436,7 +453,7 @@
"discordServeImage": "从服务器提供 {{discord}} 图像", "discordServeImage": "从服务器提供 {{discord}} 图像",
"discordServeImage_description": "从服务器本身分享 {{discord}} rich presence 的封面艺术,仅适用于 Jellyfin 和 Navidrome。 {{discord}} 使用机器人来获取图像,因此您的服务器必须可通过公共互联网访问", "discordServeImage_description": "从服务器本身分享 {{discord}} rich presence 的封面艺术,仅适用于 Jellyfin 和 Navidrome。 {{discord}} 使用机器人来获取图像,因此您的服务器必须可通过公共互联网访问",
"musicbrainz": "显示 MusicBrainz 链接", "musicbrainz": "显示 MusicBrainz 链接",
"musicbrainz_description": "在存在 MusicBrainz ID 的艺术家/专辑页面上显示 MusicBrainz 链接", "musicbrainz_description": "在艺术家/专辑页面上显示 MusicBrainz 链接(如果存在 MusicBrainz ID",
"lastfm": "显示 last.fm 链接", "lastfm": "显示 last.fm 链接",
"lastfm_description": "在艺术家/专辑页面上显示 Last.fm 的链接", "lastfm_description": "在艺术家/专辑页面上显示 Last.fm 的链接",
"preferLocalLyrics_description": "优先选择本地歌词(如有),而不是远程歌词", "preferLocalLyrics_description": "优先选择本地歌词(如有),而不是远程歌词",
@@ -463,7 +480,7 @@
"releaseChannel_optionLatest": "最新的", "releaseChannel_optionLatest": "最新的",
"releaseChannel_optionBeta": "测试版", "releaseChannel_optionBeta": "测试版",
"releaseChannel": "发布通道", "releaseChannel": "发布通道",
"releaseChannel_description": "选择稳定版本或测试版以进行自动更新", "releaseChannel_description": "选择稳定版测试版或 Alpha(夜间构建版)以启用自动更新",
"mediaSession": "启用媒体会话", "mediaSession": "启用媒体会话",
"mediaSession_description": "启用媒体会话集成,在系统音量叠加层和锁屏界面显示媒体控件和元数据", "mediaSession_description": "启用媒体会话集成,在系统音量叠加层和锁屏界面显示媒体控件和元数据",
"exportImportSettings_control_description": "通过 JSON 导出和导入设置", "exportImportSettings_control_description": "通过 JSON 导出和导入设置",
@@ -562,7 +579,40 @@
"sidebarPlaylistListFilterRegex_placeholder": "例如:^每日精选*", "sidebarPlaylistListFilterRegex_placeholder": "例如:^每日精选*",
"sidebarPlaylistListFilterRegex": "播放列表筛选正则表达式", "sidebarPlaylistListFilterRegex": "播放列表筛选正则表达式",
"queryBuilder": "查询构建器", "queryBuilder": "查询构建器",
"queryBuilderCustomFields": "自定义字段" "queryBuilderCustomFields": "自定义字段",
"analyticsEnable": "发送基于使用情况的分析",
"analyticsEnable_description": "发送匿名使用数据帮助开发者改进应用程序",
"automaticUpdates": "自动更新",
"automaticUpdates_description": "自动检查并安装更新",
"releaseChannel_optionAlpha": "alpha(每日构建版)",
"discordStateIcon": "显示播放图标",
"discordStateIcon_description": "在 rich presence 状态中显示一个小的播放图标。启用“暂停时显示 rich presence 在线状态”后,暂停图标始终显示",
"blurExplicitImages": "模糊显式图片",
"blurExplicitImages_description": "专辑和歌曲封面若被标记为不雅内容,将会进行模糊处理",
"autosave": "自动保存播放队列",
"autosave_description": "启用自动将播放队列保存到服务器的功能。此功能仅在使用 Navidrome/Subsonic 时可用,且不能使用混合播放队列。",
"autosaveCount": "自动播放队列保存频率",
"autosaveCount_description": "队列保存前需要更改多少首歌曲?1(最少)表示每次歌曲更改",
"useThemePrimaryShade": "使用主题主色调",
"useThemePrimaryShade_description": "对于主要颜色变体,请使用所选主题中定义的主色调",
"primaryShade": "主色调",
"primaryShade_description": "覆盖按钮、链接和其他主色元素使用的主色调(0-9)",
"playerItemConfiguration_description": "配置全屏播放器上显示的项目及其显示顺序",
"playerItemConfiguration": "播放器项目配置",
"listenbrainz_description": "在艺术家/专辑页面上显示 ListenBrainz 链接",
"listenbrainz": "显示 ListenBrainz 链接",
"qobuz_description": "在艺术家/专辑页面上显示 Qobuz 链接",
"qobuz": "显示 Qobuz 链接",
"spotify_description": "在艺术家/专辑页面上显示 Spotify 链接",
"spotify": "显示 Spotify 链接",
"nativeSpotify_description": "在 Spotify 应用中打开,而不是在浏览器中打开",
"nativeSpotify": "使用 Spotify 应用",
"sidePlayQueueLayout": "侧边播放队列布局",
"sidePlayQueueLayout_description": "设置附加侧边播放队列的布局",
"sidePlayQueueLayout_optionHorizontal": "水平",
"sidePlayQueueLayout_optionVertical": "垂直",
"waveformLoadingDelay": "波形加载延迟",
"waveformLoadingDelay_description": "加载波形前的延迟时间(秒)。如果在使用网页播放器时遇到卡顿现象,请增加此值。"
}, },
"error": { "error": {
"remotePortWarning": "重启服务器使新端口生效", "remotePortWarning": "重启服务器使新端口生效",
@@ -593,7 +643,10 @@
"noNetwork": "服务器不可用", "noNetwork": "服务器不可用",
"noNetworkDescription": "无法连接到该服务器", "noNetworkDescription": "无法连接到该服务器",
"saveQueueFailed": "播放列表保存失败", "saveQueueFailed": "播放列表保存失败",
"settingsSyncError": "渲染器设置与主进程中存在差异,请重启程序以应用更改" "settingsSyncError": "渲染器设置与主进程中存在差异,请重启程序以应用更改",
"invalidJson": "无效的 JSON",
"serverLockSingleServer": "服务器锁定时,只允许一台服务器运行",
"playbackPausedDueToError": "发生错误,播放已暂停"
}, },
"filter": { "filter": {
"mostPlayed": "最多播放过", "mostPlayed": "最多播放过",
@@ -639,7 +692,9 @@
"duration": "时长", "duration": "时长",
"album": "$t(entity.album, {\"count\": 1})", "album": "$t(entity.album, {\"count\": 1})",
"explicitStatus": "$t(common.explicitStatus)", "explicitStatus": "$t(common.explicitStatus)",
"sortName": "排序名称" "sortName": "排序名称",
"matchAnd": "和",
"matchOr": "或"
}, },
"page": { "page": {
"sidebar": { "sidebar": {
@@ -808,7 +863,11 @@
"appearsOn": "出现在", "appearsOn": "出现在",
"viewAll": "查看全部", "viewAll": "查看全部",
"groupingTypeAll": "所有发行类型", "groupingTypeAll": "所有发行类型",
"groupingTypePrimary": "首选发布类型" "groupingTypePrimary": "首选发布类型",
"favoriteSongs": "收藏的歌曲",
"favoriteSongsFrom": "来自 {{title}} 收藏的歌曲",
"topSongsCommunity": "社区",
"topSongsPersonal": "个人"
}, },
"itemDetail": { "itemDetail": {
"copyPath": "将路径复制到剪贴板", "copyPath": "将路径复制到剪贴板",
@@ -842,6 +901,11 @@
"collections": { "collections": {
"overrideExisting": "覆盖现有", "overrideExisting": "覆盖现有",
"saveAsCollection": "保存为集合" "saveAsCollection": "保存为集合"
},
"releasenotes": {
"commitsSinceStable": "自 {{stable}} 以来的提交",
"noNewCommits": "此范围内没有新的提交",
"noStableReleaseToCompare": "目前没有稳定版本可供比较"
} }
}, },
"form": { "form": {
@@ -900,8 +964,7 @@
"editPlaylist": { "editPlaylist": {
"title": "编辑$t(entity.playlist, {\"count\": 1})", "title": "编辑$t(entity.playlist, {\"count\": 1})",
"publicJellyfinNote": "Jellyfin 出于某种原因不会显示播放列表是否公开。如果您希望保持公开,请选择以下输入", "publicJellyfinNote": "Jellyfin 出于某种原因不会显示播放列表是否公开。如果您希望保持公开,请选择以下输入",
"success": "$t(entity.playlist, {\"count\": 1})更新成功", "success": "$t(entity.playlist, {\"count\": 1})更新成功"
"editNote": "不建议对大型播放列表进行手动编辑,你确定接受新播放列表覆盖已有播放列表可能导致的数据丢失风险吗?"
}, },
"lyricSearch": { "lyricSearch": {
"title": "搜索歌词", "title": "搜索歌词",
@@ -914,7 +977,9 @@
"allowDownloading": "允许下载", "allowDownloading": "允许下载",
"description": "描述", "description": "描述",
"setExpiration": "设置过期时间", "setExpiration": "设置过期时间",
"success": "共享链接已复制到剪贴板(或单击此处打开)" "success": "共享链接已复制到剪贴板(或单击此处打开)",
"copyToClipboard": "复制到剪贴板:Ctrl+CEnter",
"successMustClick": "分享创建成功。点击此处打开"
}, },
"privateMode": { "privateMode": {
"enabled": "启用私人模式,播放状态现在对外部集成隐藏", "enabled": "启用私人模式,播放状态现在对外部集成隐藏",
@@ -950,6 +1015,9 @@
"input_played_optionPlayed": "仅已播放的曲目", "input_played_optionPlayed": "仅已播放的曲目",
"input_limit": "有多少首歌?", "input_limit": "有多少首歌?",
"input_played": "播放筛选器" "input_played": "播放筛选器"
},
"editRadioStation": {
"success": "电台更新成功"
} }
}, },
"table": { "table": {
@@ -989,7 +1057,8 @@
"view": { "view": {
"table": "表格", "table": "表格",
"grid": "网格", "grid": "网格",
"list": "列表" "list": "列表",
"detail": "详情"
}, },
"label": { "label": {
"releaseDate": "发布日期", "releaseDate": "发布日期",
@@ -1026,7 +1095,8 @@
"sampleRate": "$t(common.sampleRate)", "sampleRate": "$t(common.sampleRate)",
"genreBadge": "$t(entity.genre, {\"count\": 1})(徽章)", "genreBadge": "$t(entity.genre, {\"count\": 1})(徽章)",
"composer": "作曲家", "composer": "作曲家",
"titleArtist": "$t(common.title) (艺术家)" "titleArtist": "$t(common.title) (艺术家)",
"albumGroup": "专辑分组"
} }
}, },
"column": { "column": {
@@ -1162,21 +1232,41 @@
"miscellaneousSettings": "杂项设置", "miscellaneousSettings": "杂项设置",
"options": { "options": {
"channelLayout": { "channelLayout": {
"single": "单项" "single": "单项",
"dualCombined": "双重组合",
"dualHorizontal": "双水平",
"dualVertical": "双垂直"
}, },
"mode": { "mode": {
"0": "[0] 离散频率" "0": "[0] 离散频率",
"1": "[1] 1/24倍频程 / 240频段",
"2": "[2] 1/12 倍频程 / 120 频段",
"3": "[3] 1/8倍频程 / 80频段",
"4": "[4] 1/6倍频程 / 60频段",
"5": "[5] 1/4倍频程 / 40频段",
"6": "[6] 1/3倍频程 / 30频段",
"7": "[7] 半倍频程 / 20 频段",
"8": "[8] 全倍频程 / 10 频段",
"10": "[10] 折线图 / 面积图"
}, },
"colorMode": { "colorMode": {
"gradient": "渐变" "gradient": "渐变",
"barIndex": "Bar-Index",
"barLevel": "Bar-Level"
}, },
"gradient": { "gradient": {
"classic": "经典", "classic": "经典",
"prism": "棱镜", "prism": "棱镜",
"rainbow": "彩虹" "rainbow": "彩虹",
"steelblue": "钢蓝色",
"orangered": "橙红色"
}, },
"frequencyScale": { "frequencyScale": {
"none": "无" "none": "无",
"bark": "树皮鳞片",
"linear": "线性刻度",
"log": "对数刻度",
"mel": "梅尔刻度"
}, },
"weightingFilter": { "weightingFilter": {
"none": "无", "none": "无",
@@ -1234,7 +1324,14 @@
"splitGradient": "渐变分割", "splitGradient": "渐变分割",
"showScaleX": "显示比例尺 X", "showScaleX": "显示比例尺 X",
"noteLabels": "笔记标签", "noteLabels": "笔记标签",
"showScaleY": "显示比例尺 Y" "showScaleY": "显示比例尺 Y",
"alphaBars": "Alpha 条",
"ansiBands": "ANSI 频段",
"ledBars": "LED 灯条",
"trueLeds": "真正的LED",
"lumiBars": "Lumi 条",
"outlineBars": "轮廓栏",
"roundBars": "圆条"
}, },
"queryBuilder": { "queryBuilder": {
"standardTags": "标准标签", "standardTags": "标准标签",
+131 -59
View File
@@ -12,7 +12,7 @@
"delete": "刪除", "delete": "刪除",
"descending": "降冪", "descending": "降冪",
"description": "描述", "description": "描述",
"forceRestartRequired": "重新啟動應用程式使更改生效…關閉通知即可重啟", "forceRestartRequired": "重新啟動應用程式使更改生效…關閉通知即可重啟",
"menu": "選單", "menu": "選單",
"action_other": "操作", "action_other": "操作",
"add": "新增", "add": "新增",
@@ -39,7 +39,7 @@
"ok": "好", "ok": "好",
"owner": "所有者", "owner": "所有者",
"path": "路徑", "path": "路徑",
"playerMustBePaused": "播放器必須暫停", "playerMustBePaused": "播放器必須暫停",
"previousSong": "上一首$t(entity.track, {\"count\": 1})", "previousSong": "上一首$t(entity.track, {\"count\": 1})",
"quit": "退出", "quit": "退出",
"random": "隨機", "random": "隨機",
@@ -64,8 +64,8 @@
"cancel": "取消", "cancel": "取消",
"center": "中央", "center": "中央",
"channel_other": "聲道", "channel_other": "聲道",
"configure": "配置", "configure": "設定",
"create": "建", "create": "建",
"currentSong": "目前$t(entity.track, {\"count\": 1})", "currentSong": "目前$t(entity.track, {\"count\": 1})",
"minimize": "最小化", "minimize": "最小化",
"modified": "已修改", "modified": "已修改",
@@ -78,7 +78,7 @@
"newVersion": "已安裝新版本 ({{version}})", "newVersion": "已安裝新版本 ({{version}})",
"viewReleaseNotes": "查看發行註記", "viewReleaseNotes": "查看發行註記",
"albumGain": "專輯增益", "albumGain": "專輯增益",
"albumPeak": "專輯peak", "albumPeak": "專輯峰值",
"bitDepth": "位元深度", "bitDepth": "位元深度",
"close": "關閉", "close": "關閉",
"codec": "編碼", "codec": "編碼",
@@ -115,7 +115,10 @@
"rename": "重新命名", "rename": "重新命名",
"itemsMore": "{{count}} 更多", "itemsMore": "{{count}} 更多",
"filter_single": "單選", "filter_single": "單選",
"filter_multiple": "複選" "filter_multiple": "複選",
"newVersionAvailable": "有新的版本可供使用",
"numberOfResults": "{{numberOfResults}} 項結果",
"grouping": "分組"
}, },
"error": { "error": {
"endpointNotImplementedError": "{{serverType}} 尚未實現端點 {{endpoint}}", "endpointNotImplementedError": "{{serverType}} 尚未實現端點 {{endpoint}}",
@@ -124,13 +127,13 @@
"authenticationFailed": "驗證失敗", "authenticationFailed": "驗證失敗",
"credentialsRequired": "需要憑證", "credentialsRequired": "需要憑證",
"genericError": "發生了錯誤", "genericError": "發生了錯誤",
"invalidServer": "無效的服器", "invalidServer": "無效的服器",
"localFontAccessDenied": "無法取得本地字體", "localFontAccessDenied": "無法取得本地字體",
"loginRateError": "登請求嘗試次數過多,請稍後再試", "loginRateError": "登請求嘗試次數過多,請稍後再試",
"remoteDisableError": "$t(common.disable)遠端伺服器時出現錯誤", "remoteDisableError": "$t(common.disable)遠端伺服器時出現錯誤",
"remoteEnableError": "$t(common.enable)遠端伺服器時出現錯誤", "remoteEnableError": "$t(common.enable)遠端伺服器時出現錯誤",
"remotePortError": "設定遠端伺服器端口時發生錯誤", "remotePortError": "設定遠端伺服器連接埠時發生錯誤",
"remotePortWarning": "重啟伺服器使新端口生效", "remotePortWarning": "重啟伺服器使新連接埠生效",
"serverRequired": "需要伺服器", "serverRequired": "需要伺服器",
"sessionExpiredError": "工作階段已過期", "sessionExpiredError": "工作階段已過期",
"systemFontError": "嘗試取得系統字體時出現錯誤", "systemFontError": "嘗試取得系統字體時出現錯誤",
@@ -138,15 +141,18 @@
"mpvRequired": "需要 MPV", "mpvRequired": "需要 MPV",
"playbackError": "無法播放媒體", "playbackError": "無法播放媒體",
"badAlbum": "您看到此頁面是因為這首歌不是專輯的一部分。如果您的音樂資料夾頂層有一首歌,則很可能會看到此問題。 Jellyfin 僅將資料夾中的曲目分組", "badAlbum": "您看到此頁面是因為這首歌不是專輯的一部分。如果您的音樂資料夾頂層有一首歌,則很可能會看到此問題。 Jellyfin 僅將資料夾中的曲目分組",
"badValue": "無效選項{{value}}。該值不再存在", "badValue": "無效選項{{value}}。該值不再存在",
"networkError": "發生網路錯誤", "networkError": "發生網路錯誤",
"notificationDenied": "通知權限被拒絕。此設定無效", "notificationDenied": "通知權限被拒絕。此設定無效",
"openError": "無法開啟檔案", "openError": "無法開啟檔案",
"multipleServerSaveQueueError": "播放佇列中包含不是來自目前伺服器的歌曲,此操作不受支援", "multipleServerSaveQueueError": "播放佇列中包含不是來自目前伺服器的歌曲,此操作不受支援",
"saveQueueFailed": "儲存播放佇列失敗", "saveQueueFailed": "儲存播放佇列失敗",
"settingsSyncError": "偵測到渲染器與主程之間的設定不一致,請重新啟動應用程式以套用變更", "settingsSyncError": "偵測到渲染器與主程之間的設定不一致,請重新啟動應用程式以套用變更",
"noNetwork": "伺服器無法連線", "noNetwork": "伺服器無法連線",
"noNetworkDescription": "無法連接到此伺服器" "noNetworkDescription": "無法連接到此伺服器",
"invalidJson": "無效的 JSON",
"serverLockSingleServer": "當伺服器鎖定時只允許一個伺服器",
"playbackPausedDueToError": "發生錯誤,已停止播放"
}, },
"page": { "page": {
"contextMenu": { "contextMenu": {
@@ -195,7 +201,7 @@
"genres": "$t(entity.genre, {\"count\": 2})" "genres": "$t(entity.genre, {\"count\": 2})"
}, },
"appMenu": { "appMenu": {
"openBrowserDevtools": "開瀏覽器開發者工具", "openBrowserDevtools": "開瀏覽器開發者工具",
"collapseSidebar": "折疊側邊欄", "collapseSidebar": "折疊側邊欄",
"expandSidebar": "展開側邊欄", "expandSidebar": "展開側邊欄",
"goBack": "返回", "goBack": "返回",
@@ -227,7 +233,9 @@
"showLyricMatch": "顯示匹配的歌詞", "showLyricMatch": "顯示匹配的歌詞",
"dynamicImageBlur": "圖片模糊大小", "dynamicImageBlur": "圖片模糊大小",
"dynamicIsImage": "啟用背景圖片", "dynamicIsImage": "啟用背景圖片",
"lyricOffset": "歌詞偏移時間 (ms)" "lyricOffset": "歌詞偏移時間 (ms)",
"lyricOpacityNonActive": "非活躍歌詞的不透明度",
"lyricScaleNonActive": "非活躍歌詞的比例"
}, },
"lyrics": "歌詞", "lyrics": "歌詞",
"related": "相關", "related": "相關",
@@ -399,7 +407,17 @@
"restoreQueueFromServer": "從伺服器還原播放佇列", "restoreQueueFromServer": "從伺服器還原播放佇列",
"saveQueueToServer": "將播放佇列儲存至伺服器", "saveQueueToServer": "將播放佇列儲存至伺服器",
"artistRadio": "藝人電台", "artistRadio": "藝人電台",
"trackRadio": "曲目電台" "trackRadio": "曲目電台",
"sleepTimer": "睡眠定時器",
"sleepTimer_endOfSong": "歌曲播完時",
"sleepTimer_minutes": "{{count}} 分鐘",
"sleepTimer_hours": "{{count}} 小時",
"sleepTimer_custom": "自訂",
"sleepTimer_off": "關閉",
"sleepTimer_timeRemaining": "剩餘 {{time}}",
"sleepTimer_setCustom": "設定定時器",
"sleepTimer_cancel": "取消定時器",
"albumRadio": "專輯電台"
}, },
"setting": { "setting": {
"audioPlayer_description": "選擇用於播放的音訊播放器", "audioPlayer_description": "選擇用於播放的音訊播放器",
@@ -415,9 +433,9 @@
"applicationHotkeys": "應用程式快捷鍵", "applicationHotkeys": "應用程式快捷鍵",
"applicationHotkeys_description": "設定應用程式快捷鍵。切換勾選框來設為全域快捷鍵(僅桌面端)", "applicationHotkeys_description": "設定應用程式快捷鍵。切換勾選框來設為全域快捷鍵(僅桌面端)",
"audioDevice": "音訊設備", "audioDevice": "音訊設備",
"audioDevice_description": "選擇用於播放的音訊設備(僅 web 播放器)", "audioDevice_description": "選擇用於播放的音訊設備",
"audioExclusiveMode": "音訊獨模式", "audioExclusiveMode": "音訊獨模式",
"audioExclusiveMode_description": "啟用獨輸出模式。在此模式下,系統通常被鎖定,只有 mpv 能夠輸出音訊", "audioExclusiveMode_description": "啟用獨輸出模式。在此模式下,系統通常被鎖定,只有 mpv 能夠輸出音訊。視覺化音訊截取在此選項啟用時不會作用",
"audioPlayer": "音訊播放器", "audioPlayer": "音訊播放器",
"crossfadeDuration": "淡入淡出持續時間", "crossfadeDuration": "淡入淡出持續時間",
"crossfadeDuration_description": "設定淡入淡出持續時間", "crossfadeDuration_description": "設定淡入淡出持續時間",
@@ -490,7 +508,7 @@
"playButtonBehavior_description": "設定歌曲新增到佇列時播放按鈕的預設動作", "playButtonBehavior_description": "設定歌曲新增到佇列時播放按鈕的預設動作",
"playButtonBehavior_optionAddLast": "$t(player.addLast)", "playButtonBehavior_optionAddLast": "$t(player.addLast)",
"playButtonBehavior_optionAddNext": "$t(player.addNext)", "playButtonBehavior_optionAddNext": "$t(player.addNext)",
"remotePort": "遠端控制伺服器端口", "remotePort": "遠端控制伺服器連接埠",
"remoteUsername": "遠端控制伺服器使用者名稱", "remoteUsername": "遠端控制伺服器使用者名稱",
"replayGainClipping": "{{ReplayGain}}削波", "replayGainClipping": "{{ReplayGain}}削波",
"replayGainFallback": "{{ReplayGain}}後備替代", "replayGainFallback": "{{ReplayGain}}後備替代",
@@ -504,7 +522,7 @@
"replayGainPreamp_description": "調整使用在{{ReplayGain}}值上的前置放大增益", "replayGainPreamp_description": "調整使用在{{ReplayGain}}值上的前置放大增益",
"savePlayQueue": "儲存播放佇列", "savePlayQueue": "儲存播放佇列",
"sampleRate_description": "如果選擇的取樣率與目前媒體的取樣率不同,請選擇要使用的輸出取樣率。小於 8000 的值將使用預設頻率", "sampleRate_description": "如果選擇的取樣率與目前媒體的取樣率不同,請選擇要使用的輸出取樣率。小於 8000 的值將使用預設頻率",
"savePlayQueue_description": "當應用程式關閉時儲存播放佇列,並在應用程式開時恢複它", "savePlayQueue_description": "當應用程式關閉時儲存播放佇列,並在應用程式開時恢複它",
"scrobble": "記錄播放資訊(Scrobble", "scrobble": "記錄播放資訊(Scrobble",
"scrobble_description": "在你的媒體伺服器中記錄播放資訊", "scrobble_description": "在你的媒體伺服器中記錄播放資訊",
"showSkipButton": "顯示跳過按鈕", "showSkipButton": "顯示跳過按鈕",
@@ -516,13 +534,13 @@
"sidebarConfiguration_description": "選擇側邊欄包含的項目與順序", "sidebarConfiguration_description": "選擇側邊欄包含的項目與順序",
"sidebarPlaylistList_description": "顯示或隱藏側邊欄歌單清單", "sidebarPlaylistList_description": "顯示或隱藏側邊欄歌單清單",
"sidePlayQueueStyle": "側邊播放佇列樣式", "sidePlayQueueStyle": "側邊播放佇列樣式",
"sidePlayQueueStyle_description": "設側邊播放佇列樣式", "sidePlayQueueStyle_description": "設側邊播放佇列樣式",
"sidePlayQueueStyle_optionAttached": "吸附", "sidePlayQueueStyle_optionAttached": "吸附",
"sidePlayQueueStyle_optionDetached": "分離", "sidePlayQueueStyle_optionDetached": "分離",
"skipDuration": "跳過時長", "skipDuration": "跳過時長",
"skipDuration_description": "設每次按下跳過按鈕將會跳過的時長", "skipDuration_description": "設每次按下跳過按鈕將會跳過的時長",
"skipPlaylistPage": "跳過播放清單頁面", "skipPlaylistPage": "跳過播放清單頁面",
"skipPlaylistPage_description": "開播放清單時,直接查看歌曲列表而非查看預設頁面", "skipPlaylistPage_description": "開播放清單時,直接查看歌曲列表而非查看預設頁面",
"theme": "主題", "theme": "主題",
"themeDark": "主題(深色)", "themeDark": "主題(深色)",
"useSystemTheme_description": "使用系統定義的淺色或深色主題", "useSystemTheme_description": "使用系統定義的淺色或深色主題",
@@ -550,25 +568,25 @@
"playButtonBehavior_optionPlay": "$t(player.play)", "playButtonBehavior_optionPlay": "$t(player.play)",
"remotePassword": "遠端控制伺服器密碼", "remotePassword": "遠端控制伺服器密碼",
"remotePassword_description": "設定遠端控制伺服器的密碼。這些憑證預設以不安全的方式傳輸,因此您應該使用一個您不在意的唯一密碼", "remotePassword_description": "設定遠端控制伺服器的密碼。這些憑證預設以不安全的方式傳輸,因此您應該使用一個您不在意的唯一密碼",
"remotePort_description": "設定遠端控制伺服器的端口", "remotePort_description": "設定遠端控制伺服器的連接埠",
"remoteUsername_description": "設定遠端控制伺服器的使用者名稱。如果使用者名稱和密碼都為空,則身驗證將被禁用", "remoteUsername_description": "設定遠端控制伺服器的使用者名稱。如果使用者名稱和密碼都為空,則身驗證將被禁用",
"replayGainClipping_description": "自動降低增益以防止{{ReplayGain}}造成削波", "replayGainClipping_description": "自動降低增益以防止{{ReplayGain}}造成削波",
"showSkipButtons": "顯示跳過按鈕", "showSkipButtons": "顯示跳過按鈕",
"themeDark_description": "應用程式將使用深色主題", "themeDark_description": "應用程式將使用深色主題",
"clearQueryCache_description": "Feishin的軟清除。這將會刷新播放清單、曲目標籤並重置儲存的歌詞。會保留設定、伺服器憑證和暫存圖片", "clearQueryCache_description": "Feishin的軟清除。這將會刷新播放清單、曲目標籤並重置儲存的歌詞。會保留設定、伺服器憑證和暫存圖片",
"clearCache": "清除瀏覽器快取", "clearCache": "清除瀏覽器快取",
"clearCache_description": "Feishin的硬清除。除了清除Feishin的快取、清除瀏覽器快取(儲存的圖片和其他資源)。會保留伺服器憑證和設定", "clearCache_description": "Feishin的硬清除。除了清除Feishin的快取、清除瀏覽器快取(儲存的圖片和其他資源)。會保留伺服器憑證和設定",
"clearQueryCache": "清除Feishin快取", "clearQueryCache": "清除Feishin快取",
"buttonSize": "播放器欄按鈕大小", "buttonSize": "播放器欄按鈕大小",
"buttonSize_description": "播放器欄按鈕大小", "buttonSize_description": "播放器欄按鈕大小",
"albumBackground": "專輯背景圖片", "albumBackground": "專輯背景圖片",
"albumBackground_description": "為包含專輯封面的專輯頁面新增背景圖片", "albumBackground_description": "為包含專輯封面的專輯頁面新增背景圖片",
"albumBackgroundBlur": "專輯背景圖片模糊大小", "albumBackgroundBlur": "專輯背景圖片模糊大小",
"albumBackgroundBlur_description": "調整應用於專輯背景圖片的模糊量", "albumBackgroundBlur_description": "調整應用程式於專輯背景圖片的模糊量",
"artistConfiguration": "專輯藝人頁面設定", "artistConfiguration": "專輯藝人頁面設定",
"artistConfiguration_description": "設定專輯藝人頁面中顯示的項目及排序", "artistConfiguration_description": "設定專輯藝人頁面中顯示的項目及排序",
"clearCacheSuccess": "成功清除快取", "clearCacheSuccess": "成功清除快取",
"contextMenu": "右鍵選單配置", "contextMenu": "右鍵選單設定",
"contextMenu_description": "允許您隱藏在右鍵選單項目時顯示的項目。未選取的項目將被隱藏", "contextMenu_description": "允許您隱藏在右鍵選單項目時顯示的項目。未選取的項目將被隱藏",
"customCssEnable": "啟用自訂CSS", "customCssEnable": "啟用自訂CSS",
"customCssEnable_description": "允許撰寫自訂CSS", "customCssEnable_description": "允許撰寫自訂CSS",
@@ -585,8 +603,8 @@
"externalLinks_description": "在藝人/專輯頁面顯示外部連結(Last.fm, MusicBrainz)", "externalLinks_description": "在藝人/專輯頁面顯示外部連結(Last.fm, MusicBrainz)",
"preferLocalLyrics": "偏好本地歌詞", "preferLocalLyrics": "偏好本地歌詞",
"preferLocalLyrics_description": "優先選擇本地歌詞,而不是遠端歌詞(如果可用)", "preferLocalLyrics_description": "優先選擇本地歌詞,而不是遠端歌詞(如果可用)",
"homeConfiguration": "首頁配置", "homeConfiguration": "首頁設定",
"homeConfiguration_description": "配置在首頁上顯示哪些項目以及顯示順序", "homeConfiguration_description": "設定在首頁上顯示哪些項目以及顯示順序",
"homeFeature": "首頁特色輪播", "homeFeature": "首頁特色輪播",
"homeFeature_description": "控制是否在首頁上顯示大型特色輪播", "homeFeature_description": "控制是否在首頁上顯示大型特色輪播",
"imageAspectRatio": "使用原生封面照長寬比", "imageAspectRatio": "使用原生封面照長寬比",
@@ -608,14 +626,14 @@
"startMinimized": "啟動時最小化", "startMinimized": "啟動時最小化",
"startMinimized_description": "在系統匣中啟動應用程式", "startMinimized_description": "在系統匣中啟動應用程式",
"transcode_description": "啟用轉碼到不同格式", "transcode_description": "啟用轉碼到不同格式",
"transcodeBitrate": "要轉碼的比特率", "transcodeBitrate": "要轉碼的位元率",
"transcodeBitrate_description": "選擇要轉碼的比特率。 0 表示讓伺服器選擇", "transcodeBitrate_description": "選擇要轉碼的位元率。 0 表示讓伺服器選擇",
"transcodeFormat": "轉碼的格式", "transcodeFormat": "轉碼的格式",
"transcodeFormat_description": "選擇要轉碼的格式。留空來讓伺服器決定", "transcodeFormat_description": "選擇要轉碼的格式。留空來讓伺服器決定",
"translationApiProvider": "翻譯API提供者", "translationApiProvider": "翻譯API提供者",
"translationApiProvider_description": "翻譯API的提供者", "translationApiProvider_description": "翻譯API的提供者",
"translationApiKey": "翻譯API金鑰", "translationApiKey": "翻譯API金鑰",
"translationApiKey_description": "翻譯的API金鑰(僅限全域服端點)", "translationApiKey_description": "翻譯的API金鑰(僅限全域服端點)",
"translationTargetLanguage": "目標翻譯語言", "translationTargetLanguage": "目標翻譯語言",
"translationTargetLanguage_description": "翻譯的目標語言", "translationTargetLanguage_description": "翻譯的目標語言",
"trayEnabled": "顯示系統匣", "trayEnabled": "顯示系統匣",
@@ -746,7 +764,41 @@
"sidebarPlaylistListFilterRegex": "播放清單過濾器正規表達式", "sidebarPlaylistListFilterRegex": "播放清單過濾器正規表達式",
"blurExplicitImages": "模糊露骨圖片", "blurExplicitImages": "模糊露骨圖片",
"blurExplicitImages_description": "標記為露骨的專輯和歌曲封面將被模糊", "blurExplicitImages_description": "標記為露骨的專輯和歌曲封面將被模糊",
"releaseChannel_optionAlpha": "alpha (每日建構版)" "releaseChannel_optionAlpha": "alpha (每日建構版)",
"analyticsEnable": "傳送基於使用情況的分析報告",
"analyticsEnable_description": "匿名化的使用情況資料會傳送給開發者,以協助改進應用程式",
"automaticUpdates": "自動更新",
"automaticUpdates_description": "自動檢查並安裝更新",
"discordStateIcon": "顯示播放中圖示",
"discordStateIcon_description": "在 rich presence 狀態中顯示一個小的播放圖示。啟用「暫停時顯示 rich presence」時,會始終顯示暫停的圖示",
"useThemePrimaryShade": "套用主題主色調",
"useThemePrimaryShade_description": "使用所選主題中定義的主色調作為主色變體",
"primaryShade": "主要色調",
"primaryShade_description": "覆蓋按鈕、連結及其他主色調元素所使用的主色調(0–9)",
"playerItemConfiguration_description": "設定全螢幕播放器顯示的項目及排列順序",
"playerItemConfiguration": "播放器項目設定",
"autosave": "自動儲存播放佇列",
"autosave_description": "啟用自動將播放佇列儲存到您的伺服器。這只有在使用Navidrome/Subsonic時才可使用,並且您不能有混合播放佇列。",
"autosaveCount": "自動播放佇列儲存頻率",
"autosaveCount_description": "在儲存佇列之前,有多少曲目更改。1(最小)表示每次歌曲更改",
"spotify_description": "在藝人與專輯頁面顯示 Spotify 的連結",
"spotify": "顯示 Spotify 的連結",
"nativeSpotify_description": "在 Spotify 應用程式中開啟,而非在瀏覽器中開啟",
"nativeSpotify": "使用 Spotify 應用程式",
"sidePlayQueueLayout": "側邊播放佇列佈局",
"sidePlayQueueLayout_description": "設定吸附側邊播放佇列的佈局",
"sidePlayQueueLayout_optionHorizontal": "水平",
"sidePlayQueueLayout_optionVertical": "垂直",
"listenbrainz_description": "在藝術家/專輯頁面上顯示 ListenBrainz 的連結",
"listenbrainz": "顯示 ListenBrainz 連結",
"qobuz_description": "在藝術家/專輯頁面上顯示 Qobuz 的連結",
"qobuz": "顯示 Qobuz 連結",
"waveformLoadingDelay": "波形載入延遲",
"waveformLoadingDelay_description": "載入波形前的延遲(以秒為單位)。如果您在使用網頁播放器時遇到卡頓,請增加此值。",
"playerbarWaveformStretch": "波形拉伸",
"playerbarWaveformStretch_description": "拉伸波形來填補可用空間",
"preventSuspendOnPlayback_description": "音樂播放時防止應用程式進入休眠",
"preventSuspendOnPlayback": "在播放時防止應用程式暫停"
}, },
"table": { "table": {
"config": { "config": {
@@ -755,7 +807,7 @@
"gap": "$t(common.gap)", "gap": "$t(common.gap)",
"size": "$t(common.size)", "size": "$t(common.size)",
"tableColumns": "列", "tableColumns": "列",
"autoFitColumns": "列寬自適應", "autoFitColumns": "自動調整列寬",
"followCurrentSong": "跟隨目前歌曲", "followCurrentSong": "跟隨目前歌曲",
"itemGap": "項目間隔 (px)", "itemGap": "項目間隔 (px)",
"itemSize": "項目大小 (px)", "itemSize": "項目大小 (px)",
@@ -817,12 +869,14 @@
"bitDepth": "$t(common.bitDepth)", "bitDepth": "$t(common.bitDepth)",
"sampleRate": "$t(common.sampleRate)", "sampleRate": "$t(common.sampleRate)",
"composer": "作曲者", "composer": "作曲者",
"titleArtist": "$t(common.title) (藝人)" "titleArtist": "$t(common.title) (藝人)",
"albumGroup": "專輯分組"
}, },
"view": { "view": {
"table": "表格", "table": "表格",
"grid": "網格", "grid": "網格",
"list": "列表" "list": "列表",
"detail": "詳情"
} }
}, },
"column": { "column": {
@@ -831,7 +885,7 @@
"albumCount": "$t(entity.album, {\"count\": 2})", "albumCount": "$t(entity.album, {\"count\": 2})",
"artist": "$t(entity.artist, {\"count\": 1})", "artist": "$t(entity.artist, {\"count\": 1})",
"biography": "簡介", "biography": "簡介",
"bitrate": "比特率", "bitrate": "位元率",
"channels": "$t(common.channel, {\"count\": 2})", "channels": "$t(common.channel, {\"count\": 2})",
"comment": "評論", "comment": "評論",
"dateAdded": "新增日期", "dateAdded": "新增日期",
@@ -858,7 +912,7 @@
"action": { "action": {
"addToFavorites": "新增到$t(entity.favorite, {\"count\": 2})", "addToFavorites": "新增到$t(entity.favorite, {\"count\": 2})",
"clearQueue": "清空播放佇列", "clearQueue": "清空播放佇列",
"createPlaylist": "建$t(entity.playlist, {\"count\": 1})", "createPlaylist": "建$t(entity.playlist, {\"count\": 1})",
"deletePlaylist": "刪除$t(entity.playlist, {\"count\": 1})", "deletePlaylist": "刪除$t(entity.playlist, {\"count\": 1})",
"addToPlaylist": "新增到$t(entity.playlist, {\"count\": 1})", "addToPlaylist": "新增到$t(entity.playlist, {\"count\": 1})",
"deselectAll": "取消全選", "deselectAll": "取消全選",
@@ -876,7 +930,10 @@
"moveToNext": "移至下一項", "moveToNext": "移至下一項",
"openIn": { "openIn": {
"lastfm": "在Last.fm開啟", "lastfm": "在Last.fm開啟",
"musicbrainz": "在MusicBrainz開啟" "musicbrainz": "在MusicBrainz開啟",
"spotify": "在 Spotify 中開啟",
"listenbrainz": "在 ListenBrainz 中開啟",
"qobuz": "在 Qobuz 中開啟"
}, },
"downloadStarted": "已開始下載 {{count}} 項內容", "downloadStarted": "已開始下載 {{count}} 項內容",
"moveItems": "移動項目", "moveItems": "移動項目",
@@ -888,12 +945,13 @@
"moveDown": "向下移動", "moveDown": "向下移動",
"holdToMoveToTop": "按住以移動至頂部", "holdToMoveToTop": "按住以移動至頂部",
"holdToMoveToBottom": "按住以移動至底部", "holdToMoveToBottom": "按住以移動至底部",
"createRadioStation": "建 $t(entity.radioStation, {\"count\": 1})", "createRadioStation": "建 $t(entity.radioStation, {\"count\": 1})",
"deleteRadioStation": "刪除 $t(entity.radioStation, {\"count\": 1})", "deleteRadioStation": "刪除 $t(entity.radioStation, {\"count\": 1})",
"openApplicationDirectory": "開啟應用程式目錄", "openApplicationDirectory": "開啟應用程式目錄",
"addOrRemoveFromSelection": "新增或移除選取項目", "addOrRemoveFromSelection": "新增或移除選取項目",
"selectAll": "全選", "selectAll": "全選",
"selectRangeOfItems": "批量選取" "selectRangeOfItems": "批量選取",
"goToCurrent": "前往當前項目"
}, },
"entity": { "entity": {
"album_other": "專輯", "album_other": "專輯",
@@ -921,7 +979,7 @@
"albumCount": "$t(entity.album, {\"count\": 2})數", "albumCount": "$t(entity.album, {\"count\": 2})數",
"artist": "$t(entity.artist, {\"count\": 1})", "artist": "$t(entity.artist, {\"count\": 1})",
"biography": "個人簡介", "biography": "個人簡介",
"bitrate": "比特率", "bitrate": "位元率",
"bpm": "bpm", "bpm": "bpm",
"channels": "$t(common.channel, {\"count\": 2})", "channels": "$t(common.channel, {\"count\": 2})",
"comment": "評論", "comment": "評論",
@@ -961,7 +1019,9 @@
"toYear": "從年份", "toYear": "從年份",
"trackNumber": "曲目", "trackNumber": "曲目",
"explicitStatus": "$t(common.explicitStatus)", "explicitStatus": "$t(common.explicitStatus)",
"sortName": "排序名稱" "sortName": "排序名稱",
"matchAnd": "和",
"matchOr": "或"
}, },
"form": { "form": {
"addServer": { "addServer": {
@@ -977,7 +1037,7 @@
"ignoreCors": "忽略 cors $t(common.restartRequired)", "ignoreCors": "忽略 cors $t(common.restartRequired)",
"ignoreSsl": "忽略 ssl $t(common.restartRequired)", "ignoreSsl": "忽略 ssl $t(common.restartRequired)",
"input_preferInstantMix": "偏好即時混音", "input_preferInstantMix": "偏好即時混音",
"input_preferInstantMixDescription": "僅使用即時混音功能來取相似歌曲。若您擁有能修改此行為的外掛,此功能將相當實用", "input_preferInstantMixDescription": "僅使用即時混音功能來取相似歌曲。若您擁有能修改此行為的外掛,此功能將相當實用",
"input_preferRemoteUrl": "優先使用公開網址", "input_preferRemoteUrl": "優先使用公開網址",
"input_remoteUrl": "公開網址", "input_remoteUrl": "公開網址",
"input_remoteUrlPlaceholder": "選用:對外功能的公開網址" "input_remoteUrlPlaceholder": "選用:對外功能的公開網址"
@@ -987,16 +1047,17 @@
"input_skipDuplicates": "跳過重複", "input_skipDuplicates": "跳過重複",
"success": "新增 $t(entity.trackWithCount, {\"count\": {{message}} }) 到 $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} })", "success": "新增 $t(entity.trackWithCount, {\"count\": {{message}} }) 到 $t(entity.playlistWithCount, {\"count\": {{numOfPlaylists}} })",
"title": "新增到$t(entity.playlist, {\"count\": 1})", "title": "新增到$t(entity.playlist, {\"count\": 1})",
"create": "建 $t(entity.playlist, {\"count\": 1}) {{playlist}}", "create": "建 $t(entity.playlist, {\"count\": 1}) {{playlist}}",
"searchOrCreate": "搜尋$t(entity.playlist, {\"count\": 2}) 或輸入內容以建立新項目" "searchOrCreate": "搜尋$t(entity.playlist, {\"count\": 2}) 或輸入內容以建立新項目",
"noneAdded": "沒有曲目新增到 $t(entity.playlist, {\"count\": 1}) '{{playlist}}'"
}, },
"createPlaylist": { "createPlaylist": {
"input_description": "$t(common.description)", "input_description": "$t(common.description)",
"input_name": "$t(common.name)", "input_name": "$t(common.name)",
"input_owner": "$t(common.owner)", "input_owner": "$t(common.owner)",
"input_public": "公開", "input_public": "公開",
"success": "已成功建 $t(entity.playlist, {\"count\": 1})", "success": "已成功建 $t(entity.playlist, {\"count\": 1})",
"title": "建$t(entity.playlist, {\"count\": 1})" "title": "建$t(entity.playlist, {\"count\": 1})"
}, },
"lyricSearch": { "lyricSearch": {
"input_name": "$t(common.name)", "input_name": "$t(common.name)",
@@ -1024,8 +1085,7 @@
"editPlaylist": { "editPlaylist": {
"title": "編輯$t(entity.playlist, {\"count\": 1})", "title": "編輯$t(entity.playlist, {\"count\": 1})",
"publicJellyfinNote": "Jellyfin 出於某種原因,不會顯示播放清單是否公開。如果您希望保持公開狀態,請選擇以下輸入", "publicJellyfinNote": "Jellyfin 出於某種原因,不會顯示播放清單是否公開。如果您希望保持公開狀態,請選擇以下輸入",
"success": "$t(entity.playlist, {\"count\": 1}) 更新成功", "success": "$t(entity.playlist, {\"count\": 1}) 更新成功"
"editNote": "不建議手動編輯大型播放清單,你確定要承擔覆寫現有播放清單可能造成的資料遺失風險嗎?"
}, },
"shareItem": { "shareItem": {
"allowDownloading": "允許下載", "allowDownloading": "允許下載",
@@ -1033,7 +1093,9 @@
"setExpiration": "設定過期時間", "setExpiration": "設定過期時間",
"success": "分享連結已複製到剪貼簿(或點擊此處開啟)", "success": "分享連結已複製到剪貼簿(或點擊此處開啟)",
"expireInvalid": "到期日必須是未來", "expireInvalid": "到期日必須是未來",
"createFailed": "無法建立分享(分享是否啟用?)" "createFailed": "無法建立分享(分享是否啟用?)",
"copyToClipboard": "複製到剪貼簿:Ctrl+C, Enter",
"successMustClick": "分享建立成功,點擊此處開啟"
}, },
"privateMode": { "privateMode": {
"enabled": "已啟用私人模式,播放狀態將對外部整合隱藏", "enabled": "已啟用私人模式,播放狀態將對外部整合隱藏",
@@ -1056,8 +1118,8 @@
"input_played_optionPlayed": "僅播放過的曲目" "input_played_optionPlayed": "僅播放過的曲目"
}, },
"createRadioStation": { "createRadioStation": {
"success": "電台建成功", "success": "電台建成功",
"title": "建電台", "title": "建電台",
"input_homepageUrl": "首頁連結", "input_homepageUrl": "首頁連結",
"input_name": "名稱", "input_name": "名稱",
"input_streamUrl": "串流網址" "input_streamUrl": "串流網址"
@@ -1069,6 +1131,9 @@
"export": "匯出歌詞", "export": "匯出歌詞",
"input_synced": "匯出同步歌詞", "input_synced": "匯出同步歌詞",
"input_offset": "$t(setting.lyricOffset)" "input_offset": "$t(setting.lyricOffset)"
},
"editRadioStation": {
"success": "電臺更新成功"
} }
}, },
"releaseType": { "releaseType": {
@@ -1166,8 +1231,8 @@
"channelLayout": "聲道佈局", "channelLayout": "聲道佈局",
"maxFPS": "最大幀率", "maxFPS": "最大幀率",
"opacity": "不透明度", "opacity": "不透明度",
"customGradients": "自定義漸層", "customGradients": "自漸層",
"addCustomGradient": "新增自定義漸層", "addCustomGradient": "新增自漸層",
"gradientName": "漸層名稱", "gradientName": "漸層名稱",
"gradientNamePlaceholder": "漸層名稱", "gradientNamePlaceholder": "漸層名稱",
"vertical": "垂直", "vertical": "垂直",
@@ -1277,6 +1342,13 @@
"d": "D", "d": "D",
"z": "Z" "z": "Z"
} }
} },
"systemAudioCaptureFailed": "無法開始擷取:{{message}}",
"systemAudioNoAudioTrack": "沒有回傳任何音軌。確保在提示時啟用音訊擷取。",
"systemAudioConsentAllow": "允許",
"systemAudioConsentBody": "此視覺化器需要存取系統音訊才能運作",
"systemAudioConsentDecline": "拒絕",
"systemAudioConsentTitle": "允許存取系統音訊?",
"systemAudioExclusiveModeNotSupported": "啟用音訊獨佔模式時,視覺化不可用。 在MPV設定中停用音訊獨佔模式,然後再試一次。"
} }
} }
+8
View File
@@ -5,6 +5,10 @@ import { getLyricsBySongId as getGenius, getSearchResults as searchGenius } from
import { getLyricsBySongId as getLrcLib, getSearchResults as searchLrcLib } from './lrclib'; import { getLyricsBySongId as getLrcLib, getSearchResults as searchLrcLib } from './lrclib';
import { getLyricsBySongId as getNetease, getSearchResults as searchNetease } from './netease'; import { getLyricsBySongId as getNetease, getSearchResults as searchNetease } from './netease';
import { orderSearchResults } from './shared'; import { orderSearchResults } from './shared';
import {
getLyricsBySongId as getSimpMusic,
getSearchResults as searchSimpMusic,
} from './simpmusic';
import { Song } from '/@/shared/types/domain-types'; import { Song } from '/@/shared/types/domain-types';
@@ -12,6 +16,7 @@ export enum LyricSource {
GENIUS = 'Genius', GENIUS = 'Genius',
LRCLIB = 'lrclib.net', LRCLIB = 'lrclib.net',
NETEASE = 'NetEase', NETEASE = 'NetEase',
SIMPMUSIC = 'SimpMusic',
} }
export type FullLyricsMetadata = Omit<InternetProviderLyricResponse, 'id' | 'lyrics' | 'source'> & { export type FullLyricsMetadata = Omit<InternetProviderLyricResponse, 'id' | 'lyrics' | 'source'> & {
@@ -66,12 +71,14 @@ const SEARCH_FETCHERS: Record<LyricSource, SearchFetcher> = {
[LyricSource.GENIUS]: searchGenius, [LyricSource.GENIUS]: searchGenius,
[LyricSource.LRCLIB]: searchLrcLib, [LyricSource.LRCLIB]: searchLrcLib,
[LyricSource.NETEASE]: searchNetease, [LyricSource.NETEASE]: searchNetease,
[LyricSource.SIMPMUSIC]: searchSimpMusic,
}; };
const GET_FETCHERS: Record<LyricSource, GetFetcher> = { const GET_FETCHERS: Record<LyricSource, GetFetcher> = {
[LyricSource.GENIUS]: getGenius, [LyricSource.GENIUS]: getGenius,
[LyricSource.LRCLIB]: getLrcLib, [LyricSource.LRCLIB]: getLrcLib,
[LyricSource.NETEASE]: getNetease, [LyricSource.NETEASE]: getNetease,
[LyricSource.SIMPMUSIC]: getSimpMusic,
}; };
const MAX_CACHED_ITEMS = 10; const MAX_CACHED_ITEMS = 10;
@@ -191,6 +198,7 @@ const searchRemoteLyrics = async (params: LyricSearchQuery) => {
[LyricSource.GENIUS]: [], [LyricSource.GENIUS]: [],
[LyricSource.LRCLIB]: [], [LyricSource.LRCLIB]: [],
[LyricSource.NETEASE]: [], [LyricSource.NETEASE]: [],
[LyricSource.SIMPMUSIC]: [],
}; };
for (const item of allSearchResults) { for (const item of allSearchResults) {
results[item.source].push(item); results[item.source].push(item);
+4 -2
View File
@@ -58,14 +58,16 @@ export async function getSearchResults(
): Promise<InternetProviderLyricSearchResponse[] | null> { ): Promise<InternetProviderLyricSearchResponse[] | null> {
let result: AxiosResponse<LrcLibSearchResponse[]>; let result: AxiosResponse<LrcLibSearchResponse[]>;
if (!params.name) { if (!params.name && !params.artist) {
return null; return null;
} }
const searchQuery = [params.name, params.artist].join(' ');
try { try {
result = await axios.get<LrcLibSearchResponse[]>(SEEARCH_URL, { result = await axios.get<LrcLibSearchResponse[]>(SEEARCH_URL, {
params: { params: {
q: params.name, q: searchQuery,
}, },
}); });
} catch (e) { } catch (e) {
+126
View File
@@ -0,0 +1,126 @@
import axios, { AxiosResponse } from 'axios';
import {
InternetProviderLyricResponse,
InternetProviderLyricSearchResponse,
LyricSearchQuery,
LyricSource,
} from '.';
import { orderSearchResults } from './shared';
const API_URL = 'https://api-lyrics.simpmusic.org/v1';
const TIMEOUT_MS = 5000;
export interface SimpMusicLyric {
albumName?: string;
artistName: string;
durationSeconds?: number;
id: string;
plainLyric?: string;
richSyncLyrics?: string;
songTitle: string;
syncedLyrics?: string;
videoId: string;
vote?: number;
}
export interface SimpMusicSearchResponse {
data: SimpMusicLyric[];
success: boolean;
}
export async function getLyricsBySongId(songId: string): Promise<null | string> {
let result: AxiosResponse;
try {
result = await axios.get(`${API_URL}/${songId}`, {
timeout: TIMEOUT_MS,
});
} catch (e) {
console.error('SimpMusic lyrics request errored:', (e as Error)?.message);
return null;
}
const firstLyric = (result.data.data?.[0] ?? null) as null | SimpMusicLyric;
if (!firstLyric) return null;
return firstLyric.syncedLyrics || firstLyric.plainLyric || null;
}
export async function getSearchResults(
params: LyricSearchQuery,
): Promise<InternetProviderLyricSearchResponse[] | null> {
let result: AxiosResponse<SimpMusicSearchResponse>;
if (!params.name) return null;
try {
result = await axios.get<SimpMusicSearchResponse>(`${API_URL}/search`, {
params: {
q: params.name,
},
timeout: TIMEOUT_MS,
});
} catch (e) {
console.error('SimpMusic search errored:', (e as Error)?.message);
return null;
}
if (!result.data?.data) return null;
const songResults: InternetProviderLyricSearchResponse[] = result.data.data.map((song) => ({
artist: song.artistName,
id: song.videoId,
isSync: song.syncedLyrics ? true : false,
name: song.songTitle,
source: LyricSource.SIMPMUSIC,
}));
return orderSearchResults({ params, results: songResults });
}
export async function query(
params: LyricSearchQuery,
): Promise<InternetProviderLyricResponse | null> {
if (!params.name) return null;
let search: AxiosResponse<SimpMusicSearchResponse>;
try {
search = await axios.get<SimpMusicSearchResponse>(`${API_URL}/search`, {
params: {
q: params.name,
},
timeout: TIMEOUT_MS,
});
} catch (e) {
console.error('SimpMusic search errored:', (e as Error).message);
return null;
}
const first = search.data?.data?.[0];
if (!first) return null;
let lyric: AxiosResponse<SimpMusicLyric>;
try {
lyric = await axios.get<SimpMusicLyric>(`${API_URL}/${first.videoId}`, {
timeout: TIMEOUT_MS,
});
} catch (e) {
console.error('SimpMusic lyrics fetch errored:', (e as Error).message);
return null;
}
const lyrics = lyric.data.syncedLyrics || lyric.data.plainLyric || null;
if (!lyrics) return null;
return {
artist: lyric.data.artistName,
id: lyric.data.videoId,
lyrics,
name: lyric.data.songTitle,
source: LyricSource.SIMPMUSIC,
};
}
+45 -6
View File
@@ -1,13 +1,13 @@
import console from 'console'; import console from 'console';
import { app, ipcMain } from 'electron'; import { app, ipcMain } from 'electron';
import { rm } from 'fs/promises'; import { access, rm } from 'fs/promises';
import uniq from 'lodash/uniq'; import uniq from 'lodash/uniq';
import MpvAPI from 'node-mpv'; import MpvAPI from 'node-mpv';
import { pid } from 'node:process'; import { pid } from 'node:process';
import process from 'process'; import process from 'process';
import { getMainWindow, sendToastToRenderer } from '../../../index'; import { getMainWindow, sendToastToRenderer } from '../../../index';
import { createLog, isWindows } from '../../../utils'; import { createLog, isMacOS, isWindows } from '../../../utils';
import { store } from '../settings'; import { store } from '../settings';
import { PlayerData } from '/@/shared/types/domain-types'; import { PlayerData } from '/@/shared/types/domain-types';
@@ -69,6 +69,7 @@ const mpvLog = (
}; };
const MPV_BINARY_PATH = store.get('mpv_path') as string | undefined; const MPV_BINARY_PATH = store.get('mpv_path') as string | undefined;
const MACOS_MPV_BINARY_PATHS = ['/opt/homebrew/bin/mpv', '/usr/local/bin/mpv'];
const prefetchPlaylistParams = [ const prefetchPlaylistParams = [
'--prefetch-playlist=no', '--prefetch-playlist=no',
@@ -86,12 +87,38 @@ const DEFAULT_MPV_PARAMETERS = (extraParameters?: string[]) => {
return parameters; return parameters;
}; };
const resolveMpvBinaryPath = async (binaryPath?: string) => {
if (binaryPath) {
return binaryPath;
}
if (MPV_BINARY_PATH) {
return MPV_BINARY_PATH;
}
if (!isMacOS()) {
return undefined;
}
for (const candidate of MACOS_MPV_BINARY_PATHS) {
try {
await access(candidate);
return candidate;
} catch {
// Try the next common Homebrew location.
}
}
return undefined;
};
const createMpv = async (data: { const createMpv = async (data: {
binaryPath?: string; binaryPath?: string;
extraParameters?: string[]; extraParameters?: string[];
properties?: Record<string, any>; properties?: Record<string, any>;
}): Promise<MpvAPI> => { }): Promise<MpvAPI> => {
const { binaryPath, extraParameters, properties } = data; const { binaryPath, extraParameters, properties } = data;
const resolvedBinaryPath = await resolveMpvBinaryPath(binaryPath);
const params = uniq([...DEFAULT_MPV_PARAMETERS(extraParameters), ...(extraParameters || [])]); const params = uniq([...DEFAULT_MPV_PARAMETERS(extraParameters), ...(extraParameters || [])]);
@@ -99,7 +126,7 @@ const createMpv = async (data: {
{ {
audio_only: true, audio_only: true,
auto_restart: false, auto_restart: false,
binary: binaryPath || MPV_BINARY_PATH || undefined, binary: resolvedBinaryPath,
socket: socketPath, socket: socketPath,
time_update: 1, time_update: 1,
}, },
@@ -116,11 +143,15 @@ const createMpv = async (data: {
mpv.on('status', (status) => { mpv.on('status', (status) => {
if (status.property === 'playlist-pos') { if (status.property === 'playlist-pos') {
// mpv uses playlist-pos = -1 when nothing is playing (ended, cleared, load failure, etc).
if (status.value === -1) { if (status.value === -1) {
mpv?.pause(); mpv?.pause();
return;
} }
if (status.value !== 0) { // In our 2-item queue model, playlist-pos should normally be 0.
// When mpv auto-advances to the next track it becomes > 0 (typically 1).
if (typeof status.value === 'number' && status.value > 0) {
getMainWindow()?.webContents.send('renderer-player-auto-next'); getMainWindow()?.webContents.send('renderer-player-auto-next');
} }
} }
@@ -433,10 +464,18 @@ ipcMain.on('player-mute', async (_event, mute: boolean) => {
ipcMain.handle('player-get-time', async (): Promise<number | undefined> => { ipcMain.handle('player-get-time', async (): Promise<number | undefined> => {
try { try {
return getMpvInstance()?.getTimePosition(); const mpv = getMpvInstance();
if (!mpv) {
return undefined;
}
return await mpv.getTimePosition();
} catch (err: any | NodeMpvError) { } catch (err: any | NodeMpvError) {
// Err 3: IPC command invalid — e.g. time-pos unavailable when idle / between tracks
if (err?.errcode === 3) {
return undefined;
}
mpvLog({ action: `Failed to get current time` }, err); mpvLog({ action: `Failed to get current time` }, err);
return 0; return undefined;
} }
}); });
+1
View File
@@ -40,6 +40,7 @@ export const store = new Store<any>({
playbackType: 'web', playbackType: 'web',
should_prompt_accessibility: true, should_prompt_accessibility: true,
shown_accessibility_warning: false, shown_accessibility_warning: false,
visualizer_system_audio_consent_granted: false,
window_enable_tray: true, window_enable_tray: true,
window_exit_to_tray: false, window_exit_to_tray: false,
window_minimize_to_tray: false, window_minimize_to_tray: false,
+8 -1
View File
@@ -1,2 +1,9 @@
import './core'; import './core';
import(`./${process.platform}`);
if (process.platform === 'linux') {
import('./linux');
} else if (process.platform === 'darwin') {
import('./darwin');
} else if (process.platform === 'win32') {
import('./win32');
}
+17
View File
@@ -150,6 +150,23 @@ ipcMain.on(
return; return;
} }
// If the served id is an empty string, this is a radio
// Use a limited subset of the fields
if (song._serverId === '') {
// The id as passed in from use-mpris is radio- plus the radio ID
// If there are spaces or some other characters, this causes MPRIS to error and
// disconnect the bus. To prevent this, just use a fake track/radio
mprisPlayer.metadata = {
'mpris:trackid': mprisPlayer.objectPath(`track/radio`),
'xesam:album': song.album || null,
'xesam:artist': song.artists?.length
? song.artists.map((artist) => artist.name)
: null,
'xesam:title': song.name || null,
};
return;
}
mprisPlayer.metadata = { mprisPlayer.metadata = {
'mpris:artUrl': imageUrl || null, 'mpris:artUrl': imageUrl || null,
'mpris:length': song.duration ? Math.round((song.duration || 0) * 1e3) : null, 'mpris:length': song.duration ? Math.round((song.duration || 0) * 1e3) : null,
+1
View File
@@ -0,0 +1 @@
export {};
+204 -26
View File
@@ -5,6 +5,7 @@ import {
app, app,
BrowserWindow, BrowserWindow,
BrowserWindowConstructorOptions, BrowserWindowConstructorOptions,
desktopCapturer,
globalShortcut, globalShortcut,
ipcMain, ipcMain,
Menu, Menu,
@@ -29,7 +30,7 @@ import packageJson from '../../package.json';
import { disableMediaKeys, enableMediaKeys } from './features/core/player/media-keys'; import { disableMediaKeys, enableMediaKeys } from './features/core/player/media-keys';
import { shutdownServer } from './features/core/remote'; import { shutdownServer } from './features/core/remote';
import { store } from './features/core/settings'; import { store } from './features/core/settings';
import MenuBuilder from './menu'; import MenuBuilder, { MenuPlaybackState } from './menu';
import { import {
autoUpdaterLogInterface, autoUpdaterLogInterface,
createLog, createLog,
@@ -41,7 +42,7 @@ import {
} from './utils'; } from './utils';
import './features'; import './features';
import { PlayerType, TitleTheme } from '/@/shared/types/types'; import { PlayerRepeat, PlayerStatus, PlayerType, TitleTheme } from '/@/shared/types/types';
const ALPHA_UPDATER_CONFIG: { const ALPHA_UPDATER_CONFIG: {
bucket: string; bucket: string;
@@ -55,6 +56,12 @@ const ALPHA_UPDATER_CONFIG: {
provider: 's3', provider: 's3',
}; };
const GITHUB_UPDATER_CONFIG = {
owner: 'jeffvli',
provider: 'github' as const,
repo: 'feishin',
};
type UpdaterInstance = AppImageUpdater | MacUpdater | NsisUpdater | typeof autoUpdater; type UpdaterInstance = AppImageUpdater | MacUpdater | NsisUpdater | typeof autoUpdater;
class AppUpdater { class AppUpdater {
@@ -62,16 +69,40 @@ class AppUpdater {
const effectiveChannel = store.get('release_channel') as string; const effectiveChannel = store.get('release_channel') as string;
console.log('Effective update channel:', effectiveChannel); console.log('Effective update channel:', effectiveChannel);
if (effectiveChannel === 'alpha') { if (effectiveChannel === 'alpha') {
checkAllChannelsAndGetBest().then(({ updater: updaterInstance }) => { checkAllChannelsAndGetBest().then(({ result, updater: updaterInstance }) => {
updaterInstance.autoInstallOnAppQuit = true; updaterInstance.autoInstallOnAppQuit = true;
updaterInstance.autoRunAppAfterInstall = true; updaterInstance.autoRunAppAfterInstall = true;
updaterInstance.checkForUpdatesAndNotify(); if (isMacOS()) {
if (result?.isUpdateAvailable) {
getMainWindow()?.webContents.send(
'update-available',
result.updateInfo.version,
);
}
} else {
updaterInstance.checkForUpdatesAndNotify();
}
}); });
return; return;
} }
configureAndGetUpdater(); configureAndGetUpdater();
autoUpdater.checkForUpdatesAndNotify(); if (isMacOS()) {
autoUpdater.autoDownload = false;
autoUpdater
.checkForUpdates()
.then((result) => {
if (result?.isUpdateAvailable) {
getMainWindow()?.webContents.send(
'update-available',
result.updateInfo.version,
);
}
})
.catch((err) => console.error('Check for updates failed', err));
} else {
autoUpdater.checkForUpdatesAndNotify();
}
} }
} }
@@ -97,6 +128,7 @@ async function checkAllChannelsAndGetBest(): Promise<{
alphaUpdater.allowDowngrade = true; alphaUpdater.allowDowngrade = true;
try { try {
console.log('Checking for updates on alpha channel');
const alphaResult = await alphaUpdater.checkForUpdates(); const alphaResult = await alphaUpdater.checkForUpdates();
if ( if (
alphaResult?.updateInfo?.version && alphaResult?.updateInfo?.version &&
@@ -111,7 +143,9 @@ async function checkAllChannelsAndGetBest(): Promise<{
} }
try { try {
autoUpdater.setFeedURL(GITHUB_UPDATER_CONFIG);
configureAutoUpdaterForChannel('latest'); configureAutoUpdaterForChannel('latest');
console.log('Checking for updates on latest channel (GitHub)');
const latestResult = await autoUpdater.checkForUpdates(); const latestResult = await autoUpdater.checkForUpdates();
if ( if (
latestResult?.updateInfo?.version && latestResult?.updateInfo?.version &&
@@ -244,6 +278,13 @@ let tray: null | Tray = null;
let exitFromTray = false; let exitFromTray = false;
let forceQuit = false; let forceQuit = false;
let powerSaveBlockerId: null | number = null; let powerSaveBlockerId: null | number = null;
let menuBuilder: MenuBuilder | null = null;
let currentPlaybackStatus: PlayerStatus = PlayerStatus.PAUSED;
let currentPrivateMode = false;
let currentRepeatMode: PlayerRepeat = PlayerRepeat.NONE;
let currentSidebarCollapsed = false;
let currentShuffleEnabled = false;
let playbackMenuAccelerators: MenuPlaybackState['accelerators'] = {};
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
import('source-map-support').then((sourceMapSupport) => { import('source-map-support').then((sourceMapSupport) => {
@@ -300,6 +341,23 @@ export const getMainWindow = () => {
return mainWindow; return mainWindow;
}; };
const rebuildMainMenu = () => {
if (!menuBuilder || !mainWindow) return;
menuBuilder.buildMenu({
accelerators: playbackMenuAccelerators,
playbackStatus: currentPlaybackStatus,
privateMode: currentPrivateMode,
repeatMode: currentRepeatMode,
shuffleEnabled: currentShuffleEnabled,
sidebarCollapsed: currentSidebarCollapsed,
});
if (process.platform !== 'darwin') {
Menu.setApplicationMenu(null);
}
};
export const sendToastToRenderer = ({ export const sendToastToRenderer = ({
message, message,
type, type,
@@ -381,8 +439,11 @@ const createTray = () => {
}, },
{ {
click: () => { click: () => {
mainWindow?.show(); if (mainWindow === null) createWindow(false);
createWinThumbarButtons(); else {
mainWindow.show();
createWinThumbarButtons();
}
}, },
label: 'Open main window', label: 'Open main window',
}, },
@@ -395,10 +456,21 @@ const createTray = () => {
}, },
]); ]);
tray.on('click', () => { if (!isMacOS()) {
mainWindow?.show(); tray.on('click', () => {
createWinThumbarButtons(); if (store.get('window_minimize_to_tray')) {
}); if (mainWindow?.isVisible()) {
mainWindow?.hide();
} else {
mainWindow?.show();
createWinThumbarButtons();
}
} else {
mainWindow?.show();
createWinThumbarButtons();
}
});
}
tray.setToolTip('Feishin'); tray.setToolTip('Feishin');
tray.setContextMenu(contextMenu); tray.setContextMenu(contextMenu);
@@ -534,8 +606,15 @@ async function createWindow(first = true): Promise<void> {
const updateAvailable = result?.isUpdateAvailable ?? false; const updateAvailable = result?.isUpdateAvailable ?? false;
console.log('Update available:', updateAvailable); console.log('Update available:', updateAvailable);
if (updateAvailable && store.get('disable_auto_updates') !== true) { if (updateAvailable && store.get('disable_auto_updates') !== true) {
console.log('Downloading update'); if (isMacOS()) {
updater.downloadUpdate(); getMainWindow()?.webContents.send(
'update-available',
result?.updateInfo?.version,
);
} else {
console.log('Downloading update');
updater.downloadUpdate();
}
} }
return { return {
@@ -609,6 +688,7 @@ async function createWindow(first = true): Promise<void> {
mainWindow.on('closed', () => { mainWindow.on('closed', () => {
ipcMain.removeHandler('window-clear-cache'); ipcMain.removeHandler('window-clear-cache');
ipcMain.removeHandler('app-check-for-updates');
mainWindow = null; mainWindow = null;
}); });
@@ -644,12 +724,8 @@ async function createWindow(first = true): Promise<void> {
}); });
} }
const menuBuilder = new MenuBuilder(mainWindow); menuBuilder = new MenuBuilder(mainWindow);
menuBuilder.buildMenu(); rebuildMainMenu();
if (process.platform !== 'darwin') {
Menu.setApplicationMenu(null);
}
// Open URLs in the user's browser // Open URLs in the user's browser
mainWindow.webContents.setWindowOpenHandler((edata) => { mainWindow.webContents.setWindowOpenHandler((edata) => {
@@ -657,6 +733,29 @@ async function createWindow(first = true): Promise<void> {
return { action: 'deny' }; return { action: 'deny' };
}); });
mainWindow.webContents.session.setDisplayMediaRequestHandler((_request, callback) => {
if (!isMacOS()) {
callback({ audio: 'loopback' });
return;
}
desktopCapturer
.getSources({ thumbnailSize: { height: 0, width: 0 }, types: ['screen'] })
.then((sources) => {
const source = sources[0];
if (!source) {
callback({});
return;
}
callback({ audio: 'loopback', video: source });
})
.catch((err) => {
log.warn('desktopCapturer.getSources failed', err);
callback({});
});
});
if (!disableAutoUpdates() && store.get('disable_auto_updates') !== true) { if (!disableAutoUpdates() && store.get('disable_auto_updates') !== true) {
new AppUpdater(); new AppUpdater();
} }
@@ -687,11 +786,17 @@ const playbackType = store.get('playbackType', PlayerType.WEB) as PlayerType;
const shouldDisableMediaFeatures = const shouldDisableMediaFeatures =
isLinux() || !enableMediaSession || playbackType !== PlayerType.WEB; isLinux() || !enableMediaSession || playbackType !== PlayerType.WEB;
const chromiumDisabledFeatures: string[] = [];
// Fractional scaling on Wayland: https://github.com/jeffvli/feishin/issues/1271#issuecomment-4063326712
if (isLinux()) {
chromiumDisabledFeatures.push('WaylandFractionalScaleV1');
}
if (shouldDisableMediaFeatures) { if (shouldDisableMediaFeatures) {
app.commandLine.appendSwitch( chromiumDisabledFeatures.push('HardwareMediaKeyHandling', 'MediaSessionService');
'disable-features', }
'HardwareMediaKeyHandling,MediaSessionService',
); if (chromiumDisabledFeatures.length > 0) {
app.commandLine.appendSwitch('disable-features', chromiumDisabledFeatures.join(','));
} }
// https://github.com/electron/electron/issues/46538#issuecomment-2808806722 // https://github.com/electron/electron/issues/46538#issuecomment-2808806722
@@ -721,6 +826,17 @@ enum BindingActions {
VOLUME_UP = 'volumeUp', VOLUME_UP = 'volumeUp',
} }
const getMenuAccelerator = (
data: Record<BindingActions, { allowGlobal: boolean; hotkey: string; isGlobal: boolean }>,
action: BindingActions,
) => {
const hotkey = data[action]?.hotkey;
if (!hotkey) return undefined;
return hotkeyToElectronAccelerator(hotkey);
};
const HOTKEY_ACTIONS: Record<BindingActions, () => void> = { const HOTKEY_ACTIONS: Record<BindingActions, () => void> = {
[BindingActions.GLOBAL_SEARCH]: () => {}, [BindingActions.GLOBAL_SEARCH]: () => {},
[BindingActions.LOCAL_SEARCH]: () => {}, [BindingActions.LOCAL_SEARCH]: () => {},
@@ -774,6 +890,26 @@ ipcMain.on(
} }
} }
playbackMenuAccelerators = {
next: getMenuAccelerator(data, BindingActions.NEXT),
playPause:
getMenuAccelerator(data, BindingActions.PLAY_PAUSE) ||
getMenuAccelerator(data, BindingActions.PLAY) ||
getMenuAccelerator(data, BindingActions.PAUSE),
previous: getMenuAccelerator(data, BindingActions.PREVIOUS),
repeat: getMenuAccelerator(data, BindingActions.TOGGLE_REPEAT),
seekBackward: getMenuAccelerator(data, BindingActions.SKIP_BACKWARD),
seekForward: getMenuAccelerator(data, BindingActions.SKIP_FORWARD),
shuffle: getMenuAccelerator(data, BindingActions.SHUFFLE),
stop: getMenuAccelerator(data, BindingActions.STOP),
volumeDown: getMenuAccelerator(data, BindingActions.VOLUME_DOWN),
volumeUp: getMenuAccelerator(data, BindingActions.VOLUME_UP),
};
if (isMacOS()) {
rebuildMainMenu();
}
const globalMediaKeysEnabled = store.get('global_media_hotkeys', true) as boolean; const globalMediaKeysEnabled = store.get('global_media_hotkeys', true) as boolean;
if (globalMediaKeysEnabled) { if (globalMediaKeysEnabled) {
@@ -795,12 +931,14 @@ ipcMain.on(
}, },
); );
ipcMain.handle('power-save-blocker-start', () => { ipcMain.handle('power-save-blocker-start', (_event, { full }: { full: boolean }) => {
if (powerSaveBlockerId !== null) { if (powerSaveBlockerId !== null) {
return powerSaveBlockerId; return powerSaveBlockerId;
} }
powerSaveBlockerId = powerSaveBlocker.start('prevent-display-sleep'); powerSaveBlockerId = powerSaveBlocker.start(
full ? 'prevent-display-sleep' : 'prevent-app-suspension',
);
return powerSaveBlockerId; return powerSaveBlockerId;
}); });
@@ -857,7 +995,7 @@ if (!singleInstance) {
app.whenReady() app.whenReady()
.then(() => { .then(() => {
protocol.handle('feishin', async (request) => { protocol.handle('feishin', async (request) => {
const filePath = `file://${request.url.slice('feishin://'.length)}`; const filePath = `file:${request.url.slice('feishin:'.length)}`;
const response = await net.fetch(filePath); const response = await net.fetch(filePath);
const contentType = response.headers.get('content-type'); const contentType = response.headers.get('content-type');
@@ -914,3 +1052,43 @@ if (!ipcMain.eventNames().includes('open-application-directory')) {
shell.openPath(userDataPath); shell.openPath(userDataPath);
}); });
} }
ipcMain.on('update-playback', (_event, status: PlayerStatus) => {
currentPlaybackStatus = status;
if (!isMacOS()) return;
rebuildMainMenu();
});
ipcMain.on('update-repeat', (_event, repeat: PlayerRepeat) => {
currentRepeatMode = repeat;
if (!isMacOS()) return;
rebuildMainMenu();
});
ipcMain.on('update-shuffle', (_event, shuffle: boolean) => {
currentShuffleEnabled = shuffle;
if (!isMacOS()) return;
rebuildMainMenu();
});
ipcMain.on('update-private-mode', (_event, privateMode: boolean) => {
currentPrivateMode = privateMode;
if (!isMacOS()) return;
rebuildMainMenu();
});
ipcMain.on('update-sidebar-collapsed', (_event, collapsedSidebar: boolean) => {
currentSidebarCollapsed = collapsedSidebar;
if (!isMacOS()) return;
rebuildMainMenu();
});
+190 -4
View File
@@ -1,18 +1,53 @@
import { app, BrowserWindow, Menu, MenuItemConstructorOptions, shell } from 'electron'; import { app, BrowserWindow, Menu, MenuItemConstructorOptions, shell } from 'electron';
import packageJson from '../../package.json';
import { PlayerRepeat, PlayerStatus } from '/@/shared/types/types';
export type MenuPlaybackState = {
accelerators?: {
next?: string;
playPause?: string;
previous?: string;
repeat?: string;
seekBackward?: string;
seekForward?: string;
shuffle?: string;
stop?: string;
volumeDown?: string;
volumeUp?: string;
};
playbackStatus?: PlayerStatus;
privateMode?: boolean;
repeatMode?: PlayerRepeat;
shuffleEnabled?: boolean;
sidebarCollapsed?: boolean;
};
interface DarwinMenuItemConstructorOptions extends MenuItemConstructorOptions { interface DarwinMenuItemConstructorOptions extends MenuItemConstructorOptions {
selector?: string; selector?: string;
submenu?: DarwinMenuItemConstructorOptions[] | Menu; submenu?: DarwinMenuItemConstructorOptions[] | Menu;
} }
export default class MenuBuilder { export default class MenuBuilder {
developmentEnvironmentSetup = false;
mainWindow: BrowserWindow; mainWindow: BrowserWindow;
constructor(mainWindow: BrowserWindow) { constructor(mainWindow: BrowserWindow) {
this.mainWindow = mainWindow; this.mainWindow = mainWindow;
} }
buildDarwinTemplate(): MenuItemConstructorOptions[] { buildDarwinTemplate({
accelerators,
playbackStatus = PlayerStatus.PAUSED,
privateMode = false,
repeatMode = PlayerRepeat.NONE,
shuffleEnabled = false,
sidebarCollapsed = false,
}: MenuPlaybackState = {}): MenuItemConstructorOptions[] {
const isPlaying = playbackStatus === PlayerStatus.PLAYING;
const isRepeatEnabled = repeatMode !== PlayerRepeat.NONE;
const subMenuAbout: DarwinMenuItemConstructorOptions = { const subMenuAbout: DarwinMenuItemConstructorOptions = {
label: 'Electron', label: 'Electron',
submenu: [ submenu: [
@@ -29,6 +64,21 @@ export default class MenuBuilder {
label: 'Settings', label: 'Settings',
}, },
{ type: 'separator' }, { type: 'separator' },
{
click: () => {
this.mainWindow.webContents.send('renderer-open-manage-servers');
},
label: 'Manage servers',
},
{
checked: privateMode,
click: () => {
this.mainWindow.webContents.send('renderer-toggle-private-mode');
},
label: 'Private session',
type: 'checkbox',
},
{ type: 'separator' },
{ label: 'Services', submenu: [] }, { label: 'Services', submenu: [] },
{ type: 'separator' }, { type: 'separator' },
{ {
@@ -71,6 +121,22 @@ export default class MenuBuilder {
const subMenuViewDev: MenuItemConstructorOptions = { const subMenuViewDev: MenuItemConstructorOptions = {
label: 'View', label: 'View',
submenu: [ submenu: [
{
accelerator: 'Command+K',
click: () => {
this.mainWindow.webContents.send('renderer-open-command-palette');
},
label: 'Command Palette...',
},
{
checked: sidebarCollapsed,
click: () => {
this.mainWindow.webContents.send('renderer-toggle-sidebar');
},
label: 'Collapse sidebar',
type: 'checkbox',
},
{ type: 'separator' },
{ {
accelerator: 'Command+R', accelerator: 'Command+R',
click: () => { click: () => {
@@ -97,6 +163,22 @@ export default class MenuBuilder {
const subMenuViewProd: MenuItemConstructorOptions = { const subMenuViewProd: MenuItemConstructorOptions = {
label: 'View', label: 'View',
submenu: [ submenu: [
{
accelerator: 'Command+K',
click: () => {
this.mainWindow.webContents.send('renderer-open-command-palette');
},
label: 'Command Palette...',
},
{
checked: sidebarCollapsed,
click: () => {
this.mainWindow.webContents.send('renderer-toggle-sidebar');
},
label: 'Collapse sidebar',
type: 'checkbox',
},
{ type: 'separator' },
{ {
accelerator: 'Ctrl+Command+F', accelerator: 'Ctrl+Command+F',
click: () => { click: () => {
@@ -119,6 +201,89 @@ export default class MenuBuilder {
{ label: 'Bring All to Front', selector: 'arrangeInFront:' }, { label: 'Bring All to Front', selector: 'arrangeInFront:' },
], ],
}; };
const subMenuPlayback: MenuItemConstructorOptions = {
label: 'Playback',
submenu: [
{
accelerator: accelerators?.playPause,
click: () => {
this.mainWindow.webContents.send('renderer-player-play-pause');
},
label: isPlaying ? 'Pause' : 'Play',
},
{ type: 'separator' },
{
accelerator: accelerators?.next,
click: () => {
this.mainWindow.webContents.send('renderer-player-next');
},
label: 'Next',
},
{
accelerator: accelerators?.previous,
click: () => {
this.mainWindow.webContents.send('renderer-player-previous');
},
label: 'Previous',
},
{
accelerator: accelerators?.seekForward,
click: () => {
this.mainWindow.webContents.send('renderer-player-skip-forward');
},
label: 'Seek Forward',
},
{
accelerator: accelerators?.seekBackward,
click: () => {
this.mainWindow.webContents.send('renderer-player-skip-backward');
},
label: 'Seek Backforward',
},
{ type: 'separator' },
{
accelerator: accelerators?.shuffle,
checked: shuffleEnabled,
click: () => {
this.mainWindow.webContents.send('renderer-player-toggle-shuffle');
},
label: 'Shuffle',
type: 'checkbox',
},
{
accelerator: accelerators?.repeat,
checked: isRepeatEnabled,
click: () => {
this.mainWindow.webContents.send('renderer-player-toggle-repeat');
},
label: 'Repeat',
type: 'checkbox',
},
{ type: 'separator' },
{
accelerator: accelerators?.stop,
click: () => {
this.mainWindow.webContents.send('renderer-player-stop');
},
label: 'Stop',
},
{ type: 'separator' },
{
accelerator: accelerators?.volumeUp,
click: () => {
this.mainWindow.webContents.send('renderer-player-volume-up');
},
label: 'Volume Up',
},
{
accelerator: accelerators?.volumeDown,
click: () => {
this.mainWindow.webContents.send('renderer-player-volume-down');
},
label: 'Volume Down',
},
],
};
const subMenuHelp: MenuItemConstructorOptions = { const subMenuHelp: MenuItemConstructorOptions = {
label: 'Help', label: 'Help',
submenu: [ submenu: [
@@ -148,6 +313,13 @@ export default class MenuBuilder {
}, },
label: 'Search Issues', label: 'Search Issues',
}, },
{ type: 'separator' },
{
click: () => {
this.mainWindow.webContents.send('renderer-open-release-notes');
},
label: 'Version ' + packageJson.version,
},
], ],
}; };
@@ -156,7 +328,14 @@ export default class MenuBuilder {
? subMenuViewDev ? subMenuViewDev
: subMenuViewProd; : subMenuViewProd;
return [subMenuAbout, subMenuEdit, subMenuView, subMenuWindow, subMenuHelp]; return [
subMenuAbout,
subMenuEdit,
subMenuView,
subMenuPlayback,
subMenuWindow,
subMenuHelp,
];
} }
buildDefaultTemplate(): MenuItemConstructorOptions[] { buildDefaultTemplate(): MenuItemConstructorOptions[] {
@@ -262,14 +441,14 @@ export default class MenuBuilder {
return templateDefault; return templateDefault;
} }
buildMenu(): Menu { buildMenu(playbackState: MenuPlaybackState = {}): Menu {
if (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true') { if (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true') {
this.setupDevelopmentEnvironment(); this.setupDevelopmentEnvironment();
} }
const template = const template =
process.platform === 'darwin' process.platform === 'darwin'
? this.buildDarwinTemplate() ? this.buildDarwinTemplate(playbackState)
: this.buildDefaultTemplate(); : this.buildDefaultTemplate();
const menu = Menu.buildFromTemplate(template); const menu = Menu.buildFromTemplate(template);
@@ -279,6 +458,13 @@ export default class MenuBuilder {
} }
setupDevelopmentEnvironment(): void { setupDevelopmentEnvironment(): void {
// buildMenu can run multiple times as menu state updates; attach this once.
if (this.developmentEnvironmentSetup) {
return;
}
this.developmentEnvironmentSetup = true;
this.mainWindow.webContents.on('context-menu', (_, props) => { this.mainWindow.webContents.on('context-menu', (_, props) => {
const { x, y } = props; const { x, y } = props;
+2 -1
View File
@@ -1,4 +1,5 @@
import { SetActivity } from '@xhayper/discord-rpc'; import type { SetActivity } from '@xhayper/discord-rpc';
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
const initialize = (clientId: string) => { const initialize = (clientId: string) => {
+1
View File
@@ -8,6 +8,7 @@ declare global {
electron: ElectronAPI; electron: ElectronAPI;
LEGACY_AUTHENTICATION?: boolean; LEGACY_AUTHENTICATION?: boolean;
queryLocalFonts?: () => Promise<Font[]>; queryLocalFonts?: () => Promise<Font[]>;
REMOTE_URL?: string;
SERVER_LOCK?: boolean; SERVER_LOCK?: boolean;
SERVER_NAME?: string; SERVER_NAME?: string;
SERVER_TYPE?: ServerType; SERVER_TYPE?: ServerType;
+10
View File
@@ -12,9 +12,19 @@ const invoke = (channel: string, ...args: any[]) => {
return ipcRenderer.invoke(channel, ...args); return ipcRenderer.invoke(channel, ...args);
}; };
const on = (channel: string, listener: (event: any, ...args: any[]) => void) => {
ipcRenderer.on(channel, listener);
};
const removeListener = (channel: string, listener: (event: any, ...args: any[]) => void) => {
ipcRenderer.removeListener(channel, listener);
};
export const ipc = { export const ipc = {
invoke, invoke,
on,
removeAllListeners, removeAllListeners,
removeListener,
send, send,
}; };
+1
View File
@@ -74,6 +74,7 @@ const env = {
SERVER_TYPE !== null SERVER_TYPE !== null
? process.env.LEGACY_AUTHENTICATION?.toLocaleLowerCase() === 'true' ? process.env.LEGACY_AUTHENTICATION?.toLocaleLowerCase() === 'true'
: false, : false,
REMOTE_URL: process.env.REMOTE_URL ?? '',
SERVER_LOCK: SERVER_LOCK:
SERVER_TYPE !== null ? process.env.SERVER_LOCK?.toLocaleLowerCase() === 'true' : false, SERVER_TYPE !== null ? process.env.SERVER_LOCK?.toLocaleLowerCase() === 'true' : false,
SERVER_NAME: process.env.SERVER_NAME ?? '', SERVER_NAME: process.env.SERVER_NAME ?? '',
+25
View File
@@ -65,6 +65,26 @@ const rendererOpenSettings = (cb: (event: IpcRendererEvent) => void) => {
ipcRenderer.on('renderer-open-settings', cb); ipcRenderer.on('renderer-open-settings', cb);
}; };
const rendererOpenCommandPalette = (cb: (event: IpcRendererEvent) => void) => {
ipcRenderer.on('renderer-open-command-palette', cb);
};
const rendererOpenManageServers = (cb: (event: IpcRendererEvent) => void) => {
ipcRenderer.on('renderer-open-manage-servers', cb);
};
const rendererTogglePrivateMode = (cb: (event: IpcRendererEvent) => void) => {
ipcRenderer.on('renderer-toggle-private-mode', cb);
};
const rendererToggleSidebar = (cb: (event: IpcRendererEvent) => void) => {
ipcRenderer.on('renderer-toggle-sidebar', cb);
};
const rendererOpenReleaseNotes = (cb: (event: IpcRendererEvent) => void) => {
ipcRenderer.on('renderer-open-release-notes', cb);
};
export const utils = { export const utils = {
checkForUpdates, checkForUpdates,
disableAutoUpdates, disableAutoUpdates,
@@ -78,7 +98,12 @@ export const utils = {
openApplicationDirectory, openApplicationDirectory,
openItem, openItem,
playerErrorListener, playerErrorListener,
rendererOpenCommandPalette,
rendererOpenManageServers,
rendererOpenReleaseNotes,
rendererOpenSettings, rendererOpenSettings,
rendererTogglePrivateMode,
rendererToggleSidebar,
}; };
export type Utils = typeof utils; export type Utils = typeof utils;
+149 -1
View File
@@ -10,6 +10,8 @@ import {
ControllerEndpoint, ControllerEndpoint,
InternalControllerEndpoint, InternalControllerEndpoint,
ServerType, ServerType,
SetPlaylistSongsArgs,
SetPlaylistSongsResponse,
} from '/@/shared/types/domain-types'; } from '/@/shared/types/domain-types';
type ApiController = { type ApiController = {
@@ -67,6 +69,7 @@ const getPathReplaceSettings = () => {
const addContext = <T extends { apiClientProps: any; context?: any }>(args: T): T => { const addContext = <T extends { apiClientProps: any; context?: any }>(args: T): T => {
const pathSettings = getPathReplaceSettings(); const pathSettings = getPathReplaceSettings();
return { return {
...args, ...args,
context: { context: {
@@ -144,6 +147,20 @@ export const controller: GeneralController = {
server.type, server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } })); )?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
}, },
deleteArtistImage(args) {
const server = getServerById(args.apiClientProps.serverId);
if (!server) {
throw new Error(
`${i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' })}: deleteArtistImage`,
);
}
return apiController(
'deleteArtistImage',
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
deleteFavorite(args) { deleteFavorite(args) {
const server = getServerById(args.apiClientProps.serverId); const server = getServerById(args.apiClientProps.serverId);
@@ -172,6 +189,20 @@ export const controller: GeneralController = {
server.type, server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } })); )?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
}, },
deleteInternetRadioStationImage(args) {
const server = getServerById(args.apiClientProps.serverId);
if (!server) {
throw new Error(
`${i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' })}: deleteInternetRadioStationImage`,
);
}
return apiController(
'deleteInternetRadioStationImage',
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
deletePlaylist(args) { deletePlaylist(args) {
const server = getServerById(args.apiClientProps.serverId); const server = getServerById(args.apiClientProps.serverId);
@@ -186,6 +217,20 @@ export const controller: GeneralController = {
server.type, server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } })); )?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
}, },
deletePlaylistImage(args) {
const server = getServerById(args.apiClientProps.serverId);
if (!server) {
throw new Error(
`${i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' })}: deletePlaylistImage`,
);
}
return apiController(
'deletePlaylistImage',
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
getAlbumArtistDetail(args) { getAlbumArtistDetail(args) {
const server = getServerById(args.apiClientProps.serverId); const server = getServerById(args.apiClientProps.serverId);
@@ -200,6 +245,18 @@ export const controller: GeneralController = {
server.type, server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } })); )?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
}, },
getAlbumArtistInfo(args) {
const server = getServerById(args.apiClientProps.serverId);
if (!server) {
return Promise.resolve(null);
}
const fn = apiController('getAlbumArtistInfo', server.type);
return fn
? fn(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }))
: Promise.resolve(null);
},
getAlbumArtistList(args) { getAlbumArtistList(args) {
const server = getServerById(args.apiClientProps.serverId); const server = getServerById(args.apiClientProps.serverId);
@@ -308,6 +365,20 @@ export const controller: GeneralController = {
}), }),
); );
}, },
getAlbumRadio(args) {
const server = getServerById(args.apiClientProps.serverId);
if (!server) {
throw new Error(
`${i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' })}: getAlbumRadio`,
);
}
return apiController(
'getAlbumRadio',
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
getArtistList(args) { getArtistList(args) {
const server = getServerById(args.apiClientProps.serverId); const server = getServerById(args.apiClientProps.serverId);
@@ -416,6 +487,25 @@ export const controller: GeneralController = {
}), }),
); );
}, },
getImageRequest(args) {
const server = getServerById(args.apiClientProps.serverId);
if (!server) {
return null;
}
return (
apiController(
'getImageRequest',
server.type,
)?.(
addContext({
...args,
apiClientProps: { ...args.apiClientProps, server },
}),
) || null
);
},
getImageUrl(args) { getImageUrl(args) {
const server = getServerById(args.apiClientProps.serverId); const server = getServerById(args.apiClientProps.serverId);
@@ -672,7 +762,9 @@ export const controller: GeneralController = {
const server = getServerById(args.apiClientProps.serverId); const server = getServerById(args.apiClientProps.serverId);
if (!server) { if (!server) {
return ''; throw new Error(
`${i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' })}: getStreamUrl`,
);
} }
return apiController( return apiController(
@@ -840,6 +932,20 @@ export const controller: GeneralController = {
}), }),
); );
}, },
setPlaylistSongs: function (args: SetPlaylistSongsArgs): Promise<SetPlaylistSongsResponse> {
const server = getServerById(args.apiClientProps.serverId);
if (!server) {
throw new Error(
`${i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' })}: setPlaylistSongs`,
);
}
return apiController(
'setPlaylistSongs',
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
setRating(args) { setRating(args) {
const server = getServerById(args.apiClientProps.serverId); const server = getServerById(args.apiClientProps.serverId);
@@ -896,4 +1002,46 @@ export const controller: GeneralController = {
server.type, server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } })); )?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
}, },
uploadArtistImage(args) {
const server = getServerById(args.apiClientProps.serverId);
if (!server) {
throw new Error(
`${i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' })}: uploadArtistImage`,
);
}
return apiController(
'uploadArtistImage',
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
uploadInternetRadioStationImage(args) {
const server = getServerById(args.apiClientProps.serverId);
if (!server) {
throw new Error(
`${i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' })}: uploadInternetRadioStationImage`,
);
}
return apiController(
'uploadInternetRadioStationImage',
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
uploadPlaylistImage(args) {
const server = getServerById(args.apiClientProps.serverId);
if (!server) {
throw new Error(
`${i18n.t('error.apiRouteError', { postProcess: 'sentenceCase' })}: uploadPlaylistImage`,
);
}
return apiController(
'uploadPlaylistImage',
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
}; };
+162 -83
View File
@@ -4,7 +4,7 @@ import filter from 'lodash/filter';
import orderBy from 'lodash/orderBy'; import orderBy from 'lodash/orderBy';
import { z } from 'zod'; import { z } from 'zod';
import { jfApiClient } from '/@/renderer/api/jellyfin/jellyfin-api'; import { createAuthHeader, jfApiClient } from '/@/renderer/api/jellyfin/jellyfin-api';
import { useRadioStore } from '/@/renderer/features/radio/store/radio-store'; import { useRadioStore } from '/@/renderer/features/radio/store/radio-store';
import { getServerUrl } from '/@/renderer/utils/normalize-server-url'; import { getServerUrl } from '/@/renderer/utils/normalize-server-url';
import { jfNormalize } from '/@/shared/api/jellyfin/jellyfin-normalize'; import { jfNormalize } from '/@/shared/api/jellyfin/jellyfin-normalize';
@@ -15,10 +15,13 @@ import {
albumListSortMap, albumListSortMap,
Folder, Folder,
genreListSortMap, genreListSortMap,
ImageArgs,
ImageRequest,
InternalControllerEndpoint, InternalControllerEndpoint,
LibraryItem, LibraryItem,
Played, Played,
playlistListSortMap, playlistListSortMap,
ReplaceApiClientProps,
ServerType, ServerType,
Song, Song,
SongListSort, SongListSort,
@@ -29,6 +32,33 @@ import {
} from '/@/shared/types/domain-types'; } from '/@/shared/types/domain-types';
import { ServerFeature } from '/@/shared/types/features-types'; import { ServerFeature } from '/@/shared/types/features-types';
const getJellyfinImageRequest = ({
apiClientProps: { server },
baseUrl,
query,
}: ReplaceApiClientProps<ImageArgs>): ImageRequest | null => {
const { id, size } = query;
const imageSize = size;
if (!server) {
return null;
}
const url = baseUrl || getServerUrl(server);
if (!url) {
return null;
}
return {
cacheKey: ['jellyfin', server.id, baseUrl || '', id, imageSize || ''].join(':'),
headers: server.credential
? { Authorization: createAuthHeader().concat(`, Token="${server.credential}"`) }
: { Authorization: createAuthHeader() },
url: `${url}/Items/${id}/Images/Primary?quality=96${imageSize ? `&width=${imageSize}` : ''}`,
};
};
const formatCommaDelimitedString = (value: string[]) => { const formatCommaDelimitedString = (value: string[]) => {
return value.join(','); return value.join(',');
}; };
@@ -54,15 +84,38 @@ const VERSION_INFO: VersionInfo = [
]; ];
const JF_FIELDS = { const JF_FIELDS = {
ALBUM_ARTIST_DETAIL: 'Genres, Overview, SortName, ProviderIds', ALBUM_ARTIST_DETAIL: ['Genres', 'Overview', 'SortName', 'ProviderIds'],
ALBUM_ARTIST_LIST: 'Genres, DateCreated, ExternalUrls, Overview, SortName, ProviderIds', ALBUM_ARTIST_LIST: [
ALBUM_DETAIL: 'Genres, DateCreated, ChildCount, People, Tags, ProviderIds', 'Genres',
ALBUM_LIST: 'People, Tags, Studios, SortName, UserData, ProviderIds, ChildCount', 'DateCreated',
FOLDER: 'Genres, DateCreated, MediaSources, UserData, ParentId', 'ExternalUrls',
GENRE: 'ItemCounts', 'Overview',
PLAYLIST_DETAIL: 'Genres, DateCreated, MediaSources, ChildCount, ParentId, SortName', 'SortName',
PLAYLIST_LIST: 'ChildCount, Genres, DateCreated, ParentId, Overview', 'ProviderIds',
SONG: 'Genres, DateCreated, MediaSources, ParentId, People, Tags, SortName, UserData, ProviderIds', ],
ALBUM_DETAIL: ['Genres', 'DateCreated', 'ChildCount', 'People', 'Tags', 'ProviderIds'],
ALBUM_LIST: ['People', 'Tags', 'Studios', 'SortName', 'ProviderIds', 'ChildCount'],
FOLDER: ['Genres', 'DateCreated', 'MediaSources', 'ParentId'],
GENRE: ['ItemCounts'],
PLAYLIST_DETAIL: [
'Genres',
'DateCreated',
'MediaSources',
'ChildCount',
'ParentId',
'SortName',
],
PLAYLIST_LIST: ['ChildCount', 'Genres', 'DateCreated', 'ParentId', 'Overview'],
SONG: [
'Genres',
'DateCreated',
'MediaSources',
'ParentId',
'People',
'Tags',
'SortName',
'ProviderIds',
],
} as const; } as const;
export const JellyfinController: InternalControllerEndpoint = { export const JellyfinController: InternalControllerEndpoint = {
@@ -235,34 +288,54 @@ export const JellyfinController: InternalControllerEndpoint = {
throw new Error('No userId found'); throw new Error('No userId found');
} }
const [res, similarArtistsRes] = await Promise.all([ const res = await jfApiClient(apiClientProps).getAlbumArtistDetail({
jfApiClient(apiClientProps).getAlbumArtistDetail({ params: {
params: { id: query.id,
id: query.id, userId: apiClientProps.server?.userId,
userId: apiClientProps.server?.userId, },
}, query: {
query: { Fields: ['Genres', 'Overview', 'SortName'],
Fields: JF_FIELDS.ALBUM_ARTIST_DETAIL, },
}, });
}),
jfApiClient(apiClientProps).getSimilarArtistList({
params: {
id: query.id,
},
query: {
Limit: 10,
},
}),
]);
if (res.status !== 200 || similarArtistsRes.status !== 200) { if (res.status !== 200) {
throw new Error('Failed to get album artist detail'); throw new Error('Failed to get album artist detail');
} }
return jfNormalize.albumArtist( return jfNormalize.albumArtist(res.body, apiClientProps.server);
{ ...res.body, similarArtists: similarArtistsRes.body }, },
apiClientProps.server, getAlbumArtistInfo: async (args) => {
const { apiClientProps, query } = args;
const similarArtistsRes = await jfApiClient(apiClientProps).getSimilarArtistList({
params: {
id: query.id,
},
query: {
Limit: query.limit ?? 10,
},
});
if (similarArtistsRes.status !== 200) {
return null;
}
const items = similarArtistsRes.body?.Items?.filter(
(entry) => entry.Name !== 'Various Artists',
); );
const similarArtists =
items?.map((entry) => ({
id: entry.Id,
imageId: entry.ImageTags?.Primary ? entry.Id : null,
imageUrl: null,
name: entry.Name,
userFavorite: entry.UserData?.IsFavorite || false,
userRating: null,
})) ?? null;
return {
similarArtists,
};
}, },
getAlbumArtistList: async (args) => { getAlbumArtistList: async (args) => {
const { apiClientProps, query } = args; const { apiClientProps, query } = args;
@@ -271,6 +344,7 @@ export const JellyfinController: InternalControllerEndpoint = {
query: { query: {
Fields: JF_FIELDS.ALBUM_ARTIST_LIST, Fields: JF_FIELDS.ALBUM_ARTIST_LIST,
ImageTypeLimit: 1, ImageTypeLimit: 1,
IsFavorite: query.favorite,
Limit: query.limit, Limit: query.limit,
ParentId: getLibraryId(query.musicFolderId), ParentId: getLibraryId(query.musicFolderId),
Recursive: true, Recursive: true,
@@ -335,6 +409,8 @@ export const JellyfinController: InternalControllerEndpoint = {
return jfNormalize.album( return jfNormalize.album(
{ ...res.body, Songs: songsRes.body.Items }, { ...res.body, Songs: songsRes.body.Items },
apiClientProps.server, apiClientProps.server,
args.context?.pathReplace,
args.context?.pathReplaceWith,
); );
}, },
getAlbumList: async (args) => { getAlbumList: async (args) => {
@@ -410,6 +486,34 @@ export const JellyfinController: InternalControllerEndpoint = {
apiClientProps, apiClientProps,
query: { ...query, limit: 1, startIndex: 0 }, query: { ...query, limit: 1, startIndex: 0 },
}).then((result) => result!.totalRecordCount!), }).then((result) => result!.totalRecordCount!),
getAlbumRadio: async (args) => {
const { apiClientProps, query } = args;
// For Jellyfin, use instant mix for album radio
const res = await jfApiClient(apiClientProps).getInstantMix({
params: {
itemId: query.albumId,
},
query: {
Fields: JF_FIELDS.SONG,
Limit: query.count,
UserId: apiClientProps.server?.userId || undefined,
},
});
if (res.status !== 200) {
throw new Error('Failed to get album radio songs');
}
return res.body.Items.map((song) =>
jfNormalize.song(
song,
apiClientProps.server,
args.context?.pathReplace,
args.context?.pathReplaceWith,
),
);
},
getArtistList: async (args) => { getArtistList: async (args) => {
const { apiClientProps, query } = args; const { apiClientProps, query } = args;
@@ -478,7 +582,8 @@ export const JellyfinController: InternalControllerEndpoint = {
return `${apiClientProps.server?.url}/items/${query.id}/download?apiKey=${apiClientProps.server?.credential}`; return `${apiClientProps.server?.url}/items/${query.id}/download?apiKey=${apiClientProps.server?.credential}`;
}, },
getFolder: async ({ apiClientProps, query }) => { getFolder: async (args) => {
const { apiClientProps, query } = args;
const userId = apiClientProps.server?.userId; const userId = apiClientProps.server?.userId;
if (!userId) throw new Error('No userId found'); if (!userId) throw new Error('No userId found');
@@ -640,6 +745,8 @@ export const JellyfinController: InternalControllerEndpoint = {
jfNormalize.song( jfNormalize.song(
item as unknown as z.infer<typeof jfType._response.song>, item as unknown as z.infer<typeof jfType._response.song>,
apiClientProps.server, apiClientProps.server,
args.context?.pathReplace,
args.context?.pathReplaceWith,
), ),
); );
@@ -717,23 +824,8 @@ export const JellyfinController: InternalControllerEndpoint = {
totalRecordCount: res.body?.TotalRecordCount || 0, totalRecordCount: res.body?.TotalRecordCount || 0,
}; };
}, },
getImageUrl: ({ apiClientProps: { server }, baseUrl, query }) => { getImageRequest: getJellyfinImageRequest,
const { id, size } = query; getImageUrl: (args) => getJellyfinImageRequest(args)?.url || null,
const imageSize = size;
const url = baseUrl || getServerUrl(server);
if (!url) {
return null;
}
// For Jellyfin, we construct the URL pattern
// The server will return a 404 or placeholder if no image exists
const imageUrl = `${url}/Items/${id}/Images/Primary?quality=96${imageSize ? `&width=${imageSize}` : ''}`;
// For songs, we might want to fall back to album art, but we don't have albumId here
// The caller can handle this if needed
return imageUrl;
},
getInternetRadioStations: async (args) => { getInternetRadioStations: async (args) => {
const { apiClientProps } = args; const { apiClientProps } = args;
@@ -1196,7 +1288,7 @@ export const JellyfinController: InternalControllerEndpoint = {
apiClientProps, apiClientProps,
query: { ...query, limit: 1, startIndex: 0 }, query: { ...query, limit: 1, startIndex: 0 },
}).then((result) => result!.totalRecordCount!), }).then((result) => result!.totalRecordCount!),
getStreamUrl: ({ apiClientProps: { server }, query }) => { getStreamUrl: async ({ apiClientProps: { server }, query }) => {
const { bitrate, format, id, transcode } = query; const { bitrate, format, id, transcode } = query;
const deviceId = ''; const deviceId = '';
@@ -1682,6 +1774,24 @@ export const JellyfinController: InternalControllerEndpoint = {
), ),
}; };
}, },
setPlaylistSongs: async (args) => {
const { apiClientProps, body } = args;
const res = await jfApiClient(apiClientProps).updatePlaylist({
body: {
Ids: body.songIds,
},
params: {
id: body.id,
},
});
if (res.status !== 204) {
throw new Error('Failed to update playlist songs');
}
return null;
},
updateInternetRadioStation: async (args) => { updateInternetRadioStation: async (args) => {
const { apiClientProps, body, query } = args; const { apiClientProps, body, query } = args;
@@ -1711,14 +1821,8 @@ export const JellyfinController: InternalControllerEndpoint = {
const res = await jfApiClient(apiClientProps).updatePlaylist({ const res = await jfApiClient(apiClientProps).updatePlaylist({
body: { body: {
Genres: body.genres?.map((item) => ({ Id: item.id, Name: item.name })) || [],
IsPublic: body.public, IsPublic: body.public,
MediaType: 'Audio',
Name: body.name, Name: body.name,
PremiereDate: null,
ProviderIds: {},
Tags: [],
UserId: apiClientProps.server?.userId, // Required
}, },
params: { params: {
id: query.id, id: query.id,
@@ -1733,31 +1837,6 @@ export const JellyfinController: InternalControllerEndpoint = {
}, },
}; };
// const getArtistList = async (args: ArtistListArgs): Promise<AlbumArtistListResponse> => {
// const { query, apiClientProps } = args;
// const res = await jfApiClient(apiClientProps).getAlbumArtistList({
// query: {
// Limit: query.limit,
// ParentId: query.musicFolderId,
// Recursive: true,
// SortBy: artistListSortMap.jellyfin[query.sortBy] || 'SortName,Name',
// SortOrder: sortOrderMap.jellyfin[query.sortOrder],
// StartIndex: query.startIndex,
// },
// });
// if (res.status !== 200) {
// throw new Error('Failed to get artist list');
// }
// return {
// items: res.body.Items.map((item) => jfNormalize.albumArtist(item, apiClientProps.server)),
// startIndex: query.startIndex,
// totalRecordCount: res.body.TotalRecordCount,
// };
// };
function getLibraryId(musicFolderId?: string | string[]) { function getLibraryId(musicFolderId?: string | string[]) {
return Array.isArray(musicFolderId) ? musicFolderId[0] : musicFolderId; return Array.isArray(musicFolderId) ? musicFolderId[0] : musicFolderId;
} }
@@ -46,6 +46,33 @@ export const contract = c.router({
500: resultWithHeaders(ndType._response.error), 500: resultWithHeaders(ndType._response.error),
}, },
}, },
deleteArtistImage: {
body: null,
method: 'DELETE',
path: 'artist/:id/image',
responses: {
200: resultWithHeaders(ndType._response.deleteArtistImage),
500: resultWithHeaders(ndType._response.error),
},
},
deleteInternetRadioStation: {
body: null,
method: 'DELETE',
path: 'radio/:id',
responses: {
200: resultWithHeaders(ndType._response.deleteInternetRadioStation),
500: resultWithHeaders(ndType._response.error),
},
},
deleteInternetRadioStationImage: {
body: null,
method: 'DELETE',
path: 'radio/:id/image',
responses: {
200: resultWithHeaders(ndType._response.deleteInternetRadioStationImage),
500: resultWithHeaders(ndType._response.error),
},
},
deletePlaylist: { deletePlaylist: {
body: null, body: null,
method: 'DELETE', method: 'DELETE',
@@ -55,6 +82,15 @@ export const contract = c.router({
500: resultWithHeaders(ndType._response.error), 500: resultWithHeaders(ndType._response.error),
}, },
}, },
deletePlaylistImage: {
body: null,
method: 'DELETE',
path: 'playlist/:id/image',
responses: {
200: resultWithHeaders(ndType._response.deletePlaylistImage),
500: resultWithHeaders(ndType._response.error),
},
},
getAlbumArtistDetail: { getAlbumArtistDetail: {
method: 'GET', method: 'GET',
path: 'artist/:id', path: 'artist/:id',
@@ -132,6 +168,15 @@ export const contract = c.router({
500: resultWithHeaders(ndType._response.error), 500: resultWithHeaders(ndType._response.error),
}, },
}, },
getRadioList: {
method: 'GET',
path: 'radio',
query: ndType._parameters.radioList,
responses: {
200: resultWithHeaders(ndType._response.radioList),
500: resultWithHeaders(ndType._response.error),
},
},
getSongDetail: { getSongDetail: {
method: 'GET', method: 'GET',
path: 'song/:id', path: 'song/:id',
@@ -205,6 +250,15 @@ export const contract = c.router({
500: resultWithHeaders(ndType._response.error), 500: resultWithHeaders(ndType._response.error),
}, },
}, },
updateInternetRadioStation: {
body: ndType._parameters.updateInternetRadioStation,
method: 'PUT',
path: 'radio/:id',
responses: {
200: resultWithHeaders(ndType._response.updateInternetRadioStation),
500: resultWithHeaders(ndType._response.error),
},
},
updatePlaylist: { updatePlaylist: {
body: ndType._parameters.updatePlaylist, body: ndType._parameters.updatePlaylist,
method: 'PUT', method: 'PUT',
@@ -214,6 +268,33 @@ export const contract = c.router({
500: resultWithHeaders(ndType._response.error), 500: resultWithHeaders(ndType._response.error),
}, },
}, },
uploadArtistImage: {
body: ndType._parameters.uploadArtistImage,
method: 'POST',
path: 'artist/:id/image',
responses: {
200: resultWithHeaders(ndType._response.uploadArtistImage),
500: resultWithHeaders(ndType._response.error),
},
},
uploadInternetRadioStationImage: {
body: ndType._parameters.uploadInternetRadioStationImage,
method: 'POST',
path: 'radio/:id/image',
responses: {
200: resultWithHeaders(ndType._response.uploadInternetRadioStationImage),
500: resultWithHeaders(ndType._response.error),
},
},
uploadPlaylistImage: {
body: ndType._parameters.uploadPlaylistImage,
method: 'POST',
path: 'playlist/:id/image',
responses: {
200: resultWithHeaders(ndType._response.uploadPlaylistImage),
500: resultWithHeaders(ndType._response.error),
},
},
}); });
const axiosClient = axios.create({}); const axiosClient = axios.create({});
@@ -1,3 +1,4 @@
import axios from 'axios';
import { set } from 'idb-keyval'; import { set } from 'idb-keyval';
import orderBy from 'lodash/orderBy'; import orderBy from 'lodash/orderBy';
@@ -5,13 +6,19 @@ import { ndApiClient } from '/@/renderer/api/navidrome/navidrome-api';
import { ssApiClient } from '/@/renderer/api/subsonic/subsonic-api'; import { ssApiClient } from '/@/renderer/api/subsonic/subsonic-api';
import { SubsonicController } from '/@/renderer/api/subsonic/subsonic-controller'; import { SubsonicController } from '/@/renderer/api/subsonic/subsonic-controller';
import { ndNormalize } from '/@/shared/api/navidrome/navidrome-normalize'; import { ndNormalize } from '/@/shared/api/navidrome/navidrome-normalize';
import { NDSongListSort } from '/@/shared/api/navidrome/navidrome-types'; import { NDRadioListSort, NDSongListSort } from '/@/shared/api/navidrome/navidrome-types';
import { ssNormalize } from '/@/shared/api/subsonic/subsonic-normalize'; import { ssNormalize } from '/@/shared/api/subsonic/subsonic-normalize';
import { getFeatures, hasFeature, hasFeatureWithVersion, VersionInfo } from '/@/shared/api/utils'; import { getFeatures, hasFeature, hasFeatureWithVersion, VersionInfo } from '/@/shared/api/utils';
import { import {
albumArtistListSortMap, albumArtistListSortMap,
albumListSortMap, albumListSortMap,
AuthenticationResponse, AuthenticationResponse,
DeleteArtistImageArgs,
DeleteArtistImageResponse,
DeleteInternetRadioStationImageArgs,
DeleteInternetRadioStationImageResponse,
DeletePlaylistImageArgs,
DeletePlaylistImageResponse,
genreListSortMap, genreListSortMap,
InternalControllerEndpoint, InternalControllerEndpoint,
playlistListSortMap, playlistListSortMap,
@@ -23,6 +30,12 @@ import {
SortOrder, SortOrder,
sortOrderMap, sortOrderMap,
tagListSortMap, tagListSortMap,
UploadArtistImageArgs,
UploadArtistImageResponse,
UploadInternetRadioStationImageArgs,
UploadInternetRadioStationImageResponse,
UploadPlaylistImageArgs,
UploadPlaylistImageResponse,
userListSortMap, userListSortMap,
} from '/@/shared/types/domain-types'; } from '/@/shared/types/domain-types';
import { ServerFeature } from '/@/shared/types/features-types'; import { ServerFeature } from '/@/shared/types/features-types';
@@ -30,6 +43,15 @@ import { ServerFeature } from '/@/shared/types/features-types';
const VERSION_INFO: VersionInfo = [ const VERSION_INFO: VersionInfo = [
// Why 2? Subsonic controller will return 1 for its own implementation // Why 2? Subsonic controller will return 1 for its own implementation
// Use 2 to denote that Navidrome's own API has a different endpoint // Use 2 to denote that Navidrome's own API has a different endpoint
[
'0.61.0',
{
[ServerFeature.ARTIST_IMAGE_UPLOAD]: [1],
[ServerFeature.INTERNET_RADIO_IMAGE_UPLOAD]: [1],
[ServerFeature.PLAYLIST_IMAGE_UPLOAD]: [1],
},
],
['0.60.4', { [ServerFeature.TRACK_YES_NO_RATING_FILTER]: [1] }],
['0.57.0', { [ServerFeature.SERVER_PLAY_QUEUE]: [2] }], ['0.57.0', { [ServerFeature.SERVER_PLAY_QUEUE]: [2] }],
['0.56.0', { [ServerFeature.TRACK_ALBUM_ARTIST_SEARCH]: [1] }], ['0.56.0', { [ServerFeature.TRACK_ALBUM_ARTIST_SEARCH]: [1] }],
['0.55.0', { [ServerFeature.BFR]: [1], [ServerFeature.TAGS]: [1] }], ['0.55.0', { [ServerFeature.BFR]: [1], [ServerFeature.TAGS]: [1] }],
@@ -169,8 +191,54 @@ export const NavidromeController: InternalControllerEndpoint = {
id: res.body.data.id, id: res.body.data.id,
}; };
}, },
deleteArtistImage: async (args: DeleteArtistImageArgs): Promise<DeleteArtistImageResponse> => {
const { apiClientProps, query } = args;
const res = await ndApiClient(apiClientProps as any).deleteArtistImage({
params: {
id: query.id,
},
});
if (res.status !== 200) {
throw new Error('Failed to delete artist image');
}
return res.body.data.status === 'ok';
},
deleteFavorite: SubsonicController.deleteFavorite, deleteFavorite: SubsonicController.deleteFavorite,
deleteInternetRadioStation: SubsonicController.deleteInternetRadioStation, deleteInternetRadioStation: async (args) => {
const { apiClientProps, query } = args;
const res = await ndApiClient(apiClientProps).deleteInternetRadioStation({
params: {
id: query.id,
},
});
if (res.status !== 200) {
throw new Error('Failed to delete internet radio station');
}
return null;
},
deleteInternetRadioStationImage: async (
args: DeleteInternetRadioStationImageArgs,
): Promise<DeleteInternetRadioStationImageResponse> => {
const { apiClientProps, query } = args;
const res = await ndApiClient(apiClientProps as any).deleteInternetRadioStationImage({
params: {
id: query.id,
},
});
if (res.status !== 200) {
throw new Error('Failed to delete internet radio station image');
}
return res.body.data.status === 'ok';
},
deletePlaylist: async (args) => { deletePlaylist: async (args) => {
const { apiClientProps, query } = args; const { apiClientProps, query } = args;
@@ -186,22 +254,31 @@ export const NavidromeController: InternalControllerEndpoint = {
return null; return null;
}, },
deletePlaylistImage: async (
args: DeletePlaylistImageArgs,
): Promise<DeletePlaylistImageResponse> => {
const { apiClientProps, query } = args;
const res = await ndApiClient(apiClientProps as any).deletePlaylistImage({
params: {
id: query.id,
},
});
if (res.status !== 200) {
throw new Error('Failed to delete playlist image');
}
return res.body.data.status === 'ok';
},
getAlbumArtistDetail: async (args) => { getAlbumArtistDetail: async (args) => {
const { apiClientProps, query } = args; const { apiClientProps, query } = args;
const [res, artistInfoRes] = await Promise.all([ const res = await ndApiClient(apiClientProps).getAlbumArtistDetail({
ndApiClient(apiClientProps).getAlbumArtistDetail({ params: {
params: { id: query.id,
id: query.id, },
}, });
}),
ssApiClient(apiClientProps).getArtistInfo({
query: {
count: 10,
id: query.id,
},
}),
]);
if (res.status !== 200) { if (res.status !== 200) {
throw new Error('Failed to get album artist detail'); throw new Error('Failed to get album artist detail');
@@ -211,22 +288,42 @@ export const NavidromeController: InternalControllerEndpoint = {
throw new Error('Server is required'); throw new Error('Server is required');
} }
// Prefer images from getArtistInfo first (which should be proxied) return ndNormalize.albumArtist(res.body.data, apiClientProps.server);
// Prioritize large > medium > small },
return ndNormalize.albumArtist( getAlbumArtistInfo: async (args) => {
{ const { apiClientProps, query } = args;
...res.body.data,
...(artistInfoRes.status === 200 && { const artistInfoRes = await ssApiClient(apiClientProps).getArtistInfo({
largeImageUrl: query: {
artistInfoRes.body.artistInfo.largeImageUrl || id: query.id,
artistInfoRes.body.artistInfo.mediumImageUrl || ...(query.limit != null && { count: query.limit }),
artistInfoRes.body.artistInfo.smallImageUrl ||
res.body.data.largeImageUrl,
similarArtists: artistInfoRes.body.artistInfo.similarArtist,
}),
}, },
apiClientProps.server, });
);
if (artistInfoRes.status !== 200) {
return null;
}
const artistInfo = artistInfoRes.body.artistInfo;
const imageUrl =
artistInfo?.largeImageUrl ||
artistInfo?.mediumImageUrl ||
artistInfo?.smallImageUrl ||
null;
return {
biography: artistInfo?.biography || null,
imageUrl,
similarArtists:
artistInfo?.similarArtist?.map((artist) => ({
id: artist.id,
imageId: artist.id,
imageUrl: null,
name: artist.name,
userFavorite: Boolean(artist.starred) || false,
userRating: artist.userRating ?? null,
})) ?? null,
};
}, },
getAlbumArtistList: async (args) => { getAlbumArtistList: async (args) => {
const { apiClientProps, query } = args; const { apiClientProps, query } = args;
@@ -376,6 +473,37 @@ export const NavidromeController: InternalControllerEndpoint = {
apiClientProps, apiClientProps,
query: { ...query, limit: 1, startIndex: 0 }, query: { ...query, limit: 1, startIndex: 0 },
}).then((result) => result!.totalRecordCount!), }).then((result) => result!.totalRecordCount!),
getAlbumRadio: async (args) => {
const { apiClientProps, query } = args;
// Use getSimilarSongs API for album radio
const res = await ssApiClient({
...apiClientProps,
silent: true,
}).getSimilarSongs({
query: {
count: query.count,
id: query.albumId,
},
});
if (res.status !== 200) {
throw new Error('Failed to get album radio songs');
}
if (!res.body.similarSongs?.song) {
return [];
}
return res.body.similarSongs.song.map((song) =>
ssNormalize.song(
song,
apiClientProps.server,
args.context?.pathReplace,
args.context?.pathReplaceWith,
),
);
},
getArtistList: async (args) => { getArtistList: async (args) => {
const { apiClientProps, query } = args; const { apiClientProps, query } = args;
@@ -443,7 +571,12 @@ export const NavidromeController: InternalControllerEndpoint = {
} }
return res.body.similarSongs2.song.map((song) => return res.body.similarSongs2.song.map((song) =>
ssNormalize.song(song, apiClientProps.server), ssNormalize.song(
song,
apiClientProps.server,
args.context?.pathReplace,
args.context?.pathReplaceWith,
),
); );
}, },
getDownloadUrl: SubsonicController.getDownloadUrl, getDownloadUrl: SubsonicController.getDownloadUrl,
@@ -506,8 +639,26 @@ export const NavidromeController: InternalControllerEndpoint = {
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0), totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
}; };
}, },
getImageRequest: SubsonicController.getImageRequest,
getImageUrl: SubsonicController.getImageUrl, getImageUrl: SubsonicController.getImageUrl,
getInternetRadioStations: SubsonicController.getInternetRadioStations, getInternetRadioStations: async (args) => {
const { apiClientProps } = args;
const res = await ndApiClient(apiClientProps).getRadioList({
query: {
_end: -1,
_order: 'ASC',
_sort: NDRadioListSort.NAME,
_start: 0,
},
});
if (res.status !== 200) {
throw new Error('Failed to get internet radio stations');
}
return res.body.data.map((station) => ndNormalize.internetRadioStation(station));
},
getLyrics: SubsonicController.getLyrics, getLyrics: SubsonicController.getLyrics,
getMusicFolderList: SubsonicController.getMusicFolderList, getMusicFolderList: SubsonicController.getMusicFolderList,
getPlaylistDetail: async (args) => { getPlaylistDetail: async (args) => {
@@ -564,6 +715,7 @@ export const NavidromeController: InternalControllerEndpoint = {
query: { query: {
_end: -1, _end: -1,
_order: 'ASC', _order: 'ASC',
_sort: NDSongListSort.ID,
_start: 0, _start: 0,
...excludeMissing(apiClientProps.server), ...excludeMissing(apiClientProps.server),
}, },
@@ -596,7 +748,7 @@ export const NavidromeController: InternalControllerEndpoint = {
throw new Error('Failed to get play queue'); throw new Error('Failed to get play queue');
} }
const { changedBy, current, items, position, updatedAt } = res.body.data; const { changedBy, current, items = [], position, updatedAt } = res.body.data; // if there is no queue saved, items is undefined
const entries = items.map((song) => const entries = items.map((song) =>
ndNormalize.song( ndNormalize.song(
@@ -643,6 +795,7 @@ export const NavidromeController: InternalControllerEndpoint = {
...subsonicArgs.features, ...subsonicArgs.features,
...navidromeFeatures, ...navidromeFeatures,
publicPlaylist: [1], publicPlaylist: [1],
[ServerFeature.ALBUM_YES_NO_RATING_FILTER]: [1],
[ServerFeature.MUSIC_FOLDER_MULTISELECT]: [1], [ServerFeature.MUSIC_FOLDER_MULTISELECT]: [1],
}; };
@@ -680,7 +833,14 @@ export const NavidromeController: InternalControllerEndpoint = {
return ( return (
(res.body.similarSongs?.song || []) (res.body.similarSongs?.song || [])
.filter((song) => song.id !== query.songId) .filter((song) => song.id !== query.songId)
.map((song) => ssNormalize.song(song, apiClientProps.server)) || [] .map((song) =>
ssNormalize.song(
song,
apiClientProps.server,
args.context?.pathReplace,
args.context?.pathReplaceWith,
),
) || []
); );
}, },
getSongDetail: async (args) => { getSongDetail: async (args) => {
@@ -706,41 +866,77 @@ export const NavidromeController: InternalControllerEndpoint = {
getSongList: async (args) => { getSongList: async (args) => {
const { apiClientProps, query } = args; const { apiClientProps, query } = args;
const res = await ndApiClient(apiClientProps).getSongList({ const ALBUM_IDS_BATCH_SIZE = 500;
query: { const albumIds = query.albumIds;
_end: query.startIndex + (query.limit || -1), const shouldBatch = albumIds && albumIds.length > ALBUM_IDS_BATCH_SIZE;
_order: sortOrderMap.navidrome[query.sortOrder],
_sort: songListSortMap.navidrome[query.sortBy],
_start: query.startIndex,
album_id: query.albumIds,
genre_id: query.genreIds,
[getArtistSongKey(apiClientProps.server)]: query.artistIds ?? query.albumArtistIds,
library_id: getLibraryId(query.musicFolderId),
starred: query.favorite,
title: query.searchTerm,
year: query.maxYear || query.minYear,
...query._custom,
...excludeMissing(apiClientProps.server),
},
});
if (res.status !== 200) { const fetchAlbums = async (albumIdBatch: string[] | undefined) => {
throw new Error('Failed to get song list'); const res = await ndApiClient(apiClientProps).getSongList({
query: {
_end: query.startIndex + (query.limit || -1),
_order: sortOrderMap.navidrome[query.sortOrder],
_sort: songListSortMap.navidrome[query.sortBy],
_start: query.startIndex,
album_id: albumIdBatch ?? query.albumIds,
genre_id: query.genreIds,
[getArtistSongKey(apiClientProps.server)]:
query.artistIds ?? query.albumArtistIds,
...(hasFeature(
apiClientProps.server,
ServerFeature.TRACK_YES_NO_RATING_FILTER,
) && query.hasRating !== undefined
? { has_rating: query.hasRating }
: {}),
library_id: getLibraryId(query.musicFolderId),
starred: query.favorite,
title: query.searchTerm,
year: query.maxYear || query.minYear,
...query._custom,
...excludeMissing(apiClientProps.server),
},
});
if (res.status !== 200) {
throw new Error('Failed to get song list');
}
return {
items: res.body.data.map((song) =>
ndNormalize.song(
song,
apiClientProps.server,
args.context?.pathReplace,
args.context?.pathReplaceWith,
),
),
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
};
};
if (shouldBatch && albumIds) {
const batches: string[][] = [];
for (let i = 0; i < albumIds.length; i += ALBUM_IDS_BATCH_SIZE) {
batches.push(albumIds.slice(i, i + ALBUM_IDS_BATCH_SIZE));
}
const results = await Promise.all(batches.map((batch) => fetchAlbums(batch)));
return {
items: results.flatMap((r) => r.items),
startIndex: query?.startIndex ?? 0,
totalRecordCount: results.reduce((sum, r) => sum + r.totalRecordCount, 0),
};
} }
const albums = await fetchAlbums(undefined);
return { return {
items: res.body.data.map((song) => items: albums.items,
ndNormalize.song( startIndex: query?.startIndex ?? 0,
song, totalRecordCount: albums.totalRecordCount,
apiClientProps.server,
args.context?.pathReplace,
args.context?.pathReplaceWith,
),
),
startIndex: query?.startIndex || 0,
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
}; };
}, },
getSongListCount: async ({ apiClientProps, query }) => getSongListCount: async ({ apiClientProps, query }) =>
NavidromeController.getSongList({ NavidromeController.getSongList({
apiClientProps, apiClientProps,
@@ -843,6 +1039,7 @@ export const NavidromeController: InternalControllerEndpoint = {
const res = await NavidromeController.getSongList({ const res = await NavidromeController.getSongList({
apiClientProps, apiClientProps,
context: args.context,
query: { query: {
artistIds: [query.artistId], artistIds: [query.artistId],
sortBy: SongListSort.PLAY_COUNT, sortBy: SongListSort.PLAY_COUNT,
@@ -933,6 +1130,7 @@ export const NavidromeController: InternalControllerEndpoint = {
query: { query: {
_end: -1, _end: -1,
_order: 'ASC', _order: 'ASC',
_sort: NDSongListSort.ID,
_start: 0, _start: 0,
...excludeMissing(apiClientProps.server), ...excludeMissing(apiClientProps.server),
}, },
@@ -1043,6 +1241,7 @@ export const NavidromeController: InternalControllerEndpoint = {
}, },
scrobble: SubsonicController.scrobble, scrobble: SubsonicController.scrobble,
search: SubsonicController.search, search: SubsonicController.search,
setPlaylistSongs: SubsonicController.setPlaylistSongs,
setRating: SubsonicController.setRating, setRating: SubsonicController.setRating,
shareItem: async (args) => { shareItem: async (args) => {
const { apiClientProps, body } = args; const { apiClientProps, body } = args;
@@ -1065,7 +1264,26 @@ export const NavidromeController: InternalControllerEndpoint = {
id: res.body.data.id, id: res.body.data.id,
}; };
}, },
updateInternetRadioStation: SubsonicController.updateInternetRadioStation, updateInternetRadioStation: async (args) => {
const { apiClientProps, body, query } = args;
const res = await ndApiClient(apiClientProps).updateInternetRadioStation({
body: {
homePageUrl: body.homepageUrl ?? '',
name: body.name,
streamUrl: body.streamUrl,
},
params: {
id: query.id,
},
});
if (res.status !== 200) {
throw new Error('Failed to update internet radio station');
}
return null;
},
updatePlaylist: async (args) => { updatePlaylist: async (args) => {
const { apiClientProps, body, query } = args; const { apiClientProps, body, query } = args;
@@ -1090,4 +1308,110 @@ export const NavidromeController: InternalControllerEndpoint = {
return null; return null;
}, },
uploadArtistImage: async (args: UploadArtistImageArgs): Promise<UploadArtistImageResponse> => {
const { apiClientProps, body, query } = args;
const server = apiClientProps.server;
const serverUrl = server?.url?.replace(/\/$/, '');
if (!serverUrl) {
throw new Error('Server is required');
}
const form = new FormData();
const bytes = body.image as Uint8Array<ArrayBuffer>;
const fileLike =
typeof File !== 'undefined'
? new File([bytes], 'image', { type: 'application/octet-stream' })
: new Blob([bytes], { type: 'application/octet-stream' });
form.append('image', fileLike as any);
const res = await axios.post(`${serverUrl}/api/artist/${query.id}/image`, form, {
headers: {
'Content-Type': 'multipart/form-data',
...(server?.ndCredential && {
'x-nd-authorization': `Bearer ${server.ndCredential}`,
}),
},
signal: apiClientProps.signal,
});
if (res.status !== 200) {
throw new Error('Failed to upload artist image');
}
return res.data?.status === 'ok';
},
uploadInternetRadioStationImage: async (
args: UploadInternetRadioStationImageArgs,
): Promise<UploadInternetRadioStationImageResponse> => {
const { apiClientProps, body, query } = args;
const server = apiClientProps.server;
const serverUrl = server?.url?.replace(/\/$/, '');
if (!serverUrl) {
throw new Error('Server is required');
}
const form = new FormData();
const bytes = body.image as Uint8Array<ArrayBuffer>;
const fileLike =
typeof File !== 'undefined'
? new File([bytes], 'image', { type: 'application/octet-stream' })
: new Blob([bytes], { type: 'application/octet-stream' });
form.append('image', fileLike as any);
const res = await axios.post(`${serverUrl}/api/radio/${query.id}/image`, form, {
headers: {
'Content-Type': 'multipart/form-data',
...(server?.ndCredential && {
'x-nd-authorization': `Bearer ${server.ndCredential}`,
}),
},
signal: apiClientProps.signal,
});
if (res.status !== 200) {
throw new Error('Failed to upload internet radio station image');
}
return res.data?.status === 'ok';
},
uploadPlaylistImage: async (
args: UploadPlaylistImageArgs,
): Promise<UploadPlaylistImageResponse> => {
const { apiClientProps, body, query } = args;
const server = apiClientProps.server;
const serverUrl = server?.url?.replace(/\/$/, '');
if (!serverUrl) {
throw new Error('Server is required');
}
const form = new FormData();
const bytes = body.image as Uint8Array<ArrayBuffer>;
const fileLike =
typeof File !== 'undefined'
? new File([bytes], 'image', { type: 'application/octet-stream' })
: new Blob([bytes], { type: 'application/octet-stream' });
form.append('image', fileLike as any);
const res = await axios.post(`${serverUrl}/api/playlist/${query.id}/image`, form, {
headers: {
'Content-Type': 'multipart/form-data',
...(server?.ndCredential && {
'x-nd-authorization': `Bearer ${server.ndCredential}`,
}),
},
signal: apiClientProps.signal,
});
if (res.status !== 200) {
throw new Error('Failed to upload playlist image');
}
return res.data?.status === 'ok';
},
}; };

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